clean up: devied files, remove router
[platform/core/pim/pims-ipc.git] / src / pims-socket.c
1 /*
2  * PIMS IPC
3  *
4  * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an AS IS BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <string.h>
23 #include <glib.h>
24 #include <errno.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <sys/ioctl.h>
28 #include <sys/un.h>
29 #include <systemd/sd-daemon.h>
30 #include <sys/stat.h>
31
32 #include "pims-internal.h"
33 #include "pims-ipc-data-internal.h"
34 #include "pims-ipc-worker.h"
35 #include "pims-ipc-utils.h"
36 #include "pims-socket.h"
37
38 #define MAX_ARRAY_LEN 65535
39 #define PIMS_WAIT_MSEC 1000
40
41 static int _get_pid(int fd)
42 {
43         int ret = 0;
44         struct ucred uc = {0};
45         socklen_t uc_len = sizeof(uc);
46         ret = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &uc, &uc_len);
47         if (ret < 0) {
48                 ERR("getsockopt() Fail(%d)", errno);
49                 return -1;
50         }
51         return uc.pid;
52 }
53
54 static bool _is_send_block(int fd)
55 {
56         int ret = 0;
57         int queue_size = 0;
58         ioctl(fd, TIOCOUTQ, &queue_size);
59
60         int buf_size = 0;
61         int rn = sizeof(int);
62         ret = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf_size, (socklen_t *)&rn);
63         if (ret < 0) {
64                 ERR("getsockopt() Fail(%d)", errno);
65                 DBG("remain size(%d)", queue_size);
66                 return false;
67         }
68         if (buf_size < queue_size) {
69                 DBG("send : buffer size(%d) < queue size(%d)", buf_size, queue_size);
70                 return true;
71         }
72         return false;
73 }
74
75 static int _sub_timespec_in_msec(struct timespec *st)
76 {
77         struct timespec et = {0};
78         clock_gettime(CLOCK_REALTIME, &et);
79
80         /* 3 digits for sec, 3 digits for msec */
81         int s_msec = ((st->tv_sec % 1000) * 1000) + (st->tv_nsec / 1000000);
82         int e_msec = ((et.tv_sec % 1000) * 1000) + (et.tv_nsec / 1000000);
83         return e_msec - s_msec;
84 }
85
86 int socket_send(int fd, char *buf, int len)
87 {
88         int length = len;
89         int passed_len = 0;
90         int write_len = 0;
91
92         bool retry = false;
93         struct timespec st = {0};
94
95         RETV_IF(NULL == buf, -1);
96         RETVM_IF(len <= 0, -1, "Invalid length(%d)", len);
97
98         while (length > 0) {
99                 passed_len = send(fd, (const void *)buf, length, MSG_DONTWAIT | MSG_NOSIGNAL);
100                 if (passed_len == -1) {
101                         if (errno == EINTR) {
102                                 ERR("EINTR error. send retry");
103                                 continue;
104                         } else if (errno == EAGAIN) { /* same as EWOULDBLOCK */
105                                 if (false == retry) {
106                                         clock_gettime(CLOCK_REALTIME, &st);
107                                         retry = true;
108                                 } else {
109                                         int diff_msec = _sub_timespec_in_msec(&st);
110                                         if (PIMS_WAIT_MSEC < diff_msec) {
111                                                 ERR("EAGAIN error. send retry");
112                                                 DBG("send timestamp (%d.%d)sec and wait (%d)msec", st.tv_sec, st.tv_nsec, diff_msec);
113                                                 int pid = _get_pid(fd);
114                                                 if (true == _is_send_block(fd)) {
115                                                         DBG("send blocked. kill fd(%d) pid(%d)", fd, pid);
116                                                         return -1;
117                                                 } else {
118                                                         DBG("reset timeout and wait (%d)msec", PIMS_WAIT_MSEC);
119                                                         clock_gettime(CLOCK_REALTIME, &st);
120                                                 }
121                                         }
122                                 }
123                                 continue;
124                         }
125                         ERR("send error [%d]", errno);
126                         break;
127                 } else if (passed_len == 0) {
128                         break;
129                 }
130
131                 length -= passed_len;
132                 buf += passed_len;
133
134                 retry = false;
135         }
136         write_len = len - length;
137
138         if (write_len != len) {
139                 WARN("WARN: buf_size [%d] != write_len[%d]", len, write_len);
140                 return -1;
141         }
142         VERBOSE("write_len [%d]", write_len);
143
144         return write_len;
145 }
146
147 int socket_recv(int fd, void **buf, unsigned int len)
148 {
149         unsigned int length = len;
150         int read_len = 0;
151         int final_len = 0;
152         char *temp = *buf;
153
154         RETV_IF(NULL == *buf, -1);
155
156         while (length > 0) {
157                 read_len = read(fd, (void *)temp, length);
158                 if (read_len < 0) {
159                         if (errno == EINTR)
160                                 continue;
161                         else if (errno == EAGAIN)
162                                 continue;
163                         else if (errno == EWOULDBLOCK)
164                                 continue;
165                         else if (errno == EPIPE) {
166                                 ERR("connection closed : read err %d", errno, read_len, length);
167                                 free(*buf);
168                                 *buf = NULL;
169                                 return 0; /* connection closed */
170                         }
171                         ERR("read err %d, read_len :%d, length : %d", errno, read_len, length);
172                         final_len = read_len;
173                         break;
174                 } else if (read_len == 0)
175                         break;
176
177                 length -= read_len;
178                 temp += read_len;
179         }
180
181         if (final_len == 0)
182                 final_len = (len-length);
183
184         if (len != final_len) {
185                 WARN("WARN: buf_size [%d] != read_len[%d]\n", read_len, final_len);
186                 return -1;
187         }
188
189         ((char*)*buf)[len] = '\0';
190
191         return final_len;
192 }
193
194 int socket_send_data(int fd, char *buf, unsigned int len)
195 {
196         int ret = 0;
197         int send_len = 0;
198         int remain_len = len;
199
200         if (len > MAX_ARRAY_LEN)
201                 INFO("send long data : length(%d) ++++++++++++++++++++++++", len);
202
203         while (len > send_len) {
204                 if (remain_len > MAX_ARRAY_LEN)
205                         ret = socket_send(fd, (buf+send_len), MAX_ARRAY_LEN);
206                 else
207                         ret = socket_send(fd, (buf+send_len), remain_len);
208
209                 if (ret < 0) {
210                         ERR("socket_send error");
211                         break;
212                 }
213                 send_len += ret;
214                 remain_len -= ret;
215         }
216
217         if (ret < 0) {
218                 ERR("socket_send error");
219                 return -1;
220         }
221
222         return send_len;
223 }
224
225 int write_command(int fd, const uint64_t cmd)
226 {
227         uint64_t clear_cmd = 0;
228         int ret = write(fd, &clear_cmd, sizeof(clear_cmd));
229         if (ret < 0)
230                 ERR("write fail (%d)", ret);
231
232         return write(fd, &cmd, sizeof(cmd));
233 }
234
235 int read_command(int fd, uint64_t *cmd)
236 {
237         uint64_t dummy;
238         int len = TEMP_FAILURE_RETRY(read(fd, &dummy, sizeof(dummy)));
239         if (len == sizeof(dummy))
240                 *cmd = dummy;
241
242         return len;
243 }
244
245
246 /*
247  * if delete = TRUE, steal client_id, then free(client_id)
248  * if delete = FALSE, return client_id pointer, then do no call free(client_id
249  */
250 static char* __find_client_id(pims_ipc_svc_s *ipc_svc, int client_fd, int delete)
251 {
252         char *client_id;
253         GList *cursor = NULL;
254         pims_ipc_client_map_s *client;
255
256         cursor = g_list_first(ipc_svc->client_id_fd_map);
257         while (cursor) {
258                 client = cursor->data;
259                 if (client && client->fd == client_fd) {
260                         client_id = client->id;
261                         if (delete) {
262                                 client->id = NULL;
263                                 ipc_svc->client_id_fd_map = g_list_delete_link(ipc_svc->client_id_fd_map,
264                                                 cursor);
265                                 free(client);
266                         }
267                         return client_id;
268                 }
269                 cursor = cursor->next;
270         }
271         return NULL;
272 }
273
274
275 static int __send_identify(int fd, unsigned int seq_no, char *id, int id_len)
276 {
277         int total_len, length = 0;
278
279         total_len = sizeof(total_len) + sizeof(id_len) + id_len + sizeof(seq_no);
280
281         char buf[total_len+1];
282         memset(buf, 0x0, total_len+1);
283
284         memcpy(buf, &total_len, sizeof(total_len));
285         length += sizeof(total_len);
286
287         memcpy(buf+length, &id_len, sizeof(id_len));
288         length += sizeof(id_len);
289         memcpy(buf+length, id, id_len);
290         length += id_len;
291
292         memcpy(buf+length, &(seq_no), sizeof(seq_no));
293         length += sizeof(seq_no);
294
295         return socket_send(fd, buf, length);
296 }
297
298 static int __recv_raw_data(int fd, pims_ipc_raw_data_s **data, int *init)
299 {
300         int len = 0;
301         pims_ipc_raw_data_s *temp;
302
303         /* read the size of message. note that ioctl is non-blocking */
304         if (ioctl(fd, FIONREAD, &len)) {
305                 ERR("ioctl() Fail(%d)", errno);
306                 return -1;
307         }
308
309         /* when server or client closed socket */
310         if (len == 0) {
311                 INFO("[IPC Socket] connection is closed");
312                 return 0;
313         }
314
315         temp = calloc(1, sizeof(pims_ipc_raw_data_s));
316         if (NULL == temp) {
317                 ERR("calloc() Fail(%d)", errno);
318                 return -1;
319         }
320         temp->client_id = NULL;
321         temp->client_id_len = 0;
322         temp->call_id = NULL;
323         temp->call_id_len = 0;
324         temp->seq_no = 0;
325         temp->has_data = FALSE;
326         temp->data = NULL;
327         temp->data_len = 0;
328
329         int ret = 0;
330         int read_len = 0;
331         unsigned int total_len = 0;
332         unsigned int has_data = FALSE;
333
334         do {
335                 ret = TEMP_FAILURE_RETRY(read(fd, &total_len, sizeof(total_len)));
336                 if (-1 == ret) {
337                         ERR("read() Fail(%d)", errno);
338                         break;
339                 }
340                 read_len += ret;
341
342                 ret = TEMP_FAILURE_RETRY(read(fd, &(temp->client_id_len), sizeof(temp->client_id_len)));
343                 if (-1 == ret) {
344                         ERR("read() Fail(%d)", errno);
345                         break;
346                 }
347                 read_len += ret;
348
349                 temp->client_id = calloc(1, temp->client_id_len+1);
350                 if (NULL == temp->client_id) {
351                         ERR("calloc() Fail");
352                         return -1;
353                 }
354                 ret = socket_recv(fd, (void *)&(temp->client_id), temp->client_id_len);
355                 if (ret < 0) {
356                         ERR("socket_recv() Fail(%d)", ret);
357                         break;
358                 }
359                 read_len += ret;
360
361                 ret = TEMP_FAILURE_RETRY(read(fd, &(temp->seq_no), sizeof(temp->seq_no)));
362                 if (ret < 0) {
363                         ERR("read() Fail(%d)", ret);
364                         break;
365                 }
366                 read_len += ret;
367
368                 if (total_len == read_len) {
369                         *data = temp;
370                         *init = TRUE;
371                         return read_len;
372                 }
373
374                 ret  = TEMP_FAILURE_RETRY(read(fd, &(temp->call_id_len), sizeof(temp->call_id_len)));
375                 if (ret < 0) {
376                         ERR("read() Fail(%d)", errno);
377                         break;
378                 }
379                 read_len += ret;
380
381                 temp->call_id = calloc(1, temp->call_id_len+1);
382                 ret = socket_recv(fd, (void *)&(temp->call_id), temp->call_id_len);
383                 if (ret < 0) {
384                         ERR("socket_recv() Fail(%d)", ret);
385                         break;
386                 }
387                 read_len += ret;
388
389                 ret = TEMP_FAILURE_RETRY(read(fd, &has_data, sizeof(has_data)));
390                 if (ret < 0) {
391                         ERR("read() Fail(%d)", errno);
392                         break;
393                 }
394                 read_len += ret;
395
396                 if (has_data) {
397                         temp->has_data = TRUE;
398                         ret = TEMP_FAILURE_RETRY(read(fd, &(temp->data_len), sizeof(temp->data_len)));
399                         if (ret < 0) {
400                                 ERR("read() Fail(%d)", errno);
401                                 break;
402                         }
403                         read_len += ret;
404
405                         temp->data = calloc(1, temp->data_len+1);
406                         ret = socket_recv(fd, (void *)&(temp->data), temp->data_len);
407                         if (ret < 0) {
408                                 ERR("socket_recv() Fail");
409                                 break;
410                         }
411                         read_len += ret;
412                 }
413
414                 INFO("client_id : %s, call_id : %s, seq_no : %d", temp->client_id, temp->call_id,
415                                 temp->seq_no);
416
417                 *data = temp;
418                 *init = FALSE;
419         } while (0);
420
421         if (ret < 0) {
422                 ERR("total_len(%d) client_id_len(%d)", total_len, temp->client_id_len);
423                 worker_free_raw_data(temp);
424                 *data = NULL;
425                 *init = FALSE;
426                 return -1;
427         }
428
429         return read_len;
430 }
431
432 static gboolean __process_init_request(int client_fd, pims_ipc_raw_data_s *req,
433                 pims_ipc_svc_s *ipc_svc)
434 {
435         int ret;
436         pims_ipc_client_map_s *client;
437
438         client = calloc(1, sizeof(pims_ipc_client_map_s));
439         if (NULL == client) {
440                 ERR("calloc() Fail(%d)", errno);
441                 return FALSE;
442         }
443         client->fd = client_fd;
444         client->id = req->client_id;
445
446         req->client_id = NULL;
447         ipc_svc->client_id_fd_map = g_list_append(ipc_svc->client_id_fd_map, client);
448
449         worker_start_idle_worker(ipc_svc);
450
451         /* send server pid to client */
452         char temp[100];
453         snprintf(temp, sizeof(temp), "%d_%x", client_get_unique_sequence_number(), getpid());
454         ret = __send_identify(client_fd, req->seq_no, temp, strlen(temp));
455
456         worker_free_raw_data(req);
457         if (-1 == ret) {
458                 ERR("__send_identify() Fail");
459                 return FALSE;
460         }
461
462         return TRUE;
463 }
464
465 static gboolean __process_request(int client_fd, pims_ipc_raw_data_s *req,
466                 pims_ipc_svc_s *ipc_svc)
467 {
468         char *client_id = NULL;
469         pims_ipc_worker_data_s *worker_data;
470
471         client_id = __find_client_id(ipc_svc, client_fd, FALSE);
472         if (NULL == client_id) {
473                 ERR("__find_client_id(%d) Fail", client_fd);
474                 return FALSE;
475         }
476
477         if (UTILS_STR_EQUAL == strcmp(PIMS_IPC_CALL_ID_CREATE, req->call_id)) {
478                 worker_data = worker_get_idle_worker(ipc_svc, client_id);
479                 if (NULL == worker_data) {
480                         ERR("worker_get_idle_worker() Fail");
481                         return FALSE;
482                 }
483                 if (!worker_data->fd) {
484                         int ret = worker_wait_idle_worker_ready(worker_data);
485                         if (ret < 0)
486                                 return FALSE;
487                 }
488         } else {
489                 worker_data = worker_find(ipc_svc, client_id);
490         }
491
492         if (worker_data) {
493                 worker_push_raw_data(worker_data, client_fd, req);
494                 write_command(worker_data->fd, 1);
495         } else {
496                 ERR("worker_find(%s) Fail[client_fd(%d)]", client_id, client_fd);
497         }
498         return TRUE;
499 }
500
501 static gboolean __request_handler(GIOChannel *src, GIOCondition condition, gpointer data)
502 {
503         int client_fd;
504         char *client_id = NULL;
505         pims_ipc_svc_s *ipc_svc = data;
506
507         RETV_IF(NULL == data, FALSE);
508
509         client_fd = g_io_channel_unix_get_fd(src);
510
511         if (G_IO_HUP & condition) {
512                 INFO("client closed: client_fd(%d)", client_fd);
513                 /* Find client_id */
514                 client_id = __find_client_id(ipc_svc, client_fd, TRUE);
515                 if (client_id) {
516                         worker_stop_client_worker(ipc_svc, client_id);
517                         free(client_id);
518                 }
519
520                 close(client_fd);
521                 return FALSE;
522         }
523
524         /* receive data from client */
525         int recv_len;
526         int init = FALSE;
527         pims_ipc_raw_data_s *req = NULL;
528
529         recv_len = __recv_raw_data(client_fd, &req, &init);
530         if (0 < recv_len) {
531                 if (init)
532                         return __process_init_request(client_fd, req, ipc_svc);
533
534                 return __process_request(client_fd, req, ipc_svc);
535         } else {
536                 ERR("receive invalid : %d", client_fd);
537                 close(client_fd);
538                 return FALSE;
539         }
540 }
541
542
543 static gboolean __socket_handler(GIOChannel *src, GIOCondition condition, gpointer data)
544 {
545         int sockfd;
546         GIOChannel *channel;
547         int client_sockfd = -1;
548         struct sockaddr_un clientaddr;
549         socklen_t client_len = sizeof(clientaddr);
550         pims_ipc_svc_s *ipc_svc = data;
551
552         sockfd = ipc_svc->sockfd;
553
554         client_sockfd = accept(sockfd, (struct sockaddr *)&clientaddr, &client_len);
555         if (-1 == client_sockfd) {
556                 char *errmsg = NULL;
557                 char buf[1024] = {0};
558                 errmsg = strerror_r(errno, buf, sizeof(buf));
559                 if (errmsg)
560                         ERR("accept error : %s", errmsg);
561
562                 return TRUE;
563         }
564
565         channel = g_io_channel_unix_new(client_sockfd);
566         g_io_add_watch(channel, G_IO_IN|G_IO_HUP, __request_handler, data);
567         g_io_channel_unref(channel);
568
569         return TRUE;
570 }
571
572 void socket_set_handler(void *user_data)
573 {
574         int ret;
575         struct sockaddr_un addr;
576         GIOChannel *gio = NULL;
577         pims_ipc_svc_s *ipc_svc = user_data;
578
579         ret = sd_is_socket_unix(SD_LISTEN_FDS_START, SOCK_STREAM, -1, ipc_svc->service, 0);
580         if (sd_listen_fds(1) == 1 && 0 < ret) {
581                 ipc_svc->sockfd = SD_LISTEN_FDS_START;
582         } else {
583                 unlink(ipc_svc->service);
584                 ipc_svc->sockfd = socket(PF_UNIX, SOCK_STREAM, 0);
585
586                 bzero(&addr, sizeof(addr));
587                 addr.sun_family = AF_UNIX;
588                 snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", ipc_svc->service);
589
590                 ret = bind(ipc_svc->sockfd, (struct sockaddr *)&addr, sizeof(addr));
591                 if (ret != 0)
592                         ERR("bind() Fail(%d)", errno);
593                 ret = listen(ipc_svc->sockfd, 30);
594
595                 ret = chown(ipc_svc->service, getuid(), ipc_svc->group);
596                 ret = chmod(ipc_svc->service, ipc_svc->mode);
597         }
598
599         gio = g_io_channel_unix_new(ipc_svc->sockfd);
600
601         g_io_add_watch(gio, G_IO_IN, __socket_handler, ipc_svc);
602 }
603