2 * Copyright 2012 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.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
8 * http://www.tizenopensource.org/license
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.
17 #include <sys/socket.h>
19 #include <sys/ioctl.h>
20 #include <sys/types.h>
28 #include "MsgException.h"
29 #include "MsgIpcSocket.h"
32 /*==================================================================================================
33 IMPLEMENTATION OF MsgIpcClientSocket - Member Functions
34 ==================================================================================================*/
35 MsgIpcClientSocket::MsgIpcClientSocket() : sockfd(-1), remotefd(-1), maxfd(-1)
41 msg_error_t MsgIpcClientSocket::connect(const char* path)
45 if (!path || strlen(path) > strlen(MSG_SOCKET_PATH)) {
46 THROW(MsgException::IPC_ERROR, "path is null");
49 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
52 THROW(MsgException::IPC_ERROR,"socket not opened %s",strerror(errno));
55 struct sockaddr_un serverSA = {0, };
56 serverSA.sun_family = AF_UNIX;
58 memset(serverSA.sun_path, 0x00, sizeof(serverSA.sun_path));
59 strncpy(serverSA.sun_path, path, sizeof(serverSA.sun_path)-1); /* // "./socket" */
61 int len = strlen(serverSA.sun_path) + sizeof(serverSA.sun_family);
63 if (::connect(sockfd, (struct sockaddr *)&serverSA, len) == CUSTOM_SOCKET_ERROR) {
64 THROW(MsgException::IPC_ERROR,"cannot connect server %s", strerror(errno));
67 /* add fd for select() */
70 /* read remote fd for reg func */
72 AutoPtr<char> wrap(&rfd);
78 THROW(MsgException::IPC_ERROR,"rfd is NULL %s", strerror(errno));
81 memcpy(&remotefd, rfd, sizeof(rlen));
83 MSG_DEBUG("Connected: client fd [%d] <----> remote fd [%d]", sockfd, remotefd);
91 msg_error_t MsgIpcClientSocket::close()
94 MSG_FATAL("Client socket is not opened (check if you call close twice by accident) [%d]", sockfd);
95 return MSG_ERR_UNKNOWN;
98 /* it means that client is going to close the connection.*/
99 int cmd = CLOSE_CONNECTION_BY_USER;
100 int len = sizeof(cmd);
104 memcpy(cmdbuf, &cmd, len);
107 sockfd = CUSTOM_SOCKET_ERROR;
112 void MsgIpcClientSocket::addfd(int fd)
114 MSG_DEBUG("%d added", fd);
120 int MsgIpcClientSocket::writen (const char *buf, int len)
126 nwrite = ::write(sockfd, (const void*) buf, nleft);
128 MSG_FATAL("writen: sockfd [%d] error [%s]", sockfd, strerror(errno));
131 else if (nwrite == 0)
140 int MsgIpcClientSocket::write(const char* buf, int len)
143 MSG_FATAL("sockfd is not opened [%d]", sockfd);
144 return CUSTOM_SOCKET_ERROR;
147 if (!buf || len <= 0) {
148 MSG_FATAL("buf[%p] and len[%d] MUST NOT NULL", buf, len);
149 return CUSTOM_SOCKET_ERROR;
152 /* send the data size first */
153 int n = writen((const char*)&len, sizeof(len));
154 if (n != sizeof(len)) {
155 MSG_FATAL("WARNING: write header_size[%d] not matched [%d]", n, sizeof(len));
156 return CUSTOM_SOCKET_ERROR;
159 /* send the data in subsequence */
160 n = writen(buf, len);
162 MSG_FATAL("WARNING: write data_size[%d] not matched [%d]", n, len);
163 return CUSTOM_SOCKET_ERROR;
169 int MsgIpcClientSocket::readn( char *buf, int len )
175 nread = ::read(sockfd, (void*) buf, nleft);
177 MSG_FATAL("WARNING read value %d: %s", nread, strerror(errno));
180 else if( nread == 0 )
190 /* what if the buf is shorter than data? */
191 int MsgIpcClientSocket::read(char** buf, int* len)
194 MSG_FATAL("socket is not opened [%d]", sockfd);
195 return CUSTOM_SOCKET_ERROR;
199 MSG_FATAL("rbuf and rlen MUST NOT NULL");
200 return CUSTOM_SOCKET_ERROR;
203 /* read the data size first */
204 int n = readn((char*) len, sizeof(int));
205 if (n == CLOSE_CONNECTION_BY_SIGNAL) { /* if msgfw gets down, it signals to all IPC clients */
206 MSG_FATAL("sockfd [%d] CLOSE_CONNECTION_BY_SIGNAL", sockfd);
210 else if (n != sizeof(int)) {
211 MSG_FATAL("WARNING: read header_size[%d] not matched [%d]", n, sizeof(int));
212 return CUSTOM_SOCKET_ERROR;
215 /* read the data in subsequence */
217 unsigned int ulen = (unsigned int)*len;
218 *buf = new char[ulen+1];
220 n = readn(*buf, ulen);
223 MSG_FATAL("WARNING: read data_size [%d] not matched [%d]", n, ulen);
224 return CUSTOM_SOCKET_ERROR;
232 /*==================================================================================================
233 IMPLEMENTATION OF MsgIpcServerSocket - Member Functions
234 ==================================================================================================*/
235 MsgIpcServerSocket::MsgIpcServerSocket() : sockfd(-1), maxfd(-1)
240 void MsgIpcServerSocket::addfd(int fd)
242 MSG_DEBUG("%d added", fd);
245 std::map<int, int>::iterator it = mapFds.find(fd);
246 if (it != mapFds.end())
247 MSG_FATAL("Duplicate FD %d", fd);
255 msg_error_t MsgIpcServerSocket::open(const char* path)
259 if (!path || strlen(path) > strlen(MSG_SOCKET_PATH)) {
260 MSG_FATAL("path is null");
261 return MSG_ERR_INVALID_PARAMETER;
264 if (sockfd != CUSTOM_SOCKET_ERROR) {
265 MSG_FATAL("WARNING: server_socket already opened %d at %p", sockfd, &sockfd);
266 return MSG_ERR_UNKNOWN;
269 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
271 if (sockfd == CUSTOM_SOCKET_ERROR) {
272 MSG_FATAL("socket failed: %s", strerror(errno));
273 return MSG_ERR_UNKNOWN;
276 MSG_DEBUG("server_socket(%p) opened : %d", &sockfd, sockfd);
278 struct sockaddr_un local = {0, };
280 local.sun_family = AF_UNIX;
281 memset(local.sun_path, 0x00, sizeof(local.sun_path));
282 strncpy(local.sun_path, path, sizeof(local.sun_path)-1);
284 unlink(local.sun_path);
286 int len = strlen(local.sun_path) + sizeof(local.sun_family);
288 if (bind(sockfd, (struct sockaddr *)&local, len) == CUSTOM_SOCKET_ERROR) {
289 MSG_FATAL("bind: %s", strerror(errno));
290 return MSG_ERR_UNKNOWN;
294 * determine permission of socket file
296 * - S_IRWXU : for user, allow read and write and execute
297 * - S_IRWXG : for group, allow read and write and execute
298 * - S_IRWXO : for other, allow read and write and execute
300 * - S_IRUSR, S_IWUSR, S_IXUSR : for user, allow only read, write, execute respectively
301 * - S_IRGRP, S_IWGRP, S_IXGRP : for group, allow only read, write, execute respectively
302 * - S_IROTH, S_IWOTH, S_IXOTH : for other, allow only read, write, execute respectively
304 mode_t sock_mode = (S_IRWXU | S_IRWXG | S_IRWXO); /* has 777 permission */
306 if (chmod(path, sock_mode) == CUSTOM_SOCKET_ERROR) {
307 MSG_FATAL("chmod: %s", strerror(errno));
308 return MSG_ERR_UNKNOWN;
311 if (listen(sockfd, CUSTOM_SOCKET_BACKLOG) == CUSTOM_SOCKET_ERROR) {
312 MSG_FATAL("listen: %s", strerror(errno));
313 return MSG_ERR_UNKNOWN;
323 msg_error_t MsgIpcServerSocket::accept()
327 if (sockfd == CUSTOM_SOCKET_ERROR) {
328 MSG_FATAL("server_socket not init");
329 return MSG_ERR_UNKNOWN;
332 struct sockaddr_un remote;
334 int t = sizeof(remote);
335 int fd = ::accept(sockfd, (struct sockaddr *)&remote, (socklen_t*) &t);
337 MSG_FATAL("accept: %s", strerror(errno));
338 return MSG_ERR_UNKNOWN;
342 MSG_DEBUG("%d is added", fd);
344 /* write the registerd fd */
345 write(fd, (const char*) &fd, sizeof(fd));
352 void MsgIpcServerSocket::close(int fd)
356 if (sockfd == CUSTOM_SOCKET_ERROR) {
357 MSG_FATAL("server_socket not init");
361 MSG_DEBUG("%d to be removed", fd);
364 std::map<int, int>::iterator it = mapFds.find(fd);
365 if (it == mapFds.end())
366 MSG_FATAL("No FD %d", fd);
372 for (it = mapFds.begin() ; it != mapFds.end() ; it++)
373 newmax = (it->second > newmax )? it->second : newmax;
376 MSG_DEBUG("fd %d removal done", fd);
382 int MsgIpcServerSocket::readn( int fd, char *buf, int len )
388 nread = ::read(fd, (void*)buf, nleft);
390 MSG_FATAL("read: %s", strerror(errno));
402 int MsgIpcServerSocket::read(int fd, char** buf, int* len )
404 if (sockfd == CUSTOM_SOCKET_ERROR) {
405 MSG_FATAL("server_socket(%p) is not initd %d", &sockfd, sockfd);
406 return CUSTOM_SOCKET_ERROR;
410 MSG_FATAL("buf[%p] and len[%p] MUST NOT NULL", buf, len);
411 return CUSTOM_SOCKET_ERROR;
414 /* read the data size first */
415 int n = readn(fd, (char*) len, sizeof(int));
417 if (n == CLOSE_CONNECTION_BY_SIGNAL) {
418 MSG_FATAL("fd %d CLOSE_CONNECTION_BY_SIGNAL", fd);
422 else if (n != sizeof(int)) {
423 MSG_FATAL("readn %d(%d)", n, sizeof(int));
424 return CUSTOM_SOCKET_ERROR;
427 MSG_DEBUG("MsgLen %d", *len);
428 if (*len == CLOSE_CONNECTION_BY_USER)
432 /* read the data in subsequence */
433 unsigned int ulen = (unsigned int)*len;
434 *buf = new char[ulen+1];
436 n = readn(fd, *buf, ulen);
439 MSG_FATAL("WARNING: read data_size [%d] not matched [%d]", n, ulen);
440 return CUSTOM_SOCKET_ERROR;
447 int MsgIpcServerSocket::writen(int fd, const char *buf, int len)
454 /* MSG_NOSIGNAL to prevent SIGPIPE Error */
455 /* MSG_DONTWAIT to avoid socket block */
456 nwrite = ::send(fd, (const void*) buf, nleft, MSG_NOSIGNAL|MSG_DONTWAIT);
459 MSG_FATAL("write: %s", strerror(errno));
462 else if (nwrite == 0) { /* Nothing is send. */
475 int MsgIpcServerSocket::write(int fd, const char* buf, int len)
479 if (!buf || len <= 0) {
480 MSG_FATAL("buf [%p] and len [%d] MUST NOT NULL", buf, len);
481 return CUSTOM_SOCKET_ERROR;
484 MSG_DEBUG("for debug - fd : [%d], buf : [%p], len : [%d]", fd, buf, len);
486 /* send the data size first */
487 int n = writen(fd, (const char*)&len, sizeof(len));
489 if (n != sizeof(len)) {
490 MSG_FATAL("WARNING: write header_size[%d] not matched [%d]", n, sizeof(len));
491 return CUSTOM_SOCKET_ERROR;
494 /* send the data in subsequence */
495 n = writen(fd, buf, len);
497 MSG_DEBUG("Writing %d bytes", n);
500 MSG_FATAL("Written byte (%d) is not matched to input byte (%d)", n, len);
501 return CUSTOM_SOCKET_ERROR;