ab40179e13d7f240122af6b7ab9cb4a530bf07e3
[framework/telephony/tel-plugin-socket_communicator.git] / common / src / sipc_server.c
1 /*
2  * tel-plugin-socket-communicator
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Ja-young Gu <jygu@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 #include <stdio.h>
22 #include <string.h>
23
24 #include <errno.h>
25 #include <sys/un.h>
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <sys/stat.h>
29
30 #include "sipc_common.h"
31 #include "sipc.h"
32
33 typedef struct sockaddr_un server_addr_t;
34
35 struct _sipc_server {
36         int fd;
37         server_addr_t*   addr;
38         GSList*                  tx_chs;
39         GSList*                  rx_chs;
40         sipc_callback_t* cb;
41         guint                    tag;
42 };
43
44
45 // Utility
46 #if 0
47 static struct _sipc_channel* _find_channel_by_fd(GSList *l, int fd)
48 {
49         int ret = -1;
50         struct _sipc_channel *c = 0;
51
52         SIPC_CHECK_DATA_NULL( l, 0);
53
54         while (l) {
55                 c = (struct _sipc_channel *) l->data;
56                 if (c->fd == fd) {
57                         return c;
58                 }
59         }
60
61         return 0;
62 }
63 #endif
64
65 static struct _sipc_channel* _find_channel_by_id(GSList *l, unsigned int id)
66 {
67         int ret = -1;
68         struct _sipc_channel *c = 0;
69
70         SIPC_CHECK_DATA_NULL( l, 0);
71
72         while (l) {
73                 c = (struct _sipc_channel *) l->data;
74                 if (c->id == id) {
75                         return c;
76                 }
77
78                 l = l->next;
79         }
80
81         return 0;
82 }
83
84 static void _free_channel(gpointer data)
85 {
86         struct _sipc_channel *c = 0;
87         c = (struct _sipc_channel*) data;
88
89         c->id = 0;
90         close(c->fd);
91
92         if (!c->tag)
93                 g_source_remove(c->tag);
94
95         g_free(c);
96 }
97
98
99 // Static Function
100
101 static int _server_deliver_data(struct _sipc_header *h, void *inparam, void **outparam, sipc_callback_t *cb)
102 {
103         int ret = -1;
104
105         SIPC_CHECK_DATA_NULL( ( h && cb ), -1);
106
107         ret = cb->func(h->ch_id, inparam, h->data_len, outparam, cb->data);
108
109         return ret;
110 }
111
112 static gboolean _server_deregister_channel(struct _sipc_server *s, unsigned int ch_id, sipc_channel_type_e t)
113 {
114         struct _sipc_channel *ch = 0;
115
116         SIPC_CHECK_DATA_NULL( s, FALSE);
117         SIPC_CHECK_DATA_RANGE( t, SIPC_CHANNEL_TYPE_TX, SIPC_CHANNEL_TYPE_RX, FALSE);
118
119         switch (t) {
120                 case SIPC_CHANNEL_TYPE_TX:
121                         ch = _find_channel_by_id(s->tx_chs, ch_id);
122                         g_source_remove(ch->tag);
123                         close(ch->fd);
124
125                         s->tx_chs = g_slist_remove(s->tx_chs, ch);
126                         break;
127
128                 case SIPC_CHANNEL_TYPE_RX:
129                         ch = _find_channel_by_id(s->rx_chs, ch_id);
130                         close(ch->fd);
131
132                         s->rx_chs = g_slist_remove(s->rx_chs, ch);
133                         break;
134
135                 default:
136                         return FALSE;
137         }
138
139         if (!ch)
140                 g_free(ch);
141
142         return TRUE;
143 }
144
145 static int _server_send(int fd, struct _sipc_header *h, const void *data)
146 {
147         int p_len;
148         char *p;
149         int ret = -1;
150
151         SIPC_CHECK_DATA_NULL( h, FALSE);
152
153         p_len = sizeof(struct _sipc_header) + h->data_len;
154         p = g_new0(char, p_len);
155
156         memcpy(p, h, sizeof(struct _sipc_header));
157
158         if ((data && h->data_len))
159                 memcpy(p + sizeof(struct _sipc_header), (char*) data, h->data_len);
160
161         ret = send(fd, p, p_len, MSG_NOSIGNAL);
162         if (ret < 0) {
163                 dbg("send() ret = %d, fd = %d, p = %p, p_len = %d", fd, ret, p, p_len);
164                 g_free(p);
165                 return -1;
166         }
167
168         g_free(p);
169         return 0;
170 }
171
172 static gboolean _server_recv(int fd, struct _sipc_server *s)
173 {
174         int ret = -1;
175         struct _sipc_header h_req = { 0, };
176         struct _sipc_header h_rsp = { 0, };
177
178         dbg("recv from fd(%d)", fd);
179
180         memset(&h_req, 0, sizeof(struct _sipc_header));
181         memset(&h_rsp, 0, sizeof(struct _sipc_header));
182
183         ret = recv(fd, &h_req, sizeof(struct _sipc_header), MSG_NOSIGNAL);
184         if (ret < 0) {
185                 dbg("error to get header in socket");
186                 h_rsp.cmd = SIPC_ACK_FAIL;
187                 _server_send(fd, &h_rsp, NULL);
188                 return FALSE;
189         }
190         dbg("recv header (size=%d)", ret);
191
192         switch (h_req.cmd) {
193                 case SIPC_SEND_DATA_SYNC:
194                 case SIPC_SEND_DATA_ASYNC: {
195                         char *in_d = NULL;
196                         char *out_d = NULL;
197
198                         if (h_req.data_len > 0) {
199                                 in_d = g_new0( char, h_req.data_len+1 );
200                                 ret = recv(fd, in_d, h_req.data_len, MSG_NOSIGNAL);
201                                 if (ret < 0) {
202                                         dbg("error to get header in socket");
203                                         h_rsp.cmd = SIPC_ACK_FAIL;
204                                         _server_send(fd, &h_rsp, NULL);
205                                         g_free(in_d);
206                                         return FALSE;
207                                 }
208
209                                 dbg("recv data (size=%d)", ret);
210                         }
211
212                         ret = _server_deliver_data(&h_req, (void*) in_d, (void **) &out_d, s->cb);
213                         if (ret < 0) {
214                                 dbg("error to send data to communicator");
215                                 h_rsp.cmd = SIPC_ACK_FAIL;
216                                 _server_send(fd, &h_rsp, NULL);
217                                 g_free(in_d);
218                                 return FALSE;
219                         }
220
221                         h_rsp.cmd = SIPC_ACK_SUCCESS;
222                         if (out_d) {
223                                 //dbg("out data (%s)", out_d);
224                                 h_rsp.data_len = strlen(out_d);
225                         }
226
227                         _server_send(fd, &h_rsp, out_d);
228                         g_free(in_d);
229                         g_free(out_d);
230                         return TRUE;
231                 }
232                         break;
233
234                 case SIPC_DEREGISTER_CHANNEL:
235                         return _server_deregister_channel(s, h_req.ch_id, h_req.ch_type);
236                         break;
237
238                 default:
239                         break;
240         }
241
242         return FALSE;
243 }
244
245 static gboolean _server_io_inspector(GIOChannel *ch, GIOCondition con, gpointer data)
246 {
247         int fd = 0;
248         fd = g_io_channel_unix_get_fd(ch);
249
250         if (con & G_IO_IN) {
251                 _server_recv(fd, (struct _sipc_server*) data);
252         }
253
254         if (con & G_IO_HUP) {
255                 // TODO: close channel
256                 dbg("channel has been changed");
257                 return FALSE;
258         }
259
260         return TRUE;
261 }
262
263 static gboolean _server_register_channel(struct _sipc_channel *ch, struct _sipc_server *s)
264 {
265         int ret = -1;
266         struct _sipc_header h_req = { 0, };
267         struct _sipc_header h_rsp = { 0, };
268
269         SIPC_CHECK_DATA_NULL( (ch && s), FALSE);
270
271         memset(&h_req, 0, sizeof(struct _sipc_header));
272         memset(&h_rsp, 0, sizeof(struct _sipc_header));
273
274         ret = recv(ch->fd, &h_req, sizeof(struct _sipc_header), MSG_NOSIGNAL);
275
276         //dbg("recv data(%d) for register ch->fd(%d), id(%d) command(%d) type(%d)", ret, ch->fd, h.ch_id, h.cmd, h.ch_type);
277         if (ret < 0) {
278                 dbg("error in socket");
279                 h_rsp.cmd = SIPC_ACK_FAIL;
280                 h_rsp.data_len = 0;
281                 _server_send(ch->fd, &h_rsp, NULL);
282                 return FALSE;
283         }
284
285         ch->id = h_req.ch_id;
286         ch->type = h_req.ch_type;
287
288         switch (ch->type) {
289                 case SIPC_CHANNEL_TYPE_TX: {
290                         GIOChannel *gch;
291
292                         gch = g_io_channel_unix_new(ch->fd);
293                         if (!gch) {
294                                 dbg("error to create channel");
295                                 h_rsp.cmd = SIPC_ACK_FAIL;
296                                 h_rsp.data_len = 0;
297                                 _server_send(ch->fd, &h_rsp, NULL);
298                                 return FALSE;
299                         }
300
301                         ch->tag = g_io_add_watch(gch, (G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL), (GIOFunc) _server_io_inspector, s);
302
303                         s->tx_chs = g_slist_append(s->tx_chs, ch);
304                         dbg("tx channel(fd=%d) is registered", ch->fd);
305                 }
306                         break;
307
308                 case SIPC_CHANNEL_TYPE_RX:
309                         s->rx_chs = g_slist_append(s->rx_chs, ch);
310                         dbg("rx channel(fd=%d) is registered", ch->fd);
311                         break;
312         }
313
314         h_rsp.cmd = SIPC_ACK_SUCCESS;
315         h_rsp.data_len = 0;
316         _server_send(ch->fd, &h_rsp, NULL);
317
318         return TRUE;
319 }
320
321 static gboolean _server_accept(GIOChannel *ch, GIOCondition con, gpointer data)
322 {
323         struct _sipc_server *s = 0;
324         struct _sipc_channel *c = 0;
325         int fd = 0;
326         int addr_len;
327
328         s = (struct _sipc_server *) data;
329
330         addr_len = sizeof(s->addr);
331
332         errno = 0;
333         fd = accept(s->fd, (struct sockaddr*) s->addr, &addr_len);
334         if (fd < 0) {
335                 printf("error : accept(), %s", strerror(errno));
336                 return FALSE;
337         }
338
339         c = g_new0( struct _sipc_channel, 1 );
340         c->fd = fd;
341
342         return _server_register_channel(c, s);
343 }
344
345
346 // API Set
347
348 struct _sipc_server* sipc_server_open(char *path)
349 {
350         int ret = -1;
351         int len = 0;
352         struct _sipc_server *s;
353
354         SIPC_CHECK_DATA_NULL( path, 0);
355
356         unlink(path);
357
358         s = g_new0( struct _sipc_server, 1 );
359
360         errno = 0;
361         s->fd = socket(AF_UNIX, SOCK_STREAM, 0);
362         if (s->fd < 0) {
363                 dbg("error : socket(), %s", strerror(errno));
364                 return 0;
365         }
366
367         s->addr = g_new0(server_addr_t, 1 );
368         s->addr->sun_family = AF_UNIX;
369         strncpy(s->addr->sun_path, path, sizeof(s->addr->sun_path));
370
371         len = sizeof(s->addr->sun_family) + strlen(path);
372
373         errno = 0;
374         ret = bind(s->fd, (struct sockaddr *) s->addr, len);
375         if (ret < 0) {
376                 dbg("error : bind(), %s", strerror(errno));
377                 return 0;
378         }
379
380         errno = 0;
381         ret = chmod(path, S_IRWXU | S_IRWXG | S_IRWXO);
382         if (ret < 0) {
383                 dbg("error : chmod(), %s", strerror(errno));
384                 return 0;
385         }
386
387         errno = 0;
388         ret = listen(s->fd, 255);
389         if (ret < 0) {
390                 dbg("error : listen(), %s", strerror(errno));
391                 return 0;
392         }
393
394         return s;
395 }
396
397 gboolean sipc_server_register_rx_callback(struct _sipc_server *s, sipc_callback_t *cb)
398 {
399         SIPC_CHECK_DATA_NULL( (s && cb), FALSE);
400
401         s->cb = cb;
402
403         return TRUE;
404 }
405
406 gboolean sipc_server_run(struct _sipc_server *s)
407 {
408         GIOChannel *ch = 0;
409         int tag = 0;
410
411         SIPC_CHECK_DATA_NULL( s, FALSE);
412
413         ch = g_io_channel_unix_new(s->fd);
414         if (!ch) {
415                 return FALSE;
416         }
417
418         tag = g_io_add_watch(ch, G_IO_IN, (GIOFunc) _server_accept, s);
419         if (!tag) {
420                 return FALSE;
421         }
422
423         s->tag = tag;
424
425         return TRUE;
426 }
427
428 gboolean sipc_server_close(struct _sipc_server *s)
429 {
430         SIPC_CHECK_DATA_NULL( s, FALSE);
431
432         g_source_remove(s->tag);
433         close(s->fd);
434
435         g_free(s->addr);
436         g_free(s->cb);
437
438         g_slist_free_full(s->tx_chs, _free_channel);
439         g_slist_free_full(s->rx_chs, _free_channel);
440
441         g_free(s);
442
443         return TRUE;
444 }
445
446 int sipc_server_send(struct _sipc_server *s, unsigned int ch_id, const void *data, unsigned int data_len, int option)
447 {
448         struct _sipc_header h = { 0, };
449         struct _sipc_channel *c = 0;
450
451         SIPC_CHECK_DATA_NULL( s, FALSE);
452
453         h.ch_id = ch_id;
454         h.cmd = option;
455         h.data_len = data_len;
456
457         c = _find_channel_by_id(s->rx_chs, ch_id);
458         if (!c)
459                 return -1;
460
461         return _server_send(c->fd, &h, data);
462 }
463
464 gboolean sipc_server_broadcast(struct _sipc_server *s, const void *data, unsigned int data_len)
465 {
466         int ret = -1;
467         struct _sipc_header h = { 0, };
468         struct _sipc_channel *c = 0;
469         GSList *list;
470
471         SIPC_CHECK_DATA_NULL( s, FALSE);
472
473         dbg("client count = %d", g_slist_length(s->rx_chs));
474
475         list = s->rx_chs;
476         while (list) {
477                 c = (struct _sipc_channel *) list->data;
478
479                 h.cmd = SIPC_SEND_DATA_BROADCAST;
480                 h.data_len = data_len;
481
482                 errno = 0;
483                 ret = _server_send(c->fd, &h, data);
484                 if (ret < 0) {
485                         // dbg
486                         dbg("send fail. ret = %d", ret);
487                 }
488
489                 list = g_slist_next(list);
490         }
491
492         return 0;
493 }