2 * tel-plugin-socket-communicator
4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Ja-young Gu <jygu@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.
26 #include <sys/types.h>
27 #include <sys/socket.h>
30 #include "sipc_common.h"
33 typedef struct sockaddr_un server_addr_t;
47 static struct _sipc_channel* _find_channel_by_fd(GSList *l, int fd)
50 struct _sipc_channel *c = 0;
52 SIPC_CHECK_DATA_NULL( l, 0);
55 c = (struct _sipc_channel *) l->data;
65 static struct _sipc_channel* _find_channel_by_id(GSList *l, unsigned int id)
68 struct _sipc_channel *c = 0;
70 SIPC_CHECK_DATA_NULL( l, 0);
73 c = (struct _sipc_channel *) l->data;
84 static void _free_channel(gpointer data)
86 struct _sipc_channel *c = 0;
87 c = (struct _sipc_channel*) data;
93 g_source_remove(c->tag);
101 static int _server_deliver_data(struct _sipc_header *h, void *inparam, void **outparam, sipc_callback_t *cb)
105 SIPC_CHECK_DATA_NULL( ( h && cb ), -1);
107 ret = cb->func(h->ch_id, inparam, h->data_len, outparam, cb->data);
112 static gboolean _server_deregister_channel(struct _sipc_server *s, unsigned int ch_id, sipc_channel_type_e t)
114 struct _sipc_channel *ch = 0;
116 SIPC_CHECK_DATA_NULL( s, FALSE);
117 SIPC_CHECK_DATA_RANGE( t, SIPC_CHANNEL_TYPE_TX, SIPC_CHANNEL_TYPE_RX, FALSE);
120 case SIPC_CHANNEL_TYPE_TX:
121 ch = _find_channel_by_id(s->tx_chs, ch_id);
122 g_source_remove(ch->tag);
125 s->tx_chs = g_slist_remove(s->tx_chs, ch);
128 case SIPC_CHANNEL_TYPE_RX:
129 ch = _find_channel_by_id(s->rx_chs, ch_id);
132 s->rx_chs = g_slist_remove(s->rx_chs, ch);
145 static int _server_send(int fd, struct _sipc_header *h, const void *data)
151 SIPC_CHECK_DATA_NULL( h, FALSE);
153 p_len = sizeof(struct _sipc_header) + h->data_len;
154 p = g_new0(char, p_len);
156 memcpy(p, h, sizeof(struct _sipc_header));
158 if ((data && h->data_len))
159 memcpy(p + sizeof(struct _sipc_header), (char*) data, h->data_len);
161 ret = send(fd, p, p_len, MSG_NOSIGNAL);
163 dbg("send() ret = %d, fd = %d, p = %p, p_len = %d", fd, ret, p, p_len);
172 static gboolean _server_recv(int fd, struct _sipc_server *s)
175 struct _sipc_header h_req = { 0, };
176 struct _sipc_header h_rsp = { 0, };
178 dbg("recv from fd(%d)", fd);
180 memset(&h_req, 0, sizeof(struct _sipc_header));
181 memset(&h_rsp, 0, sizeof(struct _sipc_header));
183 ret = recv(fd, &h_req, sizeof(struct _sipc_header), MSG_NOSIGNAL);
185 dbg("error to get header in socket");
186 h_rsp.cmd = SIPC_ACK_FAIL;
187 _server_send(fd, &h_rsp, NULL);
190 dbg("recv header (size=%d)", ret);
193 case SIPC_SEND_DATA_SYNC:
194 case SIPC_SEND_DATA_ASYNC: {
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);
202 dbg("error to get header in socket");
203 h_rsp.cmd = SIPC_ACK_FAIL;
204 _server_send(fd, &h_rsp, NULL);
209 dbg("recv data (size=%d)", ret);
212 ret = _server_deliver_data(&h_req, (void*) in_d, (void **) &out_d, s->cb);
214 dbg("error to send data to communicator");
215 h_rsp.cmd = SIPC_ACK_FAIL;
216 _server_send(fd, &h_rsp, NULL);
221 h_rsp.cmd = SIPC_ACK_SUCCESS;
223 //dbg("out data (%s)", out_d);
224 h_rsp.data_len = strlen(out_d);
227 _server_send(fd, &h_rsp, out_d);
234 case SIPC_DEREGISTER_CHANNEL:
235 return _server_deregister_channel(s, h_req.ch_id, h_req.ch_type);
245 static gboolean _server_io_inspector(GIOChannel *ch, GIOCondition con, gpointer data)
248 fd = g_io_channel_unix_get_fd(ch);
251 _server_recv(fd, (struct _sipc_server*) data);
254 if (con & G_IO_HUP) {
255 // TODO: close channel
256 dbg("channel has been changed");
263 static gboolean _server_register_channel(struct _sipc_channel *ch, struct _sipc_server *s)
266 struct _sipc_header h_req = { 0, };
267 struct _sipc_header h_rsp = { 0, };
269 SIPC_CHECK_DATA_NULL( (ch && s), FALSE);
271 memset(&h_req, 0, sizeof(struct _sipc_header));
272 memset(&h_rsp, 0, sizeof(struct _sipc_header));
274 ret = recv(ch->fd, &h_req, sizeof(struct _sipc_header), MSG_NOSIGNAL);
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);
278 dbg("error in socket");
279 h_rsp.cmd = SIPC_ACK_FAIL;
281 _server_send(ch->fd, &h_rsp, NULL);
285 ch->id = h_req.ch_id;
286 ch->type = h_req.ch_type;
289 case SIPC_CHANNEL_TYPE_TX: {
292 gch = g_io_channel_unix_new(ch->fd);
294 dbg("error to create channel");
295 h_rsp.cmd = SIPC_ACK_FAIL;
297 _server_send(ch->fd, &h_rsp, NULL);
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);
303 s->tx_chs = g_slist_append(s->tx_chs, ch);
304 dbg("tx channel(fd=%d) is registered", ch->fd);
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);
314 h_rsp.cmd = SIPC_ACK_SUCCESS;
316 _server_send(ch->fd, &h_rsp, NULL);
321 static gboolean _server_accept(GIOChannel *ch, GIOCondition con, gpointer data)
323 struct _sipc_server *s = 0;
324 struct _sipc_channel *c = 0;
328 s = (struct _sipc_server *) data;
330 addr_len = sizeof(s->addr);
333 fd = accept(s->fd, (struct sockaddr*) s->addr, &addr_len);
335 printf("error : accept(), %s", strerror(errno));
339 c = g_new0( struct _sipc_channel, 1 );
342 return _server_register_channel(c, s);
348 struct _sipc_server* sipc_server_open(char *path)
352 struct _sipc_server *s;
354 SIPC_CHECK_DATA_NULL( path, 0);
358 s = g_new0( struct _sipc_server, 1 );
361 s->fd = socket(AF_UNIX, SOCK_STREAM, 0);
363 dbg("error : socket(), %s", strerror(errno));
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));
371 len = sizeof(s->addr->sun_family) + strlen(path);
374 ret = bind(s->fd, (struct sockaddr *) s->addr, len);
376 dbg("error : bind(), %s", strerror(errno));
381 ret = chmod(path, S_IRWXU | S_IRWXG | S_IRWXO);
383 dbg("error : chmod(), %s", strerror(errno));
388 ret = listen(s->fd, 255);
390 dbg("error : listen(), %s", strerror(errno));
397 gboolean sipc_server_register_rx_callback(struct _sipc_server *s, sipc_callback_t *cb)
399 SIPC_CHECK_DATA_NULL( (s && cb), FALSE);
406 gboolean sipc_server_run(struct _sipc_server *s)
411 SIPC_CHECK_DATA_NULL( s, FALSE);
413 ch = g_io_channel_unix_new(s->fd);
418 tag = g_io_add_watch(ch, G_IO_IN, (GIOFunc) _server_accept, s);
428 gboolean sipc_server_close(struct _sipc_server *s)
430 SIPC_CHECK_DATA_NULL( s, FALSE);
432 g_source_remove(s->tag);
438 g_slist_free_full(s->tx_chs, _free_channel);
439 g_slist_free_full(s->rx_chs, _free_channel);
446 int sipc_server_send(struct _sipc_server *s, unsigned int ch_id, const void *data, unsigned int data_len, int option)
448 struct _sipc_header h = { 0, };
449 struct _sipc_channel *c = 0;
451 SIPC_CHECK_DATA_NULL( s, FALSE);
455 h.data_len = data_len;
457 c = _find_channel_by_id(s->rx_chs, ch_id);
461 return _server_send(c->fd, &h, data);
464 gboolean sipc_server_broadcast(struct _sipc_server *s, const void *data, unsigned int data_len)
467 struct _sipc_header h = { 0, };
468 struct _sipc_channel *c = 0;
471 SIPC_CHECK_DATA_NULL( s, FALSE);
473 dbg("client count = %d", g_slist_length(s->rx_chs));
477 c = (struct _sipc_channel *) list->data;
479 h.cmd = SIPC_SEND_DATA_BROADCAST;
480 h.data_len = data_len;
483 ret = _server_send(c->fd, &h, data);
486 dbg("send fail. ret = %d", ret);
489 list = g_slist_next(list);