srs: Refactor code, check for NULL pointers and prevent memory leaks
[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 *srs_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 (srs_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 = srs_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 (srs_client_data->clients == NULL)
60                 srs_client_data->clients = list;
61
62         return 0;
63 }
64
65 void srs_client_unregister(struct srs_client_data *srs_client_data, struct srs_client_info *client)
66 {
67         struct list_head *list;
68
69         if (srs_client_data == NULL || client == NULL)
70                 return;
71
72         list = srs_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 == srs_client_data->clients)
79                                 srs_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 *srs_client_data)
91 {
92         struct srs_client_info *client;
93         struct list_head *list;
94
95         list = srs_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 *srs_client_data, int fd)
111 {
112         struct srs_client_info *client;
113         struct list_head *list;
114
115         list = srs_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 *srs_client_data, fd_set *fds)
132 {
133         struct srs_client_info *client;
134         struct list_head *list;
135         int fd_max;
136
137         if (srs_client_data == NULL || fds == NULL)
138                 return -1;
139
140         fd_max = -1;
141         list = srs_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 *srs_client_data, fd_set *fds)
159 {
160         struct srs_client_info *client;
161         struct list_head *list;
162         int fd;
163
164         if (srs_client_data == NULL || fds == NULL)
165                 return -1;
166
167         list = srs_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 *srs_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 (srs_client_data == NULL || message == NULL)
195                 return -EINVAL;
196
197         memset(&header, 0, sizeof(header));
198         header.group = SRS_GROUP(message->command);
199         header.index = SRS_INDEX(message->command);
200         header.length = message->length + sizeof(header);
201
202         data = calloc(1, header.length);
203         memcpy(data, &header, sizeof(header));
204         memcpy((void *) ((char *) data + sizeof(header)), message->data, message->length);
205
206         memset(&timeout, 0, sizeof(timeout));
207         timeout.tv_usec = 300;
208
209         if (srs_client_data->client_fd < 0) {
210                 rc = -1;
211                 goto complete;
212         }
213
214         FD_ZERO(&fds);
215         FD_SET(srs_client_data->client_fd, &fds);
216
217         rc = select(srs_client_data->client_fd + 1, NULL, &fds, NULL, &timeout);
218
219         if (!FD_ISSET(srs_client_data->client_fd, &fds)) {
220                 LOGE("SRS write select failed on fd %d", srs_client_data->client_fd);
221                 rc = -1;
222                 goto complete;
223         }
224
225         rc = write(srs_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", srs_client_data->client_fd, rc);
228                 rc = -1;
229                 goto complete;
230         }
231
232 complete:
233         free(data);
234
235         return rc;
236 }
237
238 int srs_client_send(struct srs_client_data *srs_client_data, unsigned short command, void *data, int length)
239 {
240         struct srs_client_info *client;
241         struct srs_message message;
242         int rc;
243
244         if (srs_client_data == NULL)
245                 return -1;
246
247         memset(&message, 0, sizeof(message));
248         message.command = command;
249         message.length = length;
250         message.data = data;
251
252         RIL_CLIENT_LOCK(srs_client_data->client);
253         rc = srs_client_send_message(srs_client_data, &message);
254         RIL_CLIENT_UNLOCK(srs_client_data->client);
255
256         if (rc <= 0) {
257                 LOGD("SRS client with fd %d terminated", srs_client_data->client_fd);
258
259                 client = srs_client_info_find_fd(srs_client_data, srs_client_data->client_fd);
260                 if (client != NULL)
261                         srs_client_unregister(srs_client_data, client);
262                 close(srs_client_data->client_fd);
263                 srs_client_data->client_fd = -1;
264         }
265
266         return rc;
267 }
268
269 int srs_send(unsigned short command, void *data, int length)
270 {
271         struct srs_client_data *srs_client_data;
272         int rc;
273
274         if (ril_data.srs_client == NULL || ril_data.srs_client->data == NULL)
275                 return -EINVAL;
276
277         srs_client_data = (struct srs_client_data *) ril_data.srs_client->data;
278
279         LOGD("SEND SRS: fd=%d command=%d length=%d", srs_client_data->client_fd, command, length);
280         if (data != NULL && length > 0) {
281                 LOGD("==== SRS DATA DUMP ====");
282                 hex_dump(data, length);
283                 LOGD("=======================");
284         }
285
286         return srs_client_send(srs_client_data, command, data, length);
287 }
288
289 int srs_client_recv(struct srs_client_data *srs_client_data, struct srs_message *message)
290 {
291         struct srs_header *header;
292         void *data;
293
294         struct timeval timeout;
295         fd_set fds;
296         int rc;
297
298         if (srs_client_data == NULL || message == NULL)
299                 return -1;
300
301         data = calloc(1, SRS_DATA_MAX_SIZE);
302
303         memset(&timeout, 0, sizeof(timeout));
304         timeout.tv_usec = 300;
305
306         if (srs_client_data->client_fd < 0) {
307                 rc = -1;
308                 goto complete;
309         }
310
311         FD_ZERO(&fds);
312         FD_SET(srs_client_data->client_fd, &fds);
313
314         rc = select(srs_client_data->client_fd + 1, &fds, NULL, NULL, &timeout);
315
316         if (!FD_ISSET(srs_client_data->client_fd, &fds)) {
317                 LOGE("SRS read select failed on fd %d", srs_client_data->client_fd);
318                 rc = -1;
319                 goto complete;
320         }
321
322         rc = read(srs_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", srs_client_data->client_fd, rc);
325                 rc = -1;
326                 goto complete;
327         }
328
329         header = (struct srs_header *) data;
330
331         memset(message, 0, sizeof(struct srs_message));
332         message->command = SRS_COMMAND(header);
333         message->length = header->length - sizeof(struct srs_header);
334         message->data = NULL;
335
336         if (message->length > 0) {
337                 message->data = calloc(1, message->length);
338                 memcpy(message->data, (void *) ((char *) data + sizeof(struct srs_header)), message->length);
339         }
340
341 complete:
342         free(data);
343
344         return rc;
345 }
346
347 void srs_control_ping(struct srs_message *message)
348 {
349         int caffe;
350
351         if (message == NULL || message->data == NULL || message->length < (int) sizeof(int))
352                 return;
353
354         caffe = *((int *) message->data);
355
356         if (caffe == SRS_CONTROL_CAFFE)
357                 srs_send(SRS_CONTROL_PING, &caffe, sizeof(caffe));
358 }
359
360 static int srs_server_open(void)
361 {
362         int server_fd;
363         int t;
364
365         for (t=0 ; t < 5 ; t++) {
366                 unlink(SRS_SOCKET_NAME);
367 #if RIL_VERSION >= 6
368                 server_fd = socket_local_server(SRS_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
369 #else
370                 server_fd = socket_local_server(SRS_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
371 #endif
372                 if (server_fd >= 0)
373                         return server_fd;
374         }
375
376         return -1;
377 }
378
379 void *srs_client_read_loop(void *data)
380 {
381         struct srs_client_info *client;
382         struct srs_client_data *srs_client_data;
383         struct srs_message message;
384         struct timeval timeout;
385         fd_set fds;
386         int fd_max;
387         int fd;
388         int rc;
389
390         if (data == NULL)
391                 pthread_exit(NULL);
392
393         srs_client_data = (struct srs_client_data *) data;
394
395         while (srs_client_data->running) {
396                 FD_ZERO(&fds);
397
398                 SRS_CLIENT_LOCK();
399                 fd_max = srs_client_info_fill_fd_set(srs_client_data, &fds);
400                 SRS_CLIENT_UNLOCK();
401
402                 if (fd_max < 0) {
403                         usleep(3000);
404                         continue;
405                 }
406
407                 timeout.tv_sec = 0;
408                 timeout.tv_usec = 3000;
409
410                 select(fd_max + 1, &fds, NULL, NULL, &timeout);
411
412                 SRS_CLIENT_LOCK();
413                 while ((fd = srs_client_info_get_fd_set(srs_client_data, &fds)) >= 0) {
414                         srs_client_data->client_fd = fd;
415
416                         RIL_CLIENT_LOCK(srs_client_data->client);
417                         rc = srs_client_recv(srs_client_data, &message);
418                         if (rc <= 0) {
419                                 LOGD("SRS client with fd %d terminated", fd);
420
421                                 client = srs_client_info_find_fd(srs_client_data, fd);
422                                 if (client != NULL)
423                                         srs_client_unregister(srs_client_data, client);
424                                 close(fd);
425
426                                 RIL_CLIENT_UNLOCK(srs_client_data->client);
427                                 continue;
428                         }
429                         RIL_CLIENT_UNLOCK(srs_client_data->client);
430
431                         LOGD("RECV SRS: fd=%d command=%d length=%d", fd, message.command, message.length);
432                         if (message.data != NULL && message.length > 0) {
433                                 LOGD("==== SRS DATA DUMP ====");
434                                 hex_dump(message.data, message.length);
435                                 LOGD("=======================");
436                         }
437
438                         srs_dispatch(&message);
439
440                         if (message.data != NULL && message.length > 0)
441                                 free(message.data);
442
443                         srs_client_data->client_fd = -1;
444                 }
445                 SRS_CLIENT_UNLOCK();
446         }
447
448         pthread_exit(NULL);
449         return NULL;
450 }
451
452 int srs_read_loop(struct ril_client *client)
453 {
454         struct srs_client_data *srs_client_data;
455
456         struct sockaddr_un client_addr;
457         int client_addr_len;
458         pthread_attr_t attr;
459         int flags;
460         int fd;
461         int rc;
462
463         if (client == NULL || client->data == NULL)
464                 return -EINVAL;
465
466         srs_client_data = (struct srs_client_data *) client->data;
467
468         pthread_attr_init(&attr);
469         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
470
471         srs_client_data->running = 1;
472
473         rc = pthread_create(&srs_client_data->thread, &attr, srs_client_read_loop, (void *) srs_client_data);
474         if (rc < 0) {
475                 LOGE("Unable to create SRS client read loop thread");
476                 return -1;
477         }
478
479         while (srs_client_data->server_fd >= 0) {
480                 fd = accept(srs_client_data->server_fd, (struct sockaddr *) &client_addr,
481                         &client_addr_len);
482                 if (fd < 0) {
483                         LOGE("Unable to accept new SRS client");
484                         break;
485                 }
486
487                 flags = fcntl(fd, F_GETFL);
488                 flags |= O_NONBLOCK;
489                 fcntl(fd, F_SETFL, flags);
490
491                 LOGD("Accepted new SRS client from fd %d", fd);
492
493                 SRS_CLIENT_LOCK();
494                 rc = srs_client_register(srs_client_data, fd);
495                 SRS_CLIENT_UNLOCK();
496                 if (rc < 0) {
497                         LOGE("Unable to register SRS client");
498                         break;
499                 }
500         }
501
502         LOGE("SRS server failure");
503
504         srs_client_data->running = 0;
505
506         // Wait for the thread to finish
507         pthread_join(srs_client_data->thread, NULL);
508
509         return 0;
510 }
511
512 int srs_create(struct ril_client *client)
513 {
514         struct srs_client_data *srs_client_data;
515
516         if (client == NULL)
517                 return -EINVAL;
518
519         LOGD("Creating new SRS client");
520
521         signal(SIGPIPE, SIG_IGN);
522
523         srs_client_data = (struct srs_client_data *) calloc(1, sizeof(struct srs_client_data));
524
525         srs_client_data->server_fd = srs_server_open();
526         if (srs_client_data->server_fd < 0) {
527                 LOGE("SRS server creation failed");
528                 goto error;
529         }
530
531         pthread_mutex_init(&srs_client_data->mutex, NULL);
532
533         srs_client_data->client = client;
534         client->data = (void *) srs_client_data;
535
536         return 0;
537
538 error:
539         free(srs_client_data);
540
541         return -1;
542 }
543
544 int srs_destroy(struct ril_client *client)
545 {
546         struct srs_client_data *srs_client_data = NULL;
547         struct srs_client_info *client_info;
548
549         if (client == NULL || client->data == NULL) {
550                 LOGE("Client was already destroyed");
551                 return 0;
552         }
553
554         srs_client_data = (struct srs_client_data *) client->data;
555
556         pthread_mutex_destroy(&srs_client_data->mutex);
557
558         while ((client_info = srs_client_info_find(srs_client_data)) != NULL) {
559                 close(client_info->fd);
560                 srs_client_unregister(srs_client_data, client_info);
561         }
562
563         if (srs_client_data->server_fd > 0)
564                 close(srs_client_data->server_fd);
565
566         srs_client_data->server_fd = -1;
567         srs_client_data->client_fd = -1;
568         srs_client_data->clients = NULL;
569         srs_client_data->running = 0;
570
571         free(srs_client_data);
572         client->data = NULL;
573
574         return 0;
575 }
576
577 struct ril_client_funcs srs_client_funcs = {
578         .create = srs_create,
579         .destroy = srs_destroy,
580         .read_loop = srs_read_loop,
581 };