3 * Copyright (c) 2000-2012 Samsung Electronics Co., Ltd. All Rights Reserved.
5 * This file is part of msg-service.
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>
14 * PROPRIETARY/CONFIDENTIAL
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.
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.
31 #include <sys/socket.h>
33 #include <sys/ioctl.h>
34 #include <sys/types.h>
42 #include "MsgException.h"
43 #include "MsgIpcSocket.h"
46 /*==================================================================================================
47 IMPLEMENTATION OF MsgIpcClientSocket - Member Functions
48 ==================================================================================================*/
49 MsgIpcClientSocket::MsgIpcClientSocket() : sockfd(-1), remotefd(-1), maxfd(-1)
55 MSG_ERROR_T MsgIpcClientSocket::connect(const char* path)
59 if (!path || strlen(path) > strlen(MSG_SOCKET_PATH)) {
60 THROW(MsgException::IPC_ERROR, "path is null");
63 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
66 THROW(MsgException::IPC_ERROR,"socket not opened %s",strerror(errno));
69 struct sockaddr_un serverSA = {0, };
70 serverSA.sun_family = AF_UNIX;
72 memset(serverSA.sun_path, 0x00, sizeof(serverSA.sun_path));
73 strncpy(serverSA.sun_path, path, sizeof(serverSA.sun_path)-1); /* // "./socket" */
75 int len = strlen(serverSA.sun_path) + sizeof(serverSA.sun_family);
77 if (::connect(sockfd, (struct sockaddr *)&serverSA, len) == CUSTOM_SOCKET_ERROR) {
78 THROW(MsgException::IPC_ERROR,"cannot connect server %s", strerror(errno));
81 /* add fd for select() */
84 /* read remote fd for reg func */
86 AutoPtr<char> wrap(&rfd);
92 THROW(MsgException::IPC_ERROR,"rfd is NULL %s", strerror(errno));
95 memcpy(&remotefd, rfd, sizeof(rlen));
97 MSG_DEBUG("Connected: client fd [%d] <----> remote fd [%d]", sockfd, remotefd);
105 MSG_ERROR_T MsgIpcClientSocket::close()
108 MSG_FATAL("Client socket is not opened (check if you call close twice by accident) [%d]", sockfd);
109 return MSG_ERR_UNKNOWN;
112 /* it means that client is going to close the connection.*/
113 int cmd = CLOSE_CONNECTION_BY_USER;
114 int len = sizeof(cmd);
118 memcpy(cmdbuf, &cmd, len);
121 sockfd = CUSTOM_SOCKET_ERROR;
126 void MsgIpcClientSocket::addfd(int fd)
128 MSG_DEBUG("%d added", fd);
134 int MsgIpcClientSocket::writen (const char *buf, int len)
140 nwrite = ::write(sockfd, (const void*) buf, nleft);
142 MSG_FATAL("writen: sockfd [%d] error [%s]", sockfd, strerror(errno));
145 else if (nwrite == 0)
154 int MsgIpcClientSocket::write(const char* buf, int len)
157 MSG_FATAL("sockfd is not opened [%d]", sockfd);
158 return CUSTOM_SOCKET_ERROR;
161 if (!buf || len <= 0) {
162 MSG_FATAL("buf[%p] and len[%d] MUST NOT NULL", buf, len);
163 return CUSTOM_SOCKET_ERROR;
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;
173 /* send the data in subsequence */
174 n = writen(buf, len);
176 MSG_FATAL("WARNING: write data_size[%d] not matched [%d]", n, len);
177 return CUSTOM_SOCKET_ERROR;
183 int MsgIpcClientSocket::readn( char *buf, int len )
189 nread = ::read(sockfd, (void*) buf, nleft);
191 MSG_FATAL("WARNING read value %d: %s", nread, strerror(errno));
194 else if( nread == 0 )
204 /* what if the buf is shorter than data? */
205 int MsgIpcClientSocket::read(char** buf, int* len)
208 MSG_FATAL("socket is not opened [%d]", sockfd);
209 return CUSTOM_SOCKET_ERROR;
213 MSG_FATAL("rbuf and rlen MUST NOT NULL");
214 return CUSTOM_SOCKET_ERROR;
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);
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;
229 /* read the data in subsequence */
231 *buf = new char[*len+1];
233 n = readn(*buf, *len);
236 MSG_FATAL("WARNING: read data_size [%d] not matched [%d]", n, *len);
237 return CUSTOM_SOCKET_ERROR;
245 /*==================================================================================================
246 IMPLEMENTATION OF MsgIpcServerSocket - Member Functions
247 ==================================================================================================*/
248 MsgIpcServerSocket::MsgIpcServerSocket() : sockfd(-1), maxfd(-1)
253 void MsgIpcServerSocket::addfd(int fd)
255 MSG_DEBUG("%d added", fd);
258 std::map<int, int>::iterator it = mapFds.find(fd);
259 if (it != mapFds.end())
260 MSG_FATAL("Duplicate FD %d", fd);
268 MSG_ERROR_T MsgIpcServerSocket::open(const char* path)
272 if (!path || strlen(path) > strlen(MSG_SOCKET_PATH)) {
273 MSG_FATAL("path is null");
274 return MSG_ERR_INVALID_PARAMETER;
277 if (sockfd != CUSTOM_SOCKET_ERROR) {
278 MSG_FATAL("WARNING: server_socket already opened %d at %p", sockfd, &sockfd);
279 return MSG_ERR_UNKNOWN;
282 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
284 if (sockfd == CUSTOM_SOCKET_ERROR) {
285 MSG_FATAL("socket failed: %s", strerror(errno));
286 return MSG_ERR_UNKNOWN;
289 MSG_DEBUG("server_socket(%p) opened : %d", &sockfd, sockfd);
291 struct sockaddr_un local = {0, };
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);
297 unlink(local.sun_path);
299 int len = strlen(local.sun_path) + sizeof(local.sun_family);
301 if (bind(sockfd, (struct sockaddr *)&local, len) == CUSTOM_SOCKET_ERROR) {
302 MSG_FATAL("bind: %s", strerror(errno));
303 return MSG_ERR_UNKNOWN;
307 * determine permission of socket file
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
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
317 mode_t sock_mode = (S_IRWXU | S_IRWXG | S_IRWXO); /* has 777 permission */
319 if (chmod(path, sock_mode) == CUSTOM_SOCKET_ERROR) {
320 MSG_FATAL("chmod: %s", strerror(errno));
321 return MSG_ERR_UNKNOWN;
324 if (listen(sockfd, CUSTOM_SOCKET_BACKLOG) == CUSTOM_SOCKET_ERROR) {
325 MSG_FATAL("listen: %s", strerror(errno));
326 return MSG_ERR_UNKNOWN;
336 MSG_ERROR_T MsgIpcServerSocket::accept()
340 if (sockfd == CUSTOM_SOCKET_ERROR) {
341 MSG_FATAL("server_socket not init");
342 return MSG_ERR_UNKNOWN;
345 struct sockaddr_un remote;
347 int t = sizeof(remote);
348 int fd = ::accept(sockfd, (struct sockaddr *)&remote, (socklen_t*) &t);
350 MSG_FATAL("accept: %s", strerror(errno));
351 return MSG_ERR_UNKNOWN;
355 MSG_DEBUG("%d is added", fd);
357 /* write the registerd fd */
358 write(fd, (const char*) &fd, sizeof(fd));
365 void MsgIpcServerSocket::close(int fd)
369 if (sockfd == CUSTOM_SOCKET_ERROR) {
370 MSG_FATAL("server_socket not init");
374 MSG_DEBUG("%d to be removed", fd);
377 std::map<int, int>::iterator it = mapFds.find(fd);
378 if (it == mapFds.end())
379 MSG_FATAL("No FD %d", fd);
385 for (it = mapFds.begin() ; it != mapFds.end() ; it++)
386 newmax = (it->second > newmax )? it->second : newmax;
389 MSG_DEBUG("fd %d removal done", fd);
395 int MsgIpcServerSocket::readn( int fd, char *buf, int len )
401 nread = ::read(fd, (void*)buf, nleft);
403 MSG_FATAL("read: %s", strerror(errno));
415 int MsgIpcServerSocket::read(int fd, char** buf, int* len )
417 if (sockfd == CUSTOM_SOCKET_ERROR) {
418 MSG_FATAL("server_socket(%p) is not initd %d", &sockfd, sockfd);
419 return CUSTOM_SOCKET_ERROR;
423 MSG_FATAL("buf[%p] and len[%p] MUST NOT NULL", buf, len);
424 return CUSTOM_SOCKET_ERROR;
427 /* read the data size first */
428 int n = readn(fd, (char*) len, sizeof(int));
430 if (n == CLOSE_CONNECTION_BY_SIGNAL) {
431 MSG_FATAL("fd %d CLOSE_CONNECTION_BY_SIGNAL", fd);
435 else if (n != sizeof(int)) {
436 MSG_FATAL("readn %d(%d)", n, sizeof(int));
437 return CUSTOM_SOCKET_ERROR;
440 MSG_DEBUG("MsgLen %d", *len);
441 if (*len == CLOSE_CONNECTION_BY_USER)
445 /* read the data in subsequence */
446 *buf = new char[*len+1];
448 n = readn(fd, *buf, *len);
451 MSG_FATAL("WARNING: read data_size [%d] not matched [%d]", n, *len);
452 return CUSTOM_SOCKET_ERROR;
459 int MsgIpcServerSocket::writen(int fd, const char *buf, int len)
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);
471 MSG_FATAL("write: %s", strerror(errno));
474 else if (nwrite == 0) { /* Nothing is send. */
487 int MsgIpcServerSocket::write(int fd, const char* buf, int len)
491 if (!buf || len <= 0) {
492 MSG_FATAL("buf [%p] and len [%d] MUST NOT NULL", buf, len);
493 return CUSTOM_SOCKET_ERROR;
496 MSG_DEBUG("for debug - fd : [%d], buf : [%p], len : [%d]", fd, buf, len);
498 /* send the data size first */
499 int n = writen(fd, (const char*)&len, sizeof(len));
501 if (n != sizeof(len)) {
502 MSG_FATAL("WARNING: write header_size[%d] not matched [%d]", n, sizeof(len));
503 return CUSTOM_SOCKET_ERROR;
506 /* send the data in subsequence */
507 n = writen(fd, buf, len);
509 MSG_DEBUG("Writing %d bytes", n);
512 MSG_FATAL("Written byte (%d) is not matched to input byte (%d)", n, len);
513 return CUSTOM_SOCKET_ERROR;