4 * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Kyuho Jo <kyuho.jo@samsung.com>, Sunghyun Kwon <sh0701.kwon@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
23 #include "email-ipc-socket.h"
24 #include "email-ipc-build.h"
26 #include "email-debug-log.h"
27 #include "email-types.h"
31 #include <sys/socket.h>
33 #include <sys/ioctl.h>
34 #include <sys/types.h>
41 #include <systemd/sd-daemon.h>
43 EXPORT_API bool emipc_init_email_socket(int *fd)
47 *fd = socket(AF_UNIX, SOCK_STREAM, 0);
50 EM_DEBUG_EXCEPTION("socket creation fails!!!: %s", strerror(errno));
54 EM_DEBUG_LOG("Socket fd = %d", *fd);
60 EXPORT_API void emipc_close_email_socket(int* fd)
62 EM_DEBUG_LOG("fd %d removal done", *fd);
67 /* returns positive write length,
68 * 0, when connection is closed
69 * -1, when send error */
70 static int emipc_writen(int fd, const char *buf, int len)
76 passed_len = send(fd, (const void *)buf, length, MSG_NOSIGNAL);
77 if (passed_len == -1) {
78 EM_DEBUG_LOG("write : %s", EM_STRERROR(errno));
79 if (errno == EINTR) continue;
80 else if (errno == EPIPE) return 0; /* connection closed */
81 else return passed_len; /* -1 */
82 } else if (passed_len == 0)
87 return (len - length);
90 /* returns positive value, when write success,
91 * 0, when socket connection is broken,
92 * EMAIL_ERROR_IPC_SOCKET_FAILURE, when write failure,
93 * EMAIL_ERROR_INVALID_PARAM, when wrong parameter */
94 EXPORT_API int emipc_send_email_socket(int fd, unsigned char *buf, int len)
96 EM_DEBUG_FUNC_BEGIN("fd [%d], buffer [%p], buf_len [%d]", fd, buf, len);
98 if (!buf || len <= 0) {
99 EM_DEBUG_EXCEPTION("No data to send %p, %d", buf, len);
100 return EMAIL_ERROR_INVALID_PARAM;
103 EM_DEBUG_LOG("Sending %dB data to [fd = %d]", len, fd);
105 int write_len = emipc_writen(fd, (char*) buf, len);
106 if ( write_len != len) {
107 if ( write_len == 0 ) return 0;
108 EM_DEBUG_LOG("WARNING: buf_size [%d] != write_len[%d]", len, write_len);
109 return EMAIL_ERROR_IPC_SOCKET_FAILURE;
115 static int emipc_readn(int fd, char *buf, int len)
121 read_len = read(fd, (void *)buf, length);
123 EM_DEBUG_EXCEPTION("Read : %s", EM_STRERROR(errno));
124 if (errno == EINTR) continue;
126 } else if (read_len == 0)
135 /* returns positive value when read success,
136 * 0, when socket is closed
137 * EMAIL_ERROR_IPC_SOCKET_FAILURE, when read failed
138 * EMAIL_ERROR_INVALID_PARAM when wrong parameter */
139 EXPORT_API int emipc_recv_email_socket(int fd, char **buf)
141 EM_DEBUG_FUNC_BEGIN();
144 EM_DEBUG_LOG("Buffer must not null");
145 return EMAIL_ERROR_INVALID_PARAM;
149 /* read the size of message. note that ioctl is non-blocking */
150 if (ioctl(fd, FIONREAD, &read_len)) {
151 EM_DEBUG_EXCEPTION("ioctl: %s", strerror(errno));
152 return EMAIL_ERROR_IPC_SOCKET_FAILURE;
154 /* when server or client closed socket */
155 if ( read_len == 0 ) {
156 EM_DEBUG_LOG("[IPC Socket] connection is closed");
160 *buf = (char *) malloc(read_len);
162 EM_DEBUG_EXCEPTION("Malloc failed");
163 return EMAIL_ERROR_OUT_OF_MEMORY;
165 memset(*buf, 0x00, read_len);
167 EM_DEBUG_LOG("[IPC Socket] Receiving [%d] bytes", read_len);
168 int len = emipc_readn(fd, *buf, read_len);
169 if (read_len != len) {
171 EM_DEBUG_LOG("WARNING: buf_size [%d] != read_len[%d]", read_len, len);
172 return EMAIL_ERROR_IPC_SOCKET_FAILURE;
175 EM_DEBUG_LOG("[IPC Socket] Receiving [%d] bytes Completed", len);
180 EXPORT_API int emipc_accept_email_socket(int fd)
182 EM_DEBUG_FUNC_BEGIN();
185 EM_DEBUG_LOG("Server_socket not init");
186 return EMAIL_ERROR_INVALID_PARAM;
189 struct sockaddr_un remote;
190 int remote_len = sizeof(remote);
191 int client_fd = accept(fd, (struct sockaddr *)&remote, (socklen_t*) &remote_len);
192 if (client_fd == -1) {
193 EM_DEBUG_LOG("accept: %s", EM_STRERROR(errno));
194 return EMAIL_ERROR_IPC_SOCKET_FAILURE;
197 EM_DEBUG_LOG("%d is added", client_fd);
203 EXPORT_API int emipc_open_email_socket(int fd, const char *path)
205 EM_DEBUG_FUNC_BEGIN("path [%s]", path);
208 if (strcmp(path, EM_SOCKET_PATH) == 0 &&
209 sd_listen_fds(1) == 1 &&
210 sd_is_socket_unix(SD_LISTEN_FDS_START, SOCK_STREAM, -1, EM_SOCKET_PATH, 0) > 0) {
212 sock_fd = SD_LISTEN_FDS_START + 0;
216 if (!path || EM_SAFE_STRLEN(path) > 108) {
217 EM_DEBUG_LOG("Path is null");
218 return EMAIL_ERROR_IPC_SOCKET_FAILURE;
222 EM_DEBUG_LOG("Socket not created %d", fd);
223 return EMAIL_ERROR_IPC_SOCKET_FAILURE;
226 struct sockaddr_un local;
227 local.sun_family = AF_UNIX;
228 strcpy(local.sun_path, path);
229 unlink(local.sun_path);
231 int len = EM_SAFE_STRLEN(local.sun_path) + sizeof(local.sun_family);
233 if (bind(fd, (struct sockaddr *)&local, len) == -1) {
234 EM_DEBUG_LOG("bind: %s", EM_STRERROR(errno));
235 return EMAIL_ERROR_IPC_SOCKET_FAILURE;
239 * determine permission of socket file
241 * - S_IRWXU : for user, allow read and write and execute
242 * - S_IRWXG : for group, allow read and write and execute
243 * - S_IRWXO : for other, allow read and write and execute
245 * - S_IRUSR, S_IWUSR, S_IXUSR : for user, allow only read, write, execute respectively
246 * - S_IRGRP, S_IWGRP, S_IXGRP : for group, allow only read, write, execute respectively
247 * - S_IROTH, S_IWOTH, S_IXOTH : for other, allow only read, write, execute respectively
249 mode_t sock_mode = (S_IRWXU | S_IRWXG | S_IRWXO); /* has 777 permission */
251 if (chmod(path, sock_mode) == -1) {
252 EM_DEBUG_LOG("chmod: %s", EM_STRERROR(errno));
253 return EMAIL_ERROR_IPC_SOCKET_FAILURE;
256 if (listen(fd, 10) == -1) {
257 EM_DEBUG_LOG("listen: %s", EM_STRERROR(errno));
258 return EMAIL_ERROR_IPC_SOCKET_FAILURE;
265 EXPORT_API bool emipc_connect_email_socket(int fd)
267 EM_DEBUG_FUNC_BEGIN();
268 struct sockaddr_un server;
269 server.sun_family = AF_UNIX;
270 strcpy(server.sun_path, EM_SOCKET_PATH);
272 int len = EM_SAFE_STRLEN(server.sun_path) + sizeof(server.sun_family);
274 if (connect(fd, (struct sockaddr *)&server, len) == -1) {
275 EM_DEBUG_LOG("Cannot connect server %s", EM_STRERROR(errno));