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, unsigned int len)
127 nwrite = ::write(sockfd, (const void*) buf, nleft);
129 MSG_FATAL("writen: sockfd [%d] error [%s]", sockfd, strerror(errno));
131 } else if (nwrite == 0) {
141 int MsgIpcClientSocket::write(const char* buf, unsigned int len)
144 MSG_FATAL("sockfd is not opened [%d]", sockfd);
145 return CUSTOM_SOCKET_ERROR;
148 if (!buf || len == 0) {
149 MSG_FATAL("buf[%p] and len[%d] MUST NOT NULL", buf, len);
150 return CUSTOM_SOCKET_ERROR;
153 /* send the data size first */
154 int n = writen((const char*)&len, sizeof(len));
155 if (n != sizeof(len)) {
156 MSG_FATAL("WARNING: write header_size[%d] not matched [%d]", n, sizeof(len));
157 return CUSTOM_SOCKET_ERROR;
160 /* send the data in subsequence */
161 n = writen(buf, len);
162 if ((unsigned int)n != len) {
163 MSG_FATAL("WARNING: write data_size[%d] not matched [%d]", n, len);
164 return CUSTOM_SOCKET_ERROR;
170 int MsgIpcClientSocket::readn( char *buf, unsigned int len )
177 nread = ::read(sockfd, (void*) buf, nleft);
179 MSG_FATAL("WARNING read value %d: %s", nread, strerror(errno));
181 } else if( nread == 0 ) {
193 /* what if the buf is shorter than data? */
194 int MsgIpcClientSocket::read(char** buf, unsigned int* len)
197 MSG_FATAL("socket is not opened [%d]", sockfd);
198 return CUSTOM_SOCKET_ERROR;
202 MSG_FATAL("rbuf and rlen MUST NOT NULL");
203 return CUSTOM_SOCKET_ERROR;
206 /* read the data size first */
207 int n = readn((char*) len, sizeof(int));
208 if (n == CLOSE_CONNECTION_BY_SIGNAL) { /* if msgfw gets down, it signals to all IPC clients */
209 MSG_FATAL("sockfd [%d] CLOSE_CONNECTION_BY_SIGNAL", sockfd);
211 } else if (n != sizeof(int)) {
212 MSG_FATAL("WARNING: read header_size[%d] not matched [%d]", n, sizeof(int));
213 return CUSTOM_SOCKET_ERROR;
216 /* read the data in subsequence */
217 unsigned int ulen = (unsigned int)*len;
218 *buf = new char[ulen];
220 n = readn(*buf, ulen);
222 if ((unsigned int)n != ulen) {
223 MSG_FATAL("WARNING: read data_size [%d] not matched [%d]", n, ulen);
224 return CUSTOM_SOCKET_ERROR;
231 /*==================================================================================================
232 IMPLEMENTATION OF MsgIpcServerSocket - Member Functions
233 ==================================================================================================*/
234 MsgIpcServerSocket::MsgIpcServerSocket() : sockfd(-1), maxfd(-1)
239 void MsgIpcServerSocket::addfd(int fd)
241 MSG_DEBUG("%d added", fd);
244 std::map<int, int>::iterator it = mapFds.find(fd);
245 if (it != mapFds.end())
246 MSG_FATAL("Duplicate FD %d", fd);
254 msg_error_t MsgIpcServerSocket::open(const char* path)
258 if (!path || strlen(path) > strlen(MSG_SOCKET_PATH)) {
259 MSG_FATAL("path is null");
260 return MSG_ERR_INVALID_PARAMETER;
263 if (sockfd != CUSTOM_SOCKET_ERROR) {
264 MSG_FATAL("WARNING: server_socket already opened %d at %p", sockfd, &sockfd);
265 return MSG_ERR_UNKNOWN;
268 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
270 if (sockfd == CUSTOM_SOCKET_ERROR) {
271 MSG_FATAL("socket failed: %s", strerror(errno));
272 return MSG_ERR_UNKNOWN;
275 MSG_DEBUG("server_socket(%p) opened : %d", &sockfd, sockfd);
277 struct sockaddr_un local = {0, };
279 local.sun_family = AF_UNIX;
280 memset(local.sun_path, 0x00, sizeof(local.sun_path));
281 strncpy(local.sun_path, path, sizeof(local.sun_path)-1);
283 unlink(local.sun_path);
285 int len = strlen(local.sun_path) + sizeof(local.sun_family);
287 if (bind(sockfd, (struct sockaddr *)&local, len) == CUSTOM_SOCKET_ERROR) {
288 MSG_FATAL("bind: %s", strerror(errno));
289 return MSG_ERR_UNKNOWN;
293 * determine permission of socket file
295 * - S_IRWXU : for user, allow read and write and execute
296 * - S_IRWXG : for group, allow read and write and execute
297 * - S_IRWXO : for other, allow read and write and execute
299 * - S_IRUSR, S_IWUSR, S_IXUSR : for user, allow only read, write, execute respectively
300 * - S_IRGRP, S_IWGRP, S_IXGRP : for group, allow only read, write, execute respectively
301 * - S_IROTH, S_IWOTH, S_IXOTH : for other, allow only read, write, execute respectively
303 mode_t sock_mode = (S_IRWXU | S_IRWXG | S_IRWXO); /* has 777 permission */
305 if (chmod(path, sock_mode) == CUSTOM_SOCKET_ERROR) {
306 MSG_FATAL("chmod: %s", strerror(errno));
307 return MSG_ERR_UNKNOWN;
310 if (listen(sockfd, CUSTOM_SOCKET_BACKLOG) == CUSTOM_SOCKET_ERROR) {
311 MSG_FATAL("listen: %s", strerror(errno));
312 return MSG_ERR_UNKNOWN;
322 msg_error_t MsgIpcServerSocket::accept()
326 if (sockfd == CUSTOM_SOCKET_ERROR) {
327 MSG_FATAL("server_socket not init");
328 return MSG_ERR_UNKNOWN;
331 struct sockaddr_un remote;
333 int t = sizeof(remote);
334 int fd = ::accept(sockfd, (struct sockaddr *)&remote, (socklen_t*) &t);
336 MSG_FATAL("accept: %s", strerror(errno));
337 return MSG_ERR_UNKNOWN;
341 MSG_DEBUG("%d is added", fd);
343 /* write the registerd fd */
344 write(fd, (const char*) &fd, sizeof(fd));
351 void MsgIpcServerSocket::close(int fd)
355 if (sockfd == CUSTOM_SOCKET_ERROR) {
356 MSG_FATAL("server_socket not init");
360 MSG_DEBUG("%d to be removed", fd);
363 std::map<int, int>::iterator it = mapFds.find(fd);
364 if (it == mapFds.end())
365 MSG_FATAL("No FD %d", fd);
371 for (it = mapFds.begin() ; it != mapFds.end() ; it++)
372 newmax = (it->second > newmax )? it->second : newmax;
375 MSG_DEBUG("fd %d removal done", fd);
381 int MsgIpcServerSocket::readn( int fd, char *buf, unsigned 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)
431 /* read the data in subsequence */
433 unsigned int ulen = (unsigned int)*len;
434 *buf = new char[ulen+1];
436 n = readn(fd, *buf, ulen);
438 if ((unsigned int)n != 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, unsigned int len)
455 /* MSG_NOSIGNAL to prevent SIGPIPE Error */
456 /* MSG_DONTWAIT to avoid socket block */
457 nwrite = ::send(fd, (const void*) buf, nleft, MSG_NOSIGNAL|MSG_DONTWAIT);
460 MSG_FATAL("write: %s", strerror(errno));
462 } else if (nwrite == 0) { /* Nothing is send. */
474 int MsgIpcServerSocket::write(int fd, const char* buf, unsigned int len)
478 if (!buf || len <= 0) {
479 MSG_FATAL("buf [%p] and len [%d] MUST NOT NULL", buf, len);
480 return CUSTOM_SOCKET_ERROR;
483 MSG_DEBUG("for debug - fd : [%d], buf : [%p], len : [%d]", fd, buf, len);
485 /* send the data size first */
486 int n = writen(fd, (const char*)&len, sizeof(len));
488 if (n != sizeof(len)) {
489 MSG_FATAL("WARNING: write header_size[%d] not matched [%d]", n, sizeof(len));
490 return CUSTOM_SOCKET_ERROR;
493 /* send the data in subsequence */
494 n = writen(fd, buf, len);
496 MSG_DEBUG("Writing %d bytes", n);
498 if ((unsigned int)n != len) {
499 MSG_FATAL("Written byte (%d) is not matched to input byte (%d)", n, len);
500 return CUSTOM_SOCKET_ERROR;