update tizen source
[framework/messaging/msg-service.git] / utils / MsgIpcSocket.cpp
1 /*
2 *
3 * Copyright (c) 2000-2012 Samsung Electronics Co., Ltd. All Rights Reserved.
4 *
5 * This file is part of msg-service.
6 *
7 * Contact: Jaeyun Jeong <jyjeong@samsung.com>
8 *          Sangkoo Kim <sangkoo.kim@samsung.com>
9 *          Seunghwan Lee <sh.cat.lee@samsung.com>
10 *          SoonMin Jung <sm0415.jung@samsung.com>
11 *          Jae-Young Lee <jy4710.lee@samsung.com>
12 *          KeeBum Kim <keebum.kim@samsung.com>
13 *
14 * PROPRIETARY/CONFIDENTIAL
15 *
16 * This software is the confidential and proprietary information of
17 * SAMSUNG ELECTRONICS ("Confidential Information"). You shall not
18 * disclose such Confidential Information and shall use it only in
19 * accordance with the terms of the license agreement you entered
20 * into with SAMSUNG ELECTRONICS.
21 *
22 * SAMSUNG make no representations or warranties about the suitability
23 * of the software, either express or implied, including but not limited
24 * to the implied warranties of merchantability, fitness for a particular
25 * purpose, or non-infringement. SAMSUNG shall not be liable for any
26 * damages suffered by licensee as a result of using, modifying or
27 * distributing this software or its derivatives.
28 *
29 */
30
31 #include <sys/socket.h>
32 #include <sys/un.h>
33 #include <sys/ioctl.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36
37 #include <errno.h>
38 #include <unistd.h>
39 #include <errno.h>
40
41 #include "MsgDebug.h"
42 #include "MsgException.h"
43 #include "MsgIpcSocket.h"
44
45
46 /*==================================================================================================
47                                      IMPLEMENTATION OF MsgIpcClientSocket - Member Functions
48 ==================================================================================================*/
49 MsgIpcClientSocket::MsgIpcClientSocket() : sockfd(-1), remotefd(-1), maxfd(-1)
50 {
51         FD_ZERO(&fds);
52 }
53
54
55 MSG_ERROR_T MsgIpcClientSocket::connect(const char* path)
56 {
57         MSG_BEGIN();
58
59         if (!path || strlen(path) > strlen(MSG_SOCKET_PATH)) {
60                 THROW(MsgException::IPC_ERROR, "path is null");
61         }
62
63         sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
64
65         if (sockfd < 0) {
66                 THROW(MsgException::IPC_ERROR,"socket not opened %s",strerror(errno));
67         }
68
69         struct sockaddr_un serverSA = {0, };
70         serverSA.sun_family = AF_UNIX;
71
72         memset(serverSA.sun_path, 0x00, sizeof(serverSA.sun_path));
73         strncpy(serverSA.sun_path, path, sizeof(serverSA.sun_path)-1);  /* // "./socket" */
74
75         int len = strlen(serverSA.sun_path) + sizeof(serverSA.sun_family);
76
77         if (::connect(sockfd, (struct sockaddr *)&serverSA, len) == CUSTOM_SOCKET_ERROR) {
78                 THROW(MsgException::IPC_ERROR,"cannot connect server %s", strerror(errno));
79         }
80
81         /* add fd for select() */
82         addfd(sockfd);
83
84         /* read remote fd for reg func */
85         char *rfd = NULL;
86         AutoPtr<char> wrap(&rfd);
87         int rlen;
88
89         read(&rfd, &rlen);
90
91         if (rfd == NULL) {
92                 THROW(MsgException::IPC_ERROR,"rfd is NULL %s", strerror(errno));
93         }
94
95         memcpy(&remotefd, rfd, sizeof(rlen));
96
97         MSG_DEBUG("Connected: client fd [%d] <----> remote fd [%d]", sockfd, remotefd);
98
99         MSG_END();
100
101         return MSG_SUCCESS;
102 }
103
104
105 MSG_ERROR_T MsgIpcClientSocket::close()
106 {
107         if (sockfd < 0) {
108                 MSG_FATAL("Client socket is not opened (check if you call close twice by accident) [%d]", sockfd);
109                 return MSG_ERR_UNKNOWN;
110         }
111
112         /* it means that client is going to close the connection.*/
113         int cmd = CLOSE_CONNECTION_BY_USER;
114         int len = sizeof(cmd);
115
116         char cmdbuf[len];
117         bzero(cmdbuf, len);
118         memcpy(cmdbuf, &cmd, len);
119
120         ::close(sockfd);
121         sockfd = CUSTOM_SOCKET_ERROR;
122
123         return MSG_SUCCESS;
124 }
125
126 void MsgIpcClientSocket::addfd(int fd)
127 {
128         MSG_DEBUG("%d added", fd);
129         FD_SET(fd, &fds);
130         if (fd > maxfd)
131                 maxfd = fd;
132 }
133
134 int MsgIpcClientSocket::writen (const char *buf, int len)
135 {
136         int nleft, nwrite;
137
138         nleft = len;
139         while (nleft > 0) {
140                 nwrite = ::write(sockfd, (const void*) buf, nleft);
141                 if (nwrite < 0) {
142                         MSG_FATAL("writen: sockfd [%d] error [%s]",  sockfd, strerror(errno));
143                         return nwrite;
144                 }
145                 else if (nwrite == 0)
146                         break;
147
148                 nleft -= nwrite;
149                 buf += nwrite;
150         }
151         return (len-nleft);
152 }
153
154 int MsgIpcClientSocket::write(const char* buf, int len)
155 {
156         if (sockfd < 0) {
157                 MSG_FATAL("sockfd is not opened [%d]", sockfd);
158                 return CUSTOM_SOCKET_ERROR;
159         }
160
161         if (!buf || len <= 0) {
162                 MSG_FATAL("buf[%p]      and len[%d] MUST NOT NULL", buf, len);
163                 return CUSTOM_SOCKET_ERROR;
164         }
165
166         /* send the data size first */
167         int n = writen((const char*)&len, sizeof(len));
168         if (n != sizeof(len)) {
169                 MSG_FATAL("WARNING: write header_size[%d] not matched [%d]", n, sizeof(len));
170                 return CUSTOM_SOCKET_ERROR;
171         }
172
173         /* send the data in subsequence */
174         n = writen(buf, len);
175         if (n != len) {
176                 MSG_FATAL("WARNING: write data_size[%d] not matched [%d]", n, len);
177                 return CUSTOM_SOCKET_ERROR;
178         }
179
180         return len;
181 }
182
183 int MsgIpcClientSocket::readn( char *buf, int len )
184 {
185         int nleft, nread;
186
187         nleft = len;
188         while (nleft > 0) {
189                 nread = ::read(sockfd, (void*) buf, nleft);
190                 if (nread < 0) {
191                         MSG_FATAL("WARNING read value %d: %s", nread, strerror(errno));
192                         return nread;
193                 }
194                 else if( nread == 0 )
195                         break;
196
197                 nleft -= nread;
198                 buf += nread;
199         }
200         return (len-nleft);
201 }
202
203
204 /* what if the buf is shorter than data? */
205 int MsgIpcClientSocket::read(char** buf, int* len)
206 {
207         if (sockfd < 0) {
208                 MSG_FATAL("socket is not opened [%d]", sockfd);
209                 return CUSTOM_SOCKET_ERROR;
210         }
211
212         if (!buf || !len) {
213                 MSG_FATAL("rbuf and rlen MUST NOT NULL");
214                 return CUSTOM_SOCKET_ERROR;
215         }
216
217         /* read the data size first */
218         int n = readn((char*) len, sizeof(int));
219         if (n == CLOSE_CONNECTION_BY_SIGNAL) { /* if msgfw gets down, it signals to all IPC clients */
220                 MSG_FATAL("sockfd [%d] CLOSE_CONNECTION_BY_SIGNAL", sockfd);
221                 return n;
222         }
223
224         else if (n != sizeof(int)) {
225                 MSG_FATAL("WARNING: read header_size[%d] not matched [%d]", n, sizeof(int));
226                 return CUSTOM_SOCKET_ERROR;
227         }
228
229         /*  read the data in subsequence */
230         if ((*len) > 0) {
231                 *buf = new char[*len+1];
232                 bzero(*buf, *len+1);
233                 n = readn(*buf, *len);
234
235                 if (n !=  *len) {
236                         MSG_FATAL("WARNING: read data_size [%d] not matched [%d]", n, *len);
237                         return CUSTOM_SOCKET_ERROR;
238                 }
239         }
240
241         return n;
242 }
243
244
245 /*==================================================================================================
246                                      IMPLEMENTATION OF MsgIpcServerSocket - Member Functions
247 ==================================================================================================*/
248 MsgIpcServerSocket::MsgIpcServerSocket() : sockfd(-1), maxfd(-1)
249 {
250         FD_ZERO(&fds);
251 }
252
253 void MsgIpcServerSocket::addfd(int fd)
254 {
255         MSG_DEBUG("%d added", fd);
256         FD_SET(fd, &fds);
257
258         std::map<int, int>::iterator it = mapFds.find(fd);
259         if (it != mapFds.end())
260                 MSG_FATAL("Duplicate FD %d", fd);
261         else
262                 mapFds[fd] = fd;
263
264         if (fd > maxfd)
265                 maxfd = fd;
266 }
267
268 MSG_ERROR_T MsgIpcServerSocket::open(const char* path)
269 {
270         MSG_BEGIN();
271
272         if (!path || strlen(path) > strlen(MSG_SOCKET_PATH)) {
273                 MSG_FATAL("path is null");
274                 return MSG_ERR_INVALID_PARAMETER;
275         }
276
277         if (sockfd != CUSTOM_SOCKET_ERROR) {
278                 MSG_FATAL("WARNING: server_socket already opened %d at %p", sockfd,  &sockfd);
279                 return MSG_ERR_UNKNOWN;
280         }
281
282         sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
283
284         if (sockfd == CUSTOM_SOCKET_ERROR) {
285                 MSG_FATAL("socket failed: %s", strerror(errno));
286                 return MSG_ERR_UNKNOWN;
287         }
288
289         MSG_DEBUG("server_socket(%p) opened : %d", &sockfd, sockfd);
290
291         struct sockaddr_un local = {0, };
292
293         local.sun_family = AF_UNIX;
294         memset(local.sun_path, 0x00, sizeof(local.sun_path));
295         strncpy(local.sun_path, path, sizeof(local.sun_path)-1);
296
297         unlink(local.sun_path);
298
299         int len = strlen(local.sun_path) + sizeof(local.sun_family);
300
301         if (bind(sockfd, (struct sockaddr *)&local, len) == CUSTOM_SOCKET_ERROR) {
302                 MSG_FATAL("bind: %s", strerror(errno));
303                 return MSG_ERR_UNKNOWN;
304         }
305
306         /**
307          * determine permission of socket file
308          *
309          *  - S_IRWXU : for user, allow read and write and execute
310          *  - S_IRWXG : for group, allow read and write and execute
311          *  - S_IRWXO : for other, allow read and write and execute
312          *
313          *  - S_IRUSR, S_IWUSR, S_IXUSR : for user, allow only read, write, execute respectively
314          *  - S_IRGRP, S_IWGRP, S_IXGRP : for group, allow only read, write, execute respectively
315          *  - S_IROTH, S_IWOTH, S_IXOTH : for other, allow only read, write, execute respectively
316          */
317         mode_t sock_mode = (S_IRWXU | S_IRWXG | S_IRWXO); /* has 777 permission */
318
319         if (chmod(path, sock_mode) == CUSTOM_SOCKET_ERROR) {
320                 MSG_FATAL("chmod: %s", strerror(errno));
321                 return MSG_ERR_UNKNOWN;
322         }
323
324         if (listen(sockfd, CUSTOM_SOCKET_BACKLOG) == CUSTOM_SOCKET_ERROR) {
325                 MSG_FATAL("listen: %s", strerror(errno));
326                 return MSG_ERR_UNKNOWN;
327         }
328
329         addfd(sockfd);
330
331         MSG_END();
332
333         return MSG_SUCCESS;
334 }
335
336 MSG_ERROR_T MsgIpcServerSocket::accept()
337 {
338         MSG_BEGIN();
339
340         if (sockfd == CUSTOM_SOCKET_ERROR) {
341                 MSG_FATAL("server_socket not init");
342                 return MSG_ERR_UNKNOWN;
343         }
344
345         struct sockaddr_un remote;
346
347         int t = sizeof(remote);
348         int fd = ::accept(sockfd, (struct sockaddr *)&remote, (socklen_t*) &t);
349         if (fd < 0) {
350                 MSG_FATAL("accept: %s", strerror(errno));
351                 return MSG_ERR_UNKNOWN;
352         }
353
354         addfd(fd);
355         MSG_DEBUG("%d is added", fd);
356
357         /* write the registerd fd */
358         write(fd, (const char*) &fd, sizeof(fd));
359
360         MSG_END();
361
362         return MSG_SUCCESS;
363 }
364
365 void MsgIpcServerSocket::close(int fd)
366 {
367         MSG_BEGIN();
368
369         if (sockfd == CUSTOM_SOCKET_ERROR) {
370                 MSG_FATAL("server_socket not init");
371                 return;
372         }
373
374         MSG_DEBUG("%d to be removed", fd);
375         FD_CLR(fd, &fds);
376
377         std::map<int, int>::iterator it = mapFds.find(fd);
378         if (it == mapFds.end())
379                 MSG_FATAL("No FD %d", fd);
380         else
381                 mapFds.erase(it);
382
383         if (fd == maxfd) {
384                 int newmax = 0;
385                 for (it = mapFds.begin() ; it != mapFds.end() ; it++)
386                         newmax = (it->second > newmax )? it->second : newmax;
387                 maxfd = newmax;
388         }
389         MSG_DEBUG("fd %d removal done", fd);
390         ::close(fd);
391
392         MSG_END();
393 }
394
395 int MsgIpcServerSocket::readn( int fd, char *buf, int len )
396 {
397         int nleft, nread;
398
399         nleft = len;
400         while (nleft > 0) {
401                 nread = ::read(fd, (void*)buf, nleft);
402                 if (nread < 0) {
403                         MSG_FATAL("read: %s", strerror(errno));
404                         return nread;
405                 }
406                 else if (nread == 0)
407                         break;
408
409                 nleft -= nread;
410                 buf += nread;
411         }
412         return (len-nleft);
413 }
414
415 int MsgIpcServerSocket::read(int fd, char** buf, int* len )
416 {
417         if (sockfd == CUSTOM_SOCKET_ERROR) {
418                 MSG_FATAL("server_socket(%p) is not initd %d", &sockfd, sockfd);
419                 return CUSTOM_SOCKET_ERROR;
420         }
421
422         if (!buf || !len) {
423                 MSG_FATAL("buf[%p] and len[%p] MUST NOT NULL", buf, len);
424                 return CUSTOM_SOCKET_ERROR;
425         }
426
427         /* read the data size first */
428         int n = readn(fd, (char*) len, sizeof(int));
429
430         if (n == CLOSE_CONNECTION_BY_SIGNAL) {
431                 MSG_FATAL("fd %d CLOSE_CONNECTION_BY_SIGNAL", fd);
432                 return n;
433         }
434
435         else if (n != sizeof(int)) {
436                 MSG_FATAL("readn %d(%d)", n, sizeof(int));
437                 return CUSTOM_SOCKET_ERROR;
438         }
439
440         MSG_DEBUG("MsgLen %d", *len);
441         if (*len == CLOSE_CONNECTION_BY_USER)
442                 return *len;
443
444         if ((*len) > 0) {
445                 /* read the data in subsequence */
446                 *buf = new char[*len+1];
447                 bzero(*buf, *len+1);
448                 n = readn(fd, *buf, *len);
449
450                 if (n != *len) {
451                         MSG_FATAL("WARNING: read data_size [%d] not matched [%d]", n, *len);
452                         return CUSTOM_SOCKET_ERROR;
453                 }
454         }
455
456         return n;
457 }
458
459 int MsgIpcServerSocket::writen(int fd, const char *buf, int len)
460 {
461         int nleft, nwrite;
462
463         nleft = len;
464
465         while (nleft > 0) {
466                 /*  MSG_NOSIGNAL to prevent SIGPIPE Error */
467                 /*  MSG_DONTWAIT to avoid socket block */
468                 nwrite = ::send(fd, (const void*) buf, nleft, MSG_NOSIGNAL|MSG_DONTWAIT);
469
470                 if (nwrite < 0) {
471                         MSG_FATAL("write: %s", strerror(errno));
472                         return nwrite;
473                 }
474                 else if (nwrite == 0) { /* Nothing is send. */
475                         break;
476                 }
477                 else {
478                         nleft -= nwrite;
479                         buf += nwrite;
480                 }
481         }
482
483         return (len-nleft);
484 }
485
486
487 int MsgIpcServerSocket::write(int fd, const char* buf, int len)
488 {
489         MSG_BEGIN();
490
491         if (!buf || len <= 0) {
492                 MSG_FATAL("buf [%p] and len [%d] MUST NOT NULL", buf, len);
493                 return CUSTOM_SOCKET_ERROR;
494         }
495
496         MSG_DEBUG("for debug - fd : [%d], buf : [%p], len : [%d]", fd, buf, len);
497
498         /* send the data size first */
499         int n = writen(fd, (const char*)&len, sizeof(len));
500
501         if (n != sizeof(len)) {
502                 MSG_FATAL("WARNING: write header_size[%d] not matched [%d]", n, sizeof(len));
503                 return CUSTOM_SOCKET_ERROR;
504         }
505
506         /*  send the data in subsequence */
507         n = writen(fd, buf, len);
508
509         MSG_DEBUG("Writing %d bytes", n);
510
511         if (n != len) {
512                 MSG_FATAL("Written byte (%d) is not matched to input byte (%d)", n, len);
513                 return CUSTOM_SOCKET_ERROR;
514         }
515
516         MSG_END();
517
518         return len;
519 }