Rework SRS to support multiple clients
[samsung-ril.git] / srs.c
1 /**
2  * This file is part of samsung-ril.
3  *
4  * Copyright (C) 2011 Paul Kocialkowski <contact@oaulk.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 <sys/stat.h>
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <sys/un.h>
25 #include <sys/select.h>
26
27 #include <arpa/inet.h>
28 #include <netinet/in.h>
29 #include <cutils/sockets.h>
30
31 #define LOG_TAG "RIL-SRS"
32 #include <utils/Log.h>
33
34 #include "samsung-ril.h"
35 #include "util.h"
36
37 static int srs_server_send_message(int client_fd, struct srs_message *message)
38 {
39         fd_set fds;
40
41         struct srs_header header;
42         void *data;
43
44         header.length = message->data_len + sizeof(header);
45         header.group = SRS_GROUP(message->command);
46         header.index = SRS_INDEX(message->command);
47
48         data = malloc(header.length);
49         memset(data, 0, header.length);
50
51         memcpy(data, &header, sizeof(header));
52         memcpy((void *) ((char*)data + sizeof(header)),
53                 message->data, message->data_len);
54
55         FD_ZERO(&fds);
56         FD_SET(client_fd, &fds);
57
58         select(FD_SETSIZE, NULL, &fds, NULL, NULL);
59
60         write(client_fd, data, header.length);
61
62         free(data);
63
64         return 0;
65 }
66
67 static int srs_server_send(int fd, unsigned short command, void *data,
68         int data_len)
69 {
70         struct srs_message message;
71         int rc;
72
73         message.command = command;
74         message.data = data;
75         message.data_len = data_len;
76
77         rc = srs_server_send_message(fd, &message);
78
79         return rc;
80 }
81
82 static int srs_server_recv(int client_fd, struct srs_message *message)
83 {
84         void *raw_data = malloc(SRS_DATA_MAX_SIZE);
85         struct srs_header *header;
86         int rc;
87
88         rc = read(client_fd, raw_data, SRS_DATA_MAX_SIZE);
89         if(rc < (int)sizeof(struct srs_header)) {
90                 return -1;
91         }
92
93         header = raw_data;
94
95         message->command = SRS_COMMAND(header);
96         message->data_len = header->length - sizeof(struct srs_header);
97         message->data = malloc(message->data_len);
98
99         memcpy(message->data, (char*)raw_data + sizeof(struct srs_header),
100                 message->data_len);
101
102         free(raw_data);
103
104         return 0;
105 }
106
107 void srs_control_ping(int fd, struct srs_message *message)
108 {
109         int caffe;
110
111         if(message->data == NULL)
112                 return;
113
114         caffe=*((int *) message->data);
115
116         if(caffe == SRS_CONTROL_CAFFE) {
117                 srs_server_send(fd, SRS_CONTROL_PING, &caffe, sizeof(caffe));
118         }
119 }
120
121 static int srs_server_open(void)
122 {
123         int server_fd = -1;
124
125         int t = 0;
126
127         while(t < 5) {
128                 unlink(SRS_SOCKET_NAME);
129                 server_fd = socket_local_server(SRS_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
130
131                 if(server_fd >= 0)
132                         break;
133
134                 t++;
135         }
136
137         return server_fd;
138 }
139
140 static void* srs_process_client(void *pfd)
141 {
142         struct srs_message srs_message;
143         fd_set fds;
144         int client_fd = -1;
145         if (!pfd) {
146                 LOGE("SRS client data is NULL");
147                 goto fail;
148         }
149
150         client_fd = ((int*)pfd)[0];
151
152         while (1) {
153                 if (client_fd < 0)
154                         break;
155
156                 FD_ZERO(&fds);
157                 FD_SET(client_fd, &fds);
158
159                 select(FD_SETSIZE, &fds, NULL, NULL, NULL);
160
161                 if (FD_ISSET(client_fd, &fds)) {
162                         if (srs_server_recv(client_fd, &srs_message) < 0) {
163                                 LOGE("SRS recv failed, aborting!");
164                                 break;
165                         }
166
167                         LOGD("SRS recv: command=%d data_len=%d",
168                              srs_message.command, srs_message.data_len);
169                         hex_dump(srs_message.data, srs_message.data_len);
170
171                         srs_dispatch(client_fd, &srs_message);
172
173                         if (srs_message.data != NULL)
174                                 free(srs_message.data);
175                 }
176         }
177
178 fail:
179         if(client_fd >= 0) {
180                 close(client_fd);
181         }
182
183         LOGE("SRS server client ended!");
184         return NULL;
185 }
186
187 static int srs_read_loop(struct ril_client *client)
188 {
189         int rc;
190
191         struct sockaddr_un client_addr;
192         int client_addr_len;
193
194         if(client == NULL) {
195                 LOGE("client is NULL, aborting!");
196                 return -1;
197         }
198
199         if(client->object == NULL) {
200                 LOGE("client object is NULL, aborting!");
201                 return -1;
202         }
203
204         int server_fd = ((int*)client->object)[0];
205
206         while(1) {
207                 if(server_fd < 0) {
208                         LOGE("SRS client server_fd is negative, aborting!");
209                         return -1;
210                 }
211
212                 rc = accept(server_fd, (struct sockaddr*)&client_addr,
213                         &client_addr_len);
214                 if (rc < 0) {
215                         LOGE("SRS Failed to accept errno %d error %s",
216                                 errno, strerror(errno));
217                         return -1;
218                 }
219                 LOGI("SRS accepted fd %d", rc);
220                 int *pfd = (int*)malloc(sizeof(int));
221                 if (!pfd) {
222                         LOGE("out of memory for the client socket");
223                         close(rc);
224                         return -1;
225                 }
226                 *pfd = rc;
227
228                 pthread_t t;
229                 if (pthread_create(&t, NULL, srs_process_client, pfd)) {
230                         LOGE("SRS failed to start client thread errno %d error %s",
231                                 errno, strerror(errno));
232                         close(rc);
233                         return -1;
234                 }
235         }
236
237         return 0;
238 }
239
240 static int srs_create(struct ril_client *client)
241 {
242         int *srs_server = NULL;
243
244         LOGD("Creating new SRS client");
245
246         srs_server = malloc(sizeof(int));
247         if (!srs_server) {
248                 LOGE("SRS out of memory for server fd");
249                 goto fail;
250         }
251
252         client->object = (void *) srs_server;
253         if((*srs_server = srs_server_open()) < 0) {
254                 LOGE("%s: samsung-ril-socket server open failed", __FUNCTION__);
255                 goto fail;
256         }
257
258         return 0;
259
260 fail:
261         if (srs_server) {
262                 free(srs_server);
263         }
264         return -1;
265 }
266
267 static int srs_destroy(struct ril_client *client)
268 {
269         if (!client) {
270                 return 0;
271         }
272
273         int *srs_server = (int*) client->object;
274         if (!srs_server) {
275                 return 0;
276         }
277
278         close(*srs_server);
279         free(srs_server);
280
281         return 0;
282 }
283
284 struct ril_client_funcs srs_client_funcs = {
285         .create = srs_create,
286         .destroy = srs_destroy,
287         .read_loop = srs_read_loop,
288 };