4 * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <sys/ioctl.h>
29 #include <systemd/sd-daemon.h>
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"
38 #define MAX_ARRAY_LEN 65535
39 #define PIMS_WAIT_MSEC 1000
41 static int _get_pid(int fd)
44 struct ucred uc = {0};
45 socklen_t uc_len = sizeof(uc);
46 ret = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &uc, &uc_len);
48 ERR("getsockopt() Fail(%d)", errno);
54 static bool _is_send_block(int fd)
58 ioctl(fd, TIOCOUTQ, &queue_size);
62 ret = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf_size, (socklen_t *)&rn);
64 ERR("getsockopt() Fail(%d)", errno);
65 DBG("remain size(%d)", queue_size);
68 if (buf_size < queue_size) {
69 DBG("send : buffer size(%d) < queue size(%d)", buf_size, queue_size);
75 static int _sub_timespec_in_msec(struct timespec *st)
77 struct timespec et = {0};
78 clock_gettime(CLOCK_REALTIME, &et);
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;
86 int socket_send(int fd, char *buf, int len)
93 struct timespec st = {0};
95 RETV_IF(NULL == buf, -1);
96 RETVM_IF(len <= 0, -1, "Invalid length(%d)", len);
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");
104 } else if (errno == EAGAIN) { /* same as EWOULDBLOCK */
105 if (false == retry) {
106 clock_gettime(CLOCK_REALTIME, &st);
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);
118 DBG("reset timeout and wait (%d)msec", PIMS_WAIT_MSEC);
119 clock_gettime(CLOCK_REALTIME, &st);
125 ERR("send error [%d]", errno);
127 } else if (passed_len == 0) {
131 length -= passed_len;
136 write_len = len - length;
138 if (write_len != len) {
139 WARN("WARN: buf_size [%d] != write_len[%d]", len, write_len);
142 VERBOSE("write_len [%d]", write_len);
147 int socket_recv(int fd, void **buf, unsigned int len)
149 unsigned int length = len;
154 RETV_IF(NULL == *buf, -1);
157 read_len = read(fd, (void *)temp, length);
161 else if (errno == EAGAIN)
163 else if (errno == EWOULDBLOCK)
165 else if (errno == EPIPE) {
166 ERR("connection closed : read err %d", errno, read_len, length);
169 return 0; /* connection closed */
171 ERR("read err %d, read_len :%d, length : %d", errno, read_len, length);
172 final_len = read_len;
174 } else if (read_len == 0)
182 final_len = (len-length);
184 if (len != final_len) {
185 WARN("WARN: buf_size [%d] != read_len[%d]\n", read_len, final_len);
189 ((char*)*buf)[len] = '\0';
194 int socket_send_data(int fd, char *buf, unsigned int len)
198 int remain_len = len;
200 if (len > MAX_ARRAY_LEN)
201 INFO("send long data : length(%d) ++++++++++++++++++++++++", len);
203 while (len > send_len) {
204 if (remain_len > MAX_ARRAY_LEN)
205 ret = socket_send(fd, (buf+send_len), MAX_ARRAY_LEN);
207 ret = socket_send(fd, (buf+send_len), remain_len);
210 ERR("socket_send error");
218 ERR("socket_send error");
225 int write_command(int fd, const uint64_t cmd)
227 uint64_t clear_cmd = 0;
228 int ret = write(fd, &clear_cmd, sizeof(clear_cmd));
230 ERR("write fail (%d)", ret);
232 return write(fd, &cmd, sizeof(cmd));
235 int read_command(int fd, uint64_t *cmd)
238 int len = TEMP_FAILURE_RETRY(read(fd, &dummy, sizeof(dummy)));
239 if (len == sizeof(dummy))
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
250 static char* __find_client_id(pims_ipc_svc_s *ipc_svc, int client_fd, int delete)
253 GList *cursor = NULL;
254 pims_ipc_client_map_s *client;
256 cursor = g_list_first(ipc_svc->client_id_fd_map);
258 client = cursor->data;
259 if (client && client->fd == client_fd) {
260 client_id = client->id;
263 ipc_svc->client_id_fd_map = g_list_delete_link(ipc_svc->client_id_fd_map,
269 cursor = cursor->next;
275 static int __send_identify(int fd, unsigned int seq_no, char *id, int id_len)
277 int total_len, length = 0;
279 total_len = sizeof(total_len) + sizeof(id_len) + id_len + sizeof(seq_no);
281 char buf[total_len+1];
282 memset(buf, 0x0, total_len+1);
284 memcpy(buf, &total_len, sizeof(total_len));
285 length += sizeof(total_len);
287 memcpy(buf+length, &id_len, sizeof(id_len));
288 length += sizeof(id_len);
289 memcpy(buf+length, id, id_len);
292 memcpy(buf+length, &(seq_no), sizeof(seq_no));
293 length += sizeof(seq_no);
295 return socket_send(fd, buf, length);
298 static int __recv_raw_data(int fd, pims_ipc_raw_data_s **data, int *init)
301 pims_ipc_raw_data_s *temp;
303 /* read the size of message. note that ioctl is non-blocking */
304 if (ioctl(fd, FIONREAD, &len)) {
305 ERR("ioctl() Fail(%d)", errno);
309 /* when server or client closed socket */
311 INFO("[IPC Socket] connection is closed");
315 temp = calloc(1, sizeof(pims_ipc_raw_data_s));
317 ERR("calloc() Fail(%d)", errno);
320 temp->client_id = NULL;
321 temp->client_id_len = 0;
322 temp->call_id = NULL;
323 temp->call_id_len = 0;
325 temp->has_data = FALSE;
331 unsigned int total_len = 0;
332 unsigned int has_data = FALSE;
335 ret = TEMP_FAILURE_RETRY(read(fd, &total_len, sizeof(total_len)));
337 ERR("read() Fail(%d)", errno);
342 ret = TEMP_FAILURE_RETRY(read(fd, &(temp->client_id_len), sizeof(temp->client_id_len)));
344 ERR("read() Fail(%d)", errno);
349 temp->client_id = calloc(1, temp->client_id_len+1);
350 if (NULL == temp->client_id) {
351 ERR("calloc() Fail");
354 ret = socket_recv(fd, (void *)&(temp->client_id), temp->client_id_len);
356 ERR("socket_recv() Fail(%d)", ret);
361 ret = TEMP_FAILURE_RETRY(read(fd, &(temp->seq_no), sizeof(temp->seq_no)));
363 ERR("read() Fail(%d)", ret);
368 if (total_len == read_len) {
374 ret = TEMP_FAILURE_RETRY(read(fd, &(temp->call_id_len), sizeof(temp->call_id_len)));
376 ERR("read() Fail(%d)", errno);
381 temp->call_id = calloc(1, temp->call_id_len+1);
382 ret = socket_recv(fd, (void *)&(temp->call_id), temp->call_id_len);
384 ERR("socket_recv() Fail(%d)", ret);
389 ret = TEMP_FAILURE_RETRY(read(fd, &has_data, sizeof(has_data)));
391 ERR("read() Fail(%d)", errno);
397 temp->has_data = TRUE;
398 ret = TEMP_FAILURE_RETRY(read(fd, &(temp->data_len), sizeof(temp->data_len)));
400 ERR("read() Fail(%d)", errno);
405 temp->data = calloc(1, temp->data_len+1);
406 ret = socket_recv(fd, (void *)&(temp->data), temp->data_len);
408 ERR("socket_recv() Fail");
414 INFO("client_id : %s, call_id : %s, seq_no : %d", temp->client_id, temp->call_id,
422 ERR("total_len(%d) client_id_len(%d)", total_len, temp->client_id_len);
423 worker_free_raw_data(temp);
432 static gboolean __process_init_request(int client_fd, pims_ipc_raw_data_s *req,
433 pims_ipc_svc_s *ipc_svc)
436 pims_ipc_client_map_s *client;
438 client = calloc(1, sizeof(pims_ipc_client_map_s));
439 if (NULL == client) {
440 ERR("calloc() Fail(%d)", errno);
443 client->fd = client_fd;
444 client->id = req->client_id;
446 req->client_id = NULL;
447 ipc_svc->client_id_fd_map = g_list_append(ipc_svc->client_id_fd_map, client);
449 worker_start_idle_worker(ipc_svc);
451 /* send server pid to client */
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));
456 worker_free_raw_data(req);
458 ERR("__send_identify() Fail");
465 static gboolean __process_request(int client_fd, pims_ipc_raw_data_s *req,
466 pims_ipc_svc_s *ipc_svc)
468 char *client_id = NULL;
469 pims_ipc_worker_data_s *worker_data;
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);
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");
483 if (!worker_data->fd) {
484 int ret = worker_wait_idle_worker_ready(worker_data);
489 worker_data = worker_find(ipc_svc, client_id);
493 worker_push_raw_data(worker_data, client_fd, req);
494 write_command(worker_data->fd, 1);
496 ERR("worker_find(%s) Fail[client_fd(%d)]", client_id, client_fd);
501 static gboolean __request_handler(GIOChannel *src, GIOCondition condition, gpointer data)
504 char *client_id = NULL;
505 pims_ipc_svc_s *ipc_svc = data;
507 RETV_IF(NULL == data, FALSE);
509 client_fd = g_io_channel_unix_get_fd(src);
511 if (G_IO_HUP & condition) {
512 INFO("client closed: client_fd(%d)", client_fd);
514 client_id = __find_client_id(ipc_svc, client_fd, TRUE);
516 worker_stop_client_worker(ipc_svc, client_id);
524 /* receive data from client */
527 pims_ipc_raw_data_s *req = NULL;
529 recv_len = __recv_raw_data(client_fd, &req, &init);
532 return __process_init_request(client_fd, req, ipc_svc);
534 return __process_request(client_fd, req, ipc_svc);
536 ERR("receive invalid : %d", client_fd);
543 static gboolean __socket_handler(GIOChannel *src, GIOCondition condition, gpointer data)
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;
552 sockfd = ipc_svc->sockfd;
554 client_sockfd = accept(sockfd, (struct sockaddr *)&clientaddr, &client_len);
555 if (-1 == client_sockfd) {
557 char buf[1024] = {0};
558 errmsg = strerror_r(errno, buf, sizeof(buf));
560 ERR("accept error : %s", errmsg);
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);
572 void socket_set_handler(void *user_data)
575 struct sockaddr_un addr;
576 GIOChannel *gio = NULL;
577 pims_ipc_svc_s *ipc_svc = user_data;
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;
583 unlink(ipc_svc->service);
584 ipc_svc->sockfd = socket(PF_UNIX, SOCK_STREAM, 0);
586 bzero(&addr, sizeof(addr));
587 addr.sun_family = AF_UNIX;
588 snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", ipc_svc->service);
590 ret = bind(ipc_svc->sockfd, (struct sockaddr *)&addr, sizeof(addr));
592 ERR("bind() Fail(%d)", errno);
593 ret = listen(ipc_svc->sockfd, 30);
595 ret = chown(ipc_svc->service, getuid(), ipc_svc->group);
596 ret = chmod(ipc_svc->service, ipc_svc->mode);
599 gio = g_io_channel_unix_new(ipc_svc->sockfd);
601 g_io_add_watch(gio, G_IO_IN, __socket_handler, ipc_svc);