Changed the deprecated thumbnail_util APIs in msg-service
[platform/core/messaging/msg-service.git] / utils / MsgIpcSocket.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15 */
16
17 #include <sys/socket.h>
18 #include <sys/un.h>
19 #include <sys/ioctl.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22
23 #include <errno.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <glib.h>
27
28 #include "MsgDebug.h"
29 #include "MsgException.h"
30 #include "MsgIpcSocket.h"
31 #include "MsgUtilFile.h"
32
33 /*==================================================================================================
34                                      IMPLEMENTATION OF MsgIpcClientSocket - Member Functions
35 ==================================================================================================*/
36 MsgIpcClientSocket::MsgIpcClientSocket() : sockfd(-1), remotefd(-1), maxfd(-1)
37 {
38         FD_ZERO(&fds);
39 }
40
41
42 msg_error_t MsgIpcClientSocket::connect(const char* path)
43 {
44         MSG_BEGIN();
45
46         if (!path || strlen(path) > strlen(MSG_SOCKET_PATH)) {
47                 THROW(MsgException::IPC_ERROR, "path is null");
48         }
49
50         sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
51
52         if (sockfd < 0) {
53                 THROW(MsgException::IPC_ERROR, "socket not opened %s", g_strerror(errno));
54         }
55
56         struct sockaddr_un serverSA = {0, };
57         serverSA.sun_family = AF_UNIX;
58
59         memset(serverSA.sun_path, 0x00, sizeof(serverSA.sun_path));
60         strncpy(serverSA.sun_path, path, sizeof(serverSA.sun_path)-1);
61
62         int len = strlen(serverSA.sun_path) + sizeof(serverSA.sun_family);
63
64         if (::connect(sockfd, (struct sockaddr *)&serverSA, len) == CUSTOM_SOCKET_ERROR) {
65                 MSG_DEBUG("errno=[%d]", errno);
66                 if(errno == EACCES)
67                         THROW(MsgException::SECURITY_ERROR, "cannot connect server %s", g_strerror(errno));
68                 else
69                         THROW(MsgException::IPC_ERROR, "cannot connect server %s", g_strerror(errno));
70         }
71
72         /* add fd for select() */
73         addfd(sockfd);
74
75         if (!wait_for_reply()) {
76                 THROW(MsgException::IPC_ERROR, "wait_for_reply() error");
77         }
78
79         /* read remote fd for reg func */
80         char *rfd = NULL;
81         unique_ptr<char*, void(*)(char**)> wrap(&rfd, unique_ptr_deleter);
82         unsigned int rlen;
83
84         read(&rfd, &rlen);
85
86         if (rfd == NULL) {
87                 THROW(MsgException::IPC_ERROR, "rfd is NULL %s", g_strerror(errno));
88         }
89
90         memcpy(&remotefd, rfd, sizeof(rlen));
91
92         MSG_DEBUG("Connected: client fd [%d] <----> remote fd [%d]", sockfd, remotefd);
93
94         MSG_END();
95
96         return MSG_SUCCESS;
97 }
98
99
100 msg_error_t MsgIpcClientSocket::close()
101 {
102         if (sockfd < 0) {
103                 MSG_DEBUG("Client socket is not opened or already closed");
104                 return MSG_SUCCESS;
105         }
106
107         /* it means that client is going to close the connection.*/
108         int cmd = CLOSE_CONNECTION_BY_USER;
109         int len = sizeof(cmd);
110
111         char cmdbuf[len];
112         bzero(cmdbuf, len);
113         memcpy(cmdbuf, &cmd, len);
114
115         MSG_DEBUG("client socket [%d] will be closed", sockfd);
116         ::close(sockfd);
117         sockfd = CUSTOM_SOCKET_ERROR;
118
119         return MSG_SUCCESS;
120 }
121
122 void MsgIpcClientSocket::addfd(int fd)
123 {
124         MSG_DEBUG("%d added", fd);
125         FD_SET(fd, &fds);
126         if (fd > maxfd)
127                 maxfd = fd;
128 }
129
130 int MsgIpcClientSocket::writen(const char *buf, unsigned int len)
131 {
132         unsigned int nleft;
133         int nwrite;
134
135         nleft = len;
136         while (nleft > 0) {
137                 nwrite = ::write(sockfd, (const void*) buf, nleft);
138                 if (nwrite < 0) {
139                         MSG_FATAL("writen: sockfd [%d] error [%s]",  sockfd, g_strerror(errno));
140                         return nwrite;
141                 } else if (nwrite == 0) {
142                         break;
143                 }
144
145                 nleft -= nwrite;
146                 buf += nwrite;
147         }
148         return (len-nleft);
149 }
150
151 int MsgIpcClientSocket::write(const char* buf, unsigned int len)
152 {
153         if (sockfd < 0) {
154                 MSG_FATAL("sockfd is not opened [%d]", sockfd);
155                 return CUSTOM_SOCKET_ERROR;
156         }
157
158         if (!buf || len == 0) {
159                 MSG_FATAL("buf[%p]      and len[%d] MUST NOT NULL", buf, len);
160                 return CUSTOM_SOCKET_ERROR;
161         }
162
163         /* send the data size first */
164         int n = writen((const char*)&len, sizeof(len));
165         if (n != sizeof(len)) {
166                 MSG_FATAL("WARNING: write header_size[%d] not matched [%zu]", n, sizeof(len));
167                 return CUSTOM_SOCKET_ERROR;
168         }
169
170         /* send the data in subsequence */
171         n = writen(buf, len);
172         if ((unsigned int)n != len) {
173                 MSG_FATAL("WARNING: write data_size[%d] not matched [%d]", n, len);
174                 return CUSTOM_SOCKET_ERROR;
175         }
176
177         return len;
178 }
179
180 int MsgIpcClientSocket::readn(char *buf, unsigned int len)
181 {
182         unsigned int nleft;
183         int nread;
184         char t_buf[len];
185
186         nleft = len;
187         while (nleft > 0) {
188                 memset(t_buf, 0x00, len);
189                 nread = ::read(sockfd, t_buf, nleft);
190                 if (nread < 0) {
191                         MSG_FATAL("WARNING read value %d: %s", nread, g_strerror(errno));
192                         return nread;
193                 } else if (nread == 0) {
194                         break;
195                 }
196
197                 if (nleft >= (unsigned int)nread)
198                         nleft -= nread;
199                 else
200                         return -1;
201
202                 memcpy(buf, t_buf, nread);
203                 buf += nread;
204         }
205
206         return (len-nleft);
207 }
208
209 bool MsgIpcClientSocket::wait_for_reply()
210 {
211         int err = -1;
212         fd_set fds;
213         struct timeval tv;
214
215         if (sockfd < 0) {
216                 MSG_FATAL("Invalid file description : [%d]", sockfd);
217                 return false;
218         }
219
220         FD_ZERO(&fds);
221         FD_SET(sockfd, &fds);
222
223         tv.tv_sec  = 5; /* should be tuned */
224         tv.tv_usec = 0;
225
226         MSG_DEBUG("wait for response [%d]", sockfd);
227         err = select(sockfd + 1, &fds, NULL, NULL, &tv);
228         if (err == -1) {
229                 MSG_FATAL("select error[%d] fd[%d]", errno, sockfd);
230                 return false;
231         } else if (err == 0) {
232                 MSG_FATAL("select timeout fd[%d]", sockfd);
233                 return false;
234         }
235
236         if (FD_ISSET(sockfd, &fds)) return true;
237
238         return false;
239 }
240
241
242 /* what if the buf is shorter than data? */
243 int MsgIpcClientSocket::read(char** buf, unsigned int* len)
244 {
245         if (sockfd < 0) {
246                 MSG_FATAL("socket is not opened [%d]", sockfd);
247                 return CUSTOM_SOCKET_ERROR;
248         }
249
250         if (!buf || !len) {
251                 MSG_FATAL("rbuf and rlen MUST NOT NULL");
252                 return CUSTOM_SOCKET_ERROR;
253         }
254
255         *len = 0;
256         char clen[sizeof(int)] = {0};
257
258         /* read the data size first */
259         int n = readn(clen, sizeof(int));
260         memcpy(len, clen, sizeof(int));
261
262         if (n == CLOSE_CONNECTION_BY_SIGNAL) { /* if msgfw gets down, it signals to all IPC clients */
263                 MSG_FATAL("sockfd [%d] CLOSE_CONNECTION_BY_SIGNAL", sockfd);
264                 return n;
265         } else if (n != sizeof(int)) {
266                 MSG_FATAL("WARNING: read header_size[%d] not matched [%zu]", n, sizeof(int));
267                 return CUSTOM_SOCKET_ERROR;
268         }
269
270         /*  read the data in subsequence */
271         unsigned int ulen = (unsigned int)*len;
272         *buf = new char[ulen];
273         bzero(*buf, ulen);
274         n = readn(*buf, ulen);
275
276         if ((unsigned int)n !=  ulen) {
277                 MSG_FATAL("WARNING: read data_size [%d] not matched [%d]", n, ulen);
278                 return CUSTOM_SOCKET_ERROR;
279         }
280
281         return n;
282 }
283
284
285 /*==================================================================================================
286                                      IMPLEMENTATION OF MsgIpcServerSocket - Member Functions
287 ==================================================================================================*/
288 MsgIpcServerSocket::MsgIpcServerSocket() : sockfd(-1), maxfd(-1)
289 {
290         FD_ZERO(&fds);
291 }
292
293 void MsgIpcServerSocket::addfd(int fd)
294 {
295         MSG_DEBUG("%d added", fd);
296         FD_SET(fd, &fds);
297
298         std::map<int, int>::iterator it = mapFds.find(fd);
299         if (it != mapFds.end())
300                 MSG_FATAL("Duplicate FD %d", fd);
301         else
302                 mapFds[fd] = fd;
303
304         if (fd > maxfd)
305                 maxfd = fd;
306 }
307
308 msg_error_t MsgIpcServerSocket::open(const char* path)
309 {
310         MSG_BEGIN();
311
312         if (!path || strlen(path) > strlen(MSG_SOCKET_PATH)) {
313                 MSG_FATAL("path is null");
314                 return MSG_ERR_INVALID_PARAMETER;
315         }
316
317         if (sockfd != CUSTOM_SOCKET_ERROR) {
318                 MSG_FATAL("WARNING: server_socket already opened %d at %p", sockfd,  &sockfd);
319                 return MSG_ERR_UNKNOWN;
320         }
321
322         sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
323
324         if (sockfd == CUSTOM_SOCKET_ERROR) {
325                 MSG_FATAL("socket failed: %s", g_strerror(errno));
326                 return MSG_ERR_UNKNOWN;
327         }
328
329         MSG_DEBUG("server_socket(%p) opened : %d", &sockfd, sockfd);
330
331         struct sockaddr_un local = {0, };
332
333         local.sun_family = AF_UNIX;
334         memset(local.sun_path, 0x00, sizeof(local.sun_path));
335         strncpy(local.sun_path, path, sizeof(local.sun_path)-1);
336
337         unlink(local.sun_path);
338
339         int len = strlen(local.sun_path) + sizeof(local.sun_family);
340
341         if (bind(sockfd, (struct sockaddr *)&local, len) == CUSTOM_SOCKET_ERROR) {
342                 MSG_FATAL("bind: %s", g_strerror(errno));
343                 return MSG_ERR_UNKNOWN;
344         }
345
346         /**
347          * determine permission of socket file
348          *
349          *  - S_IRWXU : for user, allow read and write and execute
350          *  - S_IRWXG : for group, allow read and write and execute
351          *  - S_IRWXO : for other, allow read and write and execute
352          *
353          *  - S_IRUSR, S_IWUSR, S_IXUSR : for user, allow only read, write, execute respectively
354          *  - S_IRGRP, S_IWGRP, S_IXGRP : for group, allow only read, write, execute respectively
355          *  - S_IROTH, S_IWOTH, S_IXOTH : for other, allow only read, write, execute respectively
356          */
357         mode_t sock_mode = (S_IRWXU | S_IRWXG | S_IRWXO); /* has 777 permission */
358
359         if (chmod(path, sock_mode) == CUSTOM_SOCKET_ERROR) {
360                 MSG_FATAL("chmod: %s", g_strerror(errno));
361                 return MSG_ERR_UNKNOWN;
362         }
363         if (listen(sockfd, CUSTOM_SOCKET_BACKLOG) == CUSTOM_SOCKET_ERROR) {
364                 MSG_FATAL("listen: %s", g_strerror(errno));
365                 return MSG_ERR_UNKNOWN;
366         }
367
368         addfd(sockfd);
369
370         MSG_END();
371
372         return MSG_SUCCESS;
373 }
374
375 msg_error_t MsgIpcServerSocket::accept()
376 {
377         MSG_BEGIN();
378
379         if (sockfd == CUSTOM_SOCKET_ERROR) {
380                 MSG_FATAL("server_socket not init");
381                 return MSG_ERR_UNKNOWN;
382         }
383
384         struct sockaddr_un remote;
385
386         int t = sizeof(remote);
387         int fd = ::accept(sockfd, (struct sockaddr *)&remote, (socklen_t*) &t);
388         if (fd < 0) {
389                 MSG_FATAL("accept: %s", g_strerror(errno));
390                 return MSG_ERR_UNKNOWN;
391         }
392
393         addfd(fd);
394         MSG_DEBUG("%d is added", fd);
395
396         /* write the registerd fd */
397         write(fd, (const char*) &fd, sizeof(fd));
398
399         MSG_END();
400
401         return MSG_SUCCESS;
402 }
403
404 void MsgIpcServerSocket::close(int fd)
405 {
406         MSG_BEGIN();
407
408         if (sockfd == CUSTOM_SOCKET_ERROR) {
409                 MSG_FATAL("server_socket not init");
410                 return;
411         }
412
413         MSG_DEBUG("%d to be removed", fd);
414         FD_CLR(fd, &fds);
415
416         std::map<int, int>::iterator it = mapFds.find(fd);
417         if (it == mapFds.end())
418                 MSG_FATAL("No FD %d", fd);
419         else
420                 mapFds.erase(it);
421
422         if (fd == maxfd) {
423                 int newmax = 0;
424                 for (it = mapFds.begin() ; it != mapFds.end() ; it++)
425                         newmax = (it->second > newmax)? it->second : newmax;
426                 maxfd = newmax;
427         }
428         MSG_DEBUG("fd %d removal done", fd);
429         ::close(fd);
430
431         MSG_END();
432 }
433
434 int MsgIpcServerSocket::readn(int fd, char *buf, unsigned int len)
435 {
436         size_t nleft;
437         int nread;
438
439         nleft = (size_t)len;
440         while (nleft > 0) {
441                 nread = ::read(fd, (void*)buf, nleft);
442                 if (nread < 0) {
443                         MSG_FATAL("read: %s", g_strerror(errno));
444                         return nread;
445                 } else if (nread == 0) {
446                         break;
447                 }
448
449                 if (nleft >= (unsigned int)nread)
450                         nleft -= nread;
451                 else
452                         return -1;
453
454                 buf += nread;
455         }
456         return (len-nleft);
457 }
458
459 int MsgIpcServerSocket::read(int fd, char** buf, int* len)
460 {
461         if (sockfd == CUSTOM_SOCKET_ERROR) {
462                 MSG_FATAL("server_socket(%p) is not initd %d", &sockfd, sockfd);
463                 return CUSTOM_SOCKET_ERROR;
464         }
465
466         if (!buf || !len) {
467                 MSG_FATAL("buf[%p] and len[%p] MUST NOT NULL", buf, len);
468                 return CUSTOM_SOCKET_ERROR;
469         }
470
471         *len = 0;
472         char clen[sizeof(int)] = {0};
473
474         /* read the data size first */
475         int n = readn(fd, clen, sizeof(int));
476         memcpy(len, clen, sizeof(int));
477
478         if (n == CLOSE_CONNECTION_BY_SIGNAL) {
479                 MSG_FATAL("fd %d CLOSE_CONNECTION_BY_SIGNAL", fd);
480                 return n;
481         } else if (n != sizeof(int)) {
482                 MSG_FATAL("readn %d(%zu)", n, sizeof(int));
483                 return CUSTOM_SOCKET_ERROR;
484         }
485
486         MSG_DEBUG("MsgLen %d", *len);
487
488         if (*len == CLOSE_CONNECTION_BY_USER)
489                 return *len;
490
491         /* read the data in subsequence */
492         if (*len > 0 && *len < MSG_MAX_IPC_SIZE) {
493                 unsigned int ulen = (unsigned int)*len;
494                 *buf = new char[ulen+1];
495                 bzero(*buf, ulen+1);
496                 n = readn(fd, *buf, ulen);
497
498                 if ((unsigned int)n != ulen) {
499                         MSG_FATAL("WARNING: read data_size [%d] not matched [%d]", n, ulen);
500                         return CUSTOM_SOCKET_ERROR;
501                 }
502         }
503
504         return n;
505 }
506
507 void _get_max_buffer_size(int *max_buffer_size)
508 {
509         if (MsgAccessFile(MAX_BUFFER_PATH, R_OK) == false) {
510                 *max_buffer_size = DEFAULT_MAX_BUFFER_SIZE;
511                 return;
512         }
513
514         FILE *pFile = MsgOpenFile(MAX_BUFFER_PATH, "rb");
515         if (pFile == NULL) {
516                 *max_buffer_size = DEFAULT_MAX_BUFFER_SIZE;
517                 return;
518         }
519
520         if (fscanf(pFile, "%d", max_buffer_size) < 0) {
521                 *max_buffer_size = DEFAULT_MAX_BUFFER_SIZE;
522         }
523
524         MsgCloseFile(pFile);
525 }
526
527 bool _doubling_buffer_size(int sock)
528 {
529         int bSize = 0;
530         socklen_t rn = (socklen_t)sizeof(int);
531         static int max_buffer_size = -1;
532
533         int result = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &bSize, &rn);
534         if (result < 0) {
535                 MSG_ERR("getsockopt: %s", g_strerror(errno));
536                 return false;
537         }
538
539         MSG_DEBUG("send buffer size %d", bSize);
540
541         if (max_buffer_size < 0)
542                 _get_max_buffer_size(&max_buffer_size);
543
544         MSG_DEBUG("current buffer size [%d] max buffer size [%d]", bSize, max_buffer_size);
545
546         if (bSize * 2 > max_buffer_size)
547                 return false;
548
549         bSize *= 2;
550         result = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &bSize, rn);
551         if (result < 0) {
552                 MSG_ERR("setsockopt: %s", g_strerror(errno));
553                 return false;
554         }
555
556         return true;
557 }
558
559 int MsgIpcServerSocket::writen(int fd, const char *buf, unsigned int len)
560 {
561         unsigned int nleft;
562         int nwrite;
563
564         nleft = len;
565
566         while (nleft > 0) {
567                 /*  MSG_NOSIGNAL to prevent SIGPIPE Error */
568                 /*  MSG_DONTWAIT to avoid socket block */
569                 nwrite = ::send(fd, (const void*) buf, nleft, MSG_NOSIGNAL|MSG_DONTWAIT);
570
571                 if (nwrite < 0) {
572                         MSG_FATAL("write: %s", g_strerror(errno));
573                         if (errno == EINTR) {
574                                 continue;
575                         } else if (errno == EAGAIN) {
576                                 if (_doubling_buffer_size(fd) == true)
577                                         continue;
578                         }
579                         return nwrite;
580                 } else if (nwrite == 0) { /* Nothing is send. */
581                         break;
582                 } else {
583                         nleft -= nwrite;
584                         buf += nwrite;
585                 }
586         }
587
588         return (len-nleft);
589 }
590
591
592 int MsgIpcServerSocket::write(int fd, const char* buf, unsigned int len)
593 {
594         MSG_BEGIN();
595
596         if (!buf || len <= 0) {
597                 MSG_FATAL("buf [%p] and len [%d] MUST NOT NULL", buf, len);
598                 return CUSTOM_SOCKET_ERROR;
599         }
600
601         MSG_DEBUG("for debug - fd : [%d], buf : [%p], len : [%d]", fd, buf, len);
602
603         /* send the data size first */
604         int n = writen(fd, (const char*)&len, sizeof(len));
605
606         if (n != sizeof(len)) {
607                 MSG_FATAL("WARNING: write header_size[%d] not matched [%zu]", n, sizeof(len));
608                 return CUSTOM_SOCKET_ERROR;
609         }
610
611         /*  send the data in subsequence */
612         n = writen(fd, buf, len);
613
614         MSG_DEBUG("Writing %d bytes", n);
615
616         if ((unsigned int)n != len) {
617                 MSG_FATAL("Written byte (%d) is not matched to input byte (%d)", n, len);
618                 return CUSTOM_SOCKET_ERROR;
619         }
620
621         MSG_END();
622
623         return len;
624 }