1c9c5aaadb78a9cbf9e1cb4eb242e040890c222b
[framework/messaging/email-service.git] / email-ipc / email-socket / email-ipc-socket.c
1 /*
2 *  email-service
3 *
4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5 *
6 * Contact: Kyuho Jo <kyuho.jo@samsung.com>, Sunghyun Kwon <sh0701.kwon@samsung.com>
7
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
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
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.
19 *
20 */
21
22
23 #include "email-ipc-socket.h"
24 #include "email-ipc-build.h"
25
26 #include "email-debug-log.h"
27 #include "email-types.h"
28
29 #include <glib.h>
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 #include <malloc.h>
37
38 #include <errno.h>
39 #include <unistd.h>
40
41
42 EXPORT_API bool emipc_init_email_socket(int *fd)
43 {
44         bool ret = true;
45
46         *fd = socket(AF_UNIX, SOCK_STREAM, 0);
47
48         if (*fd < 0) {
49                 EM_DEBUG_EXCEPTION("socket creation fails!!!: %s", strerror(errno));
50                 ret = false;
51         }
52
53         EM_DEBUG_LOG("Socket fd = %d", *fd);
54
55         return ret;     
56 }
57
58 /*  Close */
59 EXPORT_API bool emipc_close_email_socket(int fd)
60 {
61         EM_DEBUG_FUNC_BEGIN("fd[%d] to be removed", fd);
62         int ret = true;
63
64         EM_DEBUG_LOG("fd %d removal done", fd);
65         close(fd);
66
67         EM_DEBUG_FUNC_END();
68         return ret;
69 }
70
71 static int emipc_writen(int fd, const char *buf, int len)
72 {
73         int length = len;
74         int passed_len = 0;
75
76         while (length > 0) {
77                 passed_len = send(fd, (const void *)buf, length, MSG_NOSIGNAL);
78                 if (passed_len == -1) {
79                         EM_DEBUG_LOG("write : %s", EM_STRERROR(errno));
80                         if (errno == EINTR) continue;
81                         return passed_len;
82                 } else if (passed_len == 0)
83                         break;
84                 length -= passed_len;
85                 buf += passed_len;
86         }
87         return (len - length);
88 }
89
90 EXPORT_API int emipc_send_email_socket(int fd, unsigned char *buf, int len)
91 {
92         EM_DEBUG_FUNC_BEGIN("fd [%d], buffer [%p], buf_len [%d]", fd, buf, len);
93
94         if (!buf) {
95                 EM_DEBUG_EXCEPTION("No data to send");
96                 return 0;
97         }
98
99         EM_DEBUG_LOG("Sending %dB data to [fd = %d]", len, fd);
100         
101         int write_len = emipc_writen(fd, (char*) buf, len);
102         if ( write_len != len) {
103                 EM_DEBUG_LOG("WARNING: buf_size [%d] != write_len[%d]", len, write_len);
104                 return EMF_ERROR_IPC_SOCKET_FAILURE;
105         }
106         EM_DEBUG_FUNC_END();
107         return write_len;
108 }
109
110 static int emipc_readn(int fd, char *buf, int len)
111 {
112         int length = len;
113         int read_len = 0;
114
115         while (length > 0) {
116                 read_len = read(fd, (void *)buf, length);
117                 if (read_len < 0) {
118                         EM_DEBUG_EXCEPTION("Read : %s", EM_STRERROR(errno));
119                         if (errno == EINTR) continue;
120                         return read_len;
121                 } else if (read_len == 0)
122                         break;
123
124                 length -= read_len;
125                 buf += read_len;
126         }
127         return (len-length);
128 }
129
130
131 EXPORT_API int emipc_recv_email_socket(int fd, char **buf)
132 {
133         EM_DEBUG_FUNC_BEGIN();
134         
135         if (!buf) {
136                 EM_DEBUG_LOG("Buffer must not null");
137                 return EMF_ERROR_INVALID_PARAM;
138         }
139
140         int read_len = 0;
141         if (ioctl(fd, FIONREAD, &read_len)) {
142                 EM_DEBUG_EXCEPTION("ioctl: %s", strerror(errno));
143                 return EMF_ERROR_IPC_SOCKET_FAILURE;
144         }
145
146         *buf = (char *) malloc(read_len);
147         if (*buf == NULL) {
148                 EM_DEBUG_EXCEPTION("Malloc failed");
149                 return EMF_ERROR_OUT_OF_MEMORY;
150         }
151         memset(*buf, 0x00, read_len);
152         
153         EM_DEBUG_LOG("[IPC Socket] Receiving Body begins for [%d] bytes", read_len);
154         int len = emipc_readn(fd, *buf, read_len);
155         if (read_len != len) {
156                 EM_SAFE_FREE(*buf);
157                 EM_DEBUG_LOG("WARNING: buf_size [%d] != read_len[%d]", read_len, len);
158                 return EMF_ERROR_IPC_SOCKET_FAILURE;
159         }
160
161         EM_DEBUG_LOG("[IPC Socket] Receiving [%d] bytes Completed", len);
162
163         return len;
164 }
165
166 EXPORT_API int emipc_accept_email_socket(int fd)
167 {
168         EM_DEBUG_FUNC_BEGIN();
169         
170         if (fd == -1) {
171                 EM_DEBUG_LOG("Server_socket not init");
172                 return EMF_ERROR_INVALID_PARAM;
173         }
174         
175         struct sockaddr_un remote;
176         int remote_len = sizeof(remote);
177         int client_fd = accept(fd, (struct sockaddr *)&remote, (socklen_t*) &remote_len);
178         if (client_fd == -1) {
179                 EM_DEBUG_LOG("accept: %s", EM_STRERROR(errno));
180                 return EMF_ERROR_IPC_SOCKET_FAILURE;
181         }
182
183         EM_DEBUG_LOG("%d is added", client_fd);
184         
185         EM_DEBUG_FUNC_END();
186         return client_fd;
187 }
188
189 EXPORT_API int emipc_open_email_socket(int fd, const char *path)
190 {
191         EM_DEBUG_FUNC_BEGIN("path [%s]", path);
192
193         if (!path || strlen(path) > 108) {
194                 EM_DEBUG_LOG("Path is null");
195                 return EMF_ERROR_IPC_SOCKET_FAILURE;
196         }
197         
198         if (fd <= 0) {
199                 EM_DEBUG_LOG("Socket not created %d", fd);
200                 return EMF_ERROR_IPC_SOCKET_FAILURE;
201         }
202
203         struct sockaddr_un local;
204         local.sun_family = AF_UNIX;
205         strcpy(local.sun_path, path);
206         unlink(local.sun_path);
207
208         int len = strlen(local.sun_path) + sizeof(local.sun_family);
209
210         if (bind(fd, (struct sockaddr *)&local, len) == -1) {
211                 EM_DEBUG_LOG("bind: %s", EM_STRERROR(errno));
212                 return EMF_ERROR_IPC_SOCKET_FAILURE;
213         }
214
215         /**
216          * determine permission of socket file
217          *
218          *  - S_IRWXU : for user, allow read and write and execute
219          *  - S_IRWXG : for group, allow read and write and execute
220          *  - S_IRWXO : for other, allow read and write and execute
221          *
222          *  - S_IRUSR, S_IWUSR, S_IXUSR : for user, allow only read, write, execute respectively
223          *  - S_IRGRP, S_IWGRP, S_IXGRP : for group, allow only read, write, execute respectively
224          *  - S_IROTH, S_IWOTH, S_IXOTH : for other, allow only read, write, execute respectively
225          */
226         mode_t sock_mode = (S_IRWXU | S_IRWXG | S_IRWXO); /*  has 777 permission */
227
228         if (chmod(path, sock_mode) == -1) {
229                 EM_DEBUG_LOG("chmod: %s", EM_STRERROR(errno));
230                 return EMF_ERROR_IPC_SOCKET_FAILURE;
231         }
232
233         if (listen(fd, 10) == -1) {
234                 EM_DEBUG_LOG("listen: %s", EM_STRERROR(errno));
235                 return EMF_ERROR_IPC_SOCKET_FAILURE;
236         }
237
238         EM_DEBUG_FUNC_END();
239         return fd;
240 }
241
242 EXPORT_API bool emipc_connect_email_socket(int fd)
243 {
244         EM_DEBUG_FUNC_BEGIN();
245         struct sockaddr_un server;
246         server.sun_family = AF_UNIX;
247         strcpy(server.sun_path, EM_SOCKET_PATH);
248
249         int len = strlen(server.sun_path) + sizeof(server.sun_family);
250         
251         if (connect(fd, (struct sockaddr *)&server, len) == -1) {
252                 EM_DEBUG_LOG("Cannot connect server %s", EM_STRERROR(errno));
253                 return false;
254         }
255
256         return true;
257 }
258