SRS: srs-client library, proper structures for protocol data
[samsung-ril.git] / srs.c
1 /**
2  * This file is part of samsung-ril.
3  *
4  * Copyright (C) 2011-2012 Paul Kocialkowski <contact@paulk.fr>
5  *
6  * samsung-ril is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * samsung-ril is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with samsung-ril.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include <fcntl.h>
22 #include <sys/stat.h>
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <sys/un.h>
26 #include <sys/select.h>
27
28 #include <arpa/inet.h>
29 #include <netinet/in.h>
30 #include <cutils/sockets.h>
31
32 #define LOG_TAG "RIL-SRS"
33 #include <utils/Log.h>
34
35 #include "samsung-ril.h"
36 #include "util.h"
37
38 int srs_client_register(struct srs_client_data *client_data, int fd)
39 {
40         struct srs_client_info *client;
41         struct list_head *list_end;
42         struct list_head *list;
43
44         if (client_data == NULL)
45                 return -1;
46
47         client = calloc(1, sizeof(struct srs_client_info));
48         if (client == NULL)
49                 return -1;
50
51         client->fd = fd;
52
53         list_end = client_data->clients;
54         while (list_end != NULL && list_end->next != NULL)
55                 list_end = list_end->next;
56
57         list = list_head_alloc((void *) client, list_end, NULL);
58
59         if (client_data->clients == NULL)
60                 client_data->clients = list;
61
62         return 0;
63 }
64
65 void srs_client_unregister(struct srs_client_data *client_data, struct srs_client_info *client)
66 {
67         struct list_head *list;
68
69         if (client_data == NULL || client == NULL)
70                 return;
71
72         list = client_data->clients;
73         while (list != NULL) {
74                 if (list->data == (void *) client) {
75                         memset(client, 0, sizeof(struct srs_client_info));
76                         free(client);
77
78                         if (list == client_data->clients)
79                                 client_data->clients = list->next;
80
81                         list_head_free(list);
82
83                         break;
84                 }
85 list_continue:
86                 list = list->next;
87         }
88 }
89
90 struct srs_client_info *srs_client_info_find(struct srs_client_data *client_data)
91 {
92         struct srs_client_info *client;
93         struct list_head *list;
94
95         list = client_data->clients;
96         while (list != NULL) {
97                 client = (struct srs_client_info *) list->data;
98                 if (client == NULL)
99                         goto list_continue;
100
101                 return client;
102
103 list_continue:
104                 list = list->next;
105         }
106
107         return NULL;
108 }
109
110 struct srs_client_info *srs_client_info_find_fd(struct srs_client_data *client_data, int fd)
111 {
112         struct srs_client_info *client;
113         struct list_head *list;
114
115         list = client_data->clients;
116         while (list != NULL) {
117                 client = (struct srs_client_info *) list->data;
118                 if (client == NULL)
119                         goto list_continue;
120
121                 if (client->fd == fd)
122                         return client;
123
124 list_continue:
125                 list = list->next;
126         }
127
128         return NULL;
129 }
130
131 int srs_client_info_fill_fd_set(struct srs_client_data *client_data, fd_set *fds)
132 {
133         struct srs_client_info *client;
134         struct list_head *list;
135         int fd_max;
136
137         if (client_data == NULL || fds == NULL)
138                 return -1;
139
140         fd_max = -1;
141         list = client_data->clients;
142         while (list != NULL) {
143                 client = (struct srs_client_info *) list->data;
144                 if (client == NULL)
145                         goto list_continue;
146
147                 FD_SET(client->fd, fds);
148                 if (client->fd > fd_max)
149                         fd_max = client->fd;
150
151 list_continue:
152                 list = list->next;
153         }
154
155         return fd_max;
156 }
157
158 int srs_client_info_get_fd_set(struct srs_client_data *client_data, fd_set *fds)
159 {
160         struct srs_client_info *client;
161         struct list_head *list;
162         int fd;
163
164         if (client_data == NULL || fds == NULL)
165                 return -1;
166
167         list = client_data->clients;
168         while (list != NULL) {
169                 client = (struct srs_client_info *) list->data;
170                 if (client == NULL)
171                         goto list_continue;
172
173                 if (FD_ISSET(client->fd, fds)) {
174                         FD_CLR(client->fd, fds);
175                         return client->fd;
176                 }
177
178 list_continue:
179                 list = list->next;
180         }
181
182         return -1;
183 }
184
185 int srs_client_send_message(struct srs_client_data *client_data, struct srs_message *message)
186 {
187         struct srs_header header;
188         void *data;
189
190         struct timeval timeout;
191         fd_set fds;
192         int rc;
193
194         if (client_data == NULL || message == NULL)
195                 return -1;
196
197         memset(&header, 0, sizeof(header));
198         header.length = message->length + sizeof(header);
199         header.group = SRS_GROUP(message->command);
200         header.index = SRS_INDEX(message->command);
201
202         data = calloc(1, header.length);
203         if (data == NULL)
204                 return -1;
205
206         memcpy(data, &header, sizeof(header));
207         memcpy((void *) ((char *) data + sizeof(header)), message->data, message->length);
208
209         memset(&timeout, 0, sizeof(timeout));
210         timeout.tv_usec = 300;
211
212         if (client_data->client_fd < 0)
213                 goto error;
214
215         FD_ZERO(&fds);
216         FD_SET(client_data->client_fd, &fds);
217
218         rc = select(client_data->client_fd + 1, NULL, &fds, NULL, &timeout);
219
220         if (!FD_ISSET(client_data->client_fd, &fds)) {
221                 LOGE("SRS write select failed on fd %d", client_data->client_fd);
222                 goto error;
223         }
224
225         rc = write(client_data->client_fd, data, header.length);
226         if (rc < (int) sizeof(struct srs_header)) {
227                 LOGE("SRS write failed on fd %d with %d bytes", client_data->client_fd, rc);
228                 goto error;
229         }
230
231         free(data);
232         return rc;
233
234 error:
235         free(data);
236         return 0;
237 }
238
239 int srs_client_send(struct srs_client_data *client_data, unsigned short command, void *data, int length)
240 {
241         struct srs_client_info *client;
242         struct srs_message message;
243         int rc;
244
245         if (client_data == NULL)
246                 return -1;
247
248         memset(&message, 0, sizeof(message));
249         message.command = command;
250         message.data = data;
251         message.length = length;
252
253         RIL_CLIENT_LOCK(client_data->client);
254         rc = srs_client_send_message(client_data, &message);
255         RIL_CLIENT_UNLOCK(client_data->client);
256
257         if (rc <= 0) {
258                 LOGD("SRS client with fd %d terminated", client_data->client_fd);
259
260                 client = srs_client_info_find_fd(client_data, client_data->client_fd);
261                 if (client != NULL)
262                         srs_client_unregister(client_data, client);
263                 close(client_data->client_fd);
264                 client_data->client_fd = -1;
265         }
266
267         return rc;
268 }
269
270 int srs_send(unsigned short command, void *data, int length)
271 {
272         struct srs_client_data *client_data;
273         int rc;
274
275         if (ril_data.srs_client == NULL || ril_data.srs_client->data == NULL)
276                 return -1;
277
278         client_data = (struct srs_client_data *) ril_data.srs_client->data;
279
280         LOGD("SEND SRS: fd=%d command=%d length=%d", client_data->client_fd, command, length);
281         if (data != NULL && length > 0) {
282                 LOGD("==== SRS DATA DUMP ====");
283                 hex_dump(data, length);
284                 LOGD("=======================");
285         }
286
287         return srs_client_send(client_data, command, data, length);
288 }
289
290 int srs_client_recv(struct srs_client_data *client_data, struct srs_message *message)
291 {
292         struct srs_header *header;
293         void *data;
294
295         struct timeval timeout;
296         fd_set fds;
297         int rc;
298
299         if (client_data == NULL || message == NULL)
300                 return -1;
301
302         data = calloc(1, SRS_DATA_MAX_SIZE);
303         if (data == NULL)
304                 return -1;
305
306         memset(&timeout, 0, sizeof(timeout));
307         timeout.tv_usec = 300;
308
309         if (client_data->client_fd < 0)
310                 goto error;
311
312         FD_ZERO(&fds);
313         FD_SET(client_data->client_fd, &fds);
314
315         rc = select(client_data->client_fd + 1, &fds, NULL, NULL, &timeout);
316
317         if (!FD_ISSET(client_data->client_fd, &fds)) {
318                 LOGE("SRS read select failed on fd %d", client_data->client_fd);
319                 goto error;
320         }
321
322         rc = read(client_data->client_fd, data, SRS_DATA_MAX_SIZE);
323         if (rc < (int) sizeof(struct srs_header)) {
324                 LOGE("SRS read failed on fd %d with %d bytes", client_data->client_fd, rc);
325                 goto error;
326         }
327
328         header = (struct srs_header *) data;
329
330         memset(message, 0, sizeof(struct srs_message));
331         message->command = SRS_COMMAND(header);
332         message->length = header->length - sizeof(struct srs_header);
333         if (message->length > 0) {
334                 message->data = calloc(1, message->length);
335                 memcpy(message->data, (void *) ((char *) data + sizeof(struct srs_header)), message->length);
336         } else {
337                 message->data = NULL;
338         }
339
340         free(data);
341         return rc;
342
343 error:
344         free(data);
345         return 0;
346 }
347
348 void srs_control_ping(struct srs_message *message)
349 {
350         int caffe;
351
352         if (message == NULL || message->data == NULL || message->length < (int) sizeof(int))
353                 return;
354
355         caffe=*((int *) message->data);
356
357         if (caffe == SRS_CONTROL_CAFFE) {
358                 srs_send(SRS_CONTROL_PING, &caffe, sizeof(caffe));
359         }
360 }
361
362 static int srs_server_open(void)
363 {
364         int server_fd;
365         int t;
366
367         for (t=0 ; t < 5 ; t++) {
368                 unlink(SRS_SOCKET_NAME);
369 #if RIL_VERSION >= 6
370                 server_fd = socket_local_server(SRS_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
371 #else
372                 server_fd = socket_local_server(SRS_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
373 #endif
374                 if (server_fd >= 0)
375                         return server_fd;
376         }
377
378         return -1;
379 }
380
381 void *srs_client_read_loop(void *data)
382 {
383         struct srs_client_info *client;
384         struct srs_client_data *client_data;
385         struct srs_message message;
386         struct timeval timeout;
387         fd_set fds;
388         int fd_max;
389         int fd;
390         int rc;
391
392         if (data == NULL)
393                 pthread_exit(NULL);
394
395         client_data = (struct srs_client_data *) data;
396
397         while (client_data->running) {
398                 FD_ZERO(&fds);
399
400                 SRS_CLIENT_LOCK();
401                 fd_max = srs_client_info_fill_fd_set(client_data, &fds);
402                 SRS_CLIENT_UNLOCK();
403
404                 if (fd_max < 0) {
405                         usleep(3000);
406                         continue;
407                 }
408
409                 timeout.tv_sec = 0;
410                 timeout.tv_usec = 3000;
411
412                 select(fd_max + 1, &fds, NULL, NULL, &timeout);
413
414                 SRS_CLIENT_LOCK();
415                 while ((fd = srs_client_info_get_fd_set(client_data, &fds)) >= 0) {
416                         client_data->client_fd = fd;
417
418                         RIL_CLIENT_LOCK(client_data->client);
419                         rc = srs_client_recv(client_data, &message);
420                         if (rc <= 0) {
421                                 LOGD("SRS client with fd %d terminated", fd);
422
423                                 client = srs_client_info_find_fd(client_data, fd);
424                                 if (client != NULL)
425                                         srs_client_unregister(client_data, client);
426                                 close(fd);
427
428                                 RIL_CLIENT_UNLOCK(client_data->client);
429                                 continue;
430                         }
431                         RIL_CLIENT_UNLOCK(client_data->client);
432
433                         LOGD("RECV SRS: fd=%d command=%d length=%d", fd, message.command, message.length);
434                         if (message.data != NULL && message.length > 0) {
435                                 LOGD("==== SRS DATA DUMP ====");
436                                 hex_dump(message.data, message.length);
437                                 LOGD("=======================");
438                         }
439
440                         srs_dispatch(&message);
441
442                         if (message.data != NULL)
443                                 free(message.data);
444
445                         client_data->client_fd = -1;
446                 }
447                 SRS_CLIENT_UNLOCK();
448         }
449
450         pthread_exit(NULL);
451         return NULL;
452 }
453
454 int srs_read_loop(struct ril_client *client)
455 {
456         struct srs_client_data *client_data;
457         struct sockaddr_un client_addr;
458         int client_addr_len;
459         pthread_attr_t attr;
460         int flags;
461         int fd;
462         int rc;
463
464         if (client == NULL || client->data == NULL)
465                 return -1;
466
467         client_data = (struct srs_client_data *) client->data;
468
469         pthread_attr_init(&attr);
470         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
471
472         client_data->running = 1;
473
474         rc = pthread_create(&client_data->thread, &attr, srs_client_read_loop, (void *) client_data);
475         if (rc < 0) {
476                 LOGE("Unable to create SRS client read loop thread");
477                 return -1;
478         }
479
480         while (client_data->server_fd >= 0) {
481                 fd = accept(client_data->server_fd, (struct sockaddr *) &client_addr,
482                         &client_addr_len);
483                 if (fd < 0) {
484                         LOGE("Unable to accept new SRS client");
485                         break;
486                 }
487
488                 flags = fcntl(fd, F_GETFL);
489                 flags |= O_NONBLOCK;
490                 fcntl(fd, F_SETFL, flags);
491
492                 LOGD("Accepted new SRS client from fd %d", fd);
493
494                 SRS_CLIENT_LOCK();
495                 rc = srs_client_register(client_data, fd);
496                 SRS_CLIENT_UNLOCK();
497                 if (rc < 0) {
498                         LOGE("Unable to register SRS client");
499                         break;
500                 }
501         }
502
503         LOGE("SRS server failure");
504
505         client_data->running = 0;
506
507         // Wait for the thread to finish
508         pthread_join(client_data->thread, NULL);
509
510         return 0;
511 }
512
513 int srs_create(struct ril_client *client)
514 {
515         struct srs_client_data *client_data = NULL;
516
517         if (client == NULL)
518                 return -1;
519
520         LOGD("Creating new SRS client");
521
522         signal(SIGPIPE, SIG_IGN);
523
524         client_data = (struct srs_client_data *) calloc(1, sizeof(struct srs_client_data));
525         if (client_data == NULL) {
526                 LOGE("SRS client data creation failed");
527                 return -1;
528         }
529
530         client_data->server_fd = srs_server_open();
531         if (client_data->server_fd < 0) {
532                 LOGE("SRS server creation failed");
533                 goto fail;
534         }
535
536         pthread_mutex_init(&client_data->mutex, NULL);
537
538         client_data->client = client;
539         client->data = (void *) client_data;
540
541         return 0;
542
543 fail:
544         if (client_data != NULL)
545                 free(client_data);
546
547         return -1;
548 }
549
550 int srs_destroy(struct ril_client *client)
551 {
552         struct srs_client_data *client_data = NULL;
553         struct srs_client_info *client_info;
554
555         if (client == NULL)
556                 return 0;
557
558         if (client->data == NULL)
559                 return -1;
560
561         client_data = (struct srs_client_data *) client->data;
562
563         pthread_mutex_destroy(&client_data->mutex);
564
565         while ((client_info = srs_client_info_find(client_data)) != NULL) {
566                 close(client_info->fd);
567                 srs_client_unregister(client_data, client_info);
568         }
569
570         if (client_data->server_fd > 0)
571                 close(client_data->server_fd);
572
573         memset(client_data, 0, sizeof(struct srs_client_data));
574         free(client_data);
575         client->data = NULL;
576
577         return 0;
578 }
579
580 struct ril_client_funcs srs_client_funcs = {
581         .create = srs_create,
582         .destroy = srs_destroy,
583         .read_loop = srs_read_loop,
584 };