Include the scan time for each app into battery info
[platform/core/connectivity/bluetooth-frwk.git] / bt-oal / oal-socket.c
1 /*
2  * Open Adaptation Layer (OAL)
3  *
4  * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *              http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <stdio.h>
21 #include <string.h>
22 #include <sys/types.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <glib.h>
26 #include <dlog.h>
27 #include <sys/socket.h>
28 #include <errno.h>
29 #include <fcntl.h>
30
31 #include <oal-event.h>
32 #include <oal-manager.h>
33 #include "oal-internal.h"
34
35 #include "bluetooth.h"
36 #include "bt_sock.h"
37 #include "oal-socket.h"
38 #include "oal-utils.h"
39
40 #define CHECK_OAL_SOCKET_ENABLED() \
41         do { \
42                 if (socket_api == NULL) { \
43                         BT_ERR("Socket is not Initialized"); \
44                         return OAL_STATUS_NOT_READY; \
45                 } \
46         } while (0)
47
48 /* Definitions */
49 #define MAX_RETRY 5
50 #define SOCK_SHORT_LEN 2
51 #define SOCK_INT_LEN 4
52 #define SOCK_CONNECT_INFO_LEN 16
53 #define SOCK_BD_ADDR_LEN 6
54
55 typedef struct {
56         int fd;
57         int sock_type;
58         bt_address_t address;
59         guint control_id;
60         GIOChannel *control_io;
61 } oal_client_info_t;
62
63 /*
64  * Global variables
65  */
66 static const btsock_interface_t* socket_api = NULL;
67
68 static int getInt(char *buf, int len)
69 {
70         int val = 0;
71
72         if (len != SOCK_INT_LEN)
73                 return -1;
74         val = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
75         return val;
76 }
77
78 static int getShort(char *buf, int len)
79 {
80         int val = 0;
81
82         if (len != SOCK_SHORT_LEN)
83                 return -1;
84         val = buf[0] | (buf[1] << 8);
85         return val;
86 }
87
88 static int getBdaddr(char *buf, int len, bt_bdaddr_t *bd)
89 {
90         int val = 0;
91
92         if (len != SOCK_BD_ADDR_LEN)
93                 return -1;
94         bd->address[0] = buf[0];
95         bd->address[1] = buf[1];
96         bd->address[2] = buf[2];
97         bd->address[3] = buf[3];
98         bd->address[4] = buf[4];
99         bd->address[5] = buf[5];
100         BT_DBG("Address: %.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
101                         bd->address[0], bd->address[1], bd->address[2],
102                         bd->address[3], bd->address[4], bd->address[5]);
103         return val;
104 }
105 static void remove_io_channel(guint gid, GIOChannel *gch)
106 {
107         if (gch != NULL)
108                 g_io_channel_shutdown(gch, TRUE, NULL);
109         if (gid > 0)
110                 g_source_remove(gid);
111 }
112
113 static int socket_process_cmsg(struct msghdr *pMsg, int * data_fd)
114 {
115         struct cmsghdr *cmsgptr = NULL;
116
117         for (cmsgptr = CMSG_FIRSTHDR(pMsg);
118                         cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(pMsg, cmsgptr)) {
119
120                 if (cmsgptr->cmsg_level != SOL_SOCKET)
121                         continue;
122
123                 if (cmsgptr->cmsg_type == SCM_RIGHTS) {
124                         int *pDescriptors = (int *)CMSG_DATA(cmsgptr);
125                         int count = ((cmsgptr->cmsg_len - CMSG_LEN(0)) / sizeof(int));
126
127                         if (count < 0) {
128                                 BT_ERR("ERROR Invalid count of descriptors");
129                                 continue;
130                         }
131
132                         BT_DBG("Server, socket fd for connection: %d", pDescriptors[0]);
133                         *data_fd = pDescriptors[0];
134                 }
135         }
136
137         return 0;
138 }
139
140 static int socket_read(int fd, char *buf, size_t len, int *data_fd)
141 {
142         int ret;
143         struct msghdr msg;
144         struct iovec iv;
145         struct cmsghdr cmsgbuf[2*sizeof(struct cmsghdr) + 0x100];
146         int retryCount = 0;
147         int flags = 0;
148
149         fd_set  toselect_fd;
150         struct timeval wait;
151
152         BT_INFO("socket_read, fd = %d", fd);
153
154         retv_if(fd < 0, -1);
155
156         memset(&msg, 0, sizeof(msg));
157         memset(&iv, 0, sizeof(iv));
158
159         iv.iov_base = buf;
160         iv.iov_len = len;
161
162         msg.msg_iov = &iv;
163         msg.msg_iovlen = 1;
164         msg.msg_control = cmsgbuf;
165         msg.msg_controllen = sizeof(cmsgbuf);
166
167         flags = fcntl(fd, F_GETFL, 0);
168         if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
169                 BT_ERR("Not able to change socket nonblocking");
170                 return -2;
171         }
172
173         FD_ZERO(&toselect_fd);
174         FD_SET(fd, &toselect_fd);
175         wait.tv_sec = 1;
176         wait.tv_usec = 0;
177
178         ret = select(fd + 1, &toselect_fd, NULL, NULL, &wait);
179         if (ret < 0) {
180                 fcntl(fd, F_SETFL, flags);
181                 BT_ERR("Time out on selecy = %d", ret);
182                 return -1;
183         }
184
185 repeat:
186         retryCount++;
187         ret = recvmsg(fd, &msg, 0); //MSG_NOSIGNAL);
188         BT_DBG("socket_read, recvmsg ret = %d", ret);
189         if (ret < 0 && errno == EINTR) {
190                 if (retryCount < MAX_RETRY) {
191                         goto repeat;
192                 } else {
193                         fcntl(fd, F_SETFL, flags);
194                         return -2;
195                 }
196         }
197
198         if (ret < 0 && errno == EPIPE) {
199                 // Treat this as an end of stream
200                 fcntl(fd, F_SETFL, flags);
201                 BT_ERR("EOS errno: %d", errno);
202                 return 0;
203         }
204
205         if (ret < 0) {
206                 fcntl(fd, F_SETFL, flags);
207                 BT_ERR("Ret errno: %d", errno);
208                 return -1;
209         }
210
211         /* FD_ISSET need not be checked */
212         fcntl(fd, F_SETFL, flags);
213         if ((msg.msg_flags & (MSG_CTRUNC | MSG_OOB | MSG_ERRQUEUE)) != 0) {
214                 // To us, any of the above flags are a fatal error
215                 BT_ERR("MSG Flags errno: %d", errno);
216                 return -2;
217         }
218
219         if (ret >= 0 && data_fd) {
220                 BT_INFO("Connection received");
221                 socket_process_cmsg(&msg, data_fd);
222         }
223
224         return ret;
225 }
226
227 static int sock_wait_for_channel(int sock_fd)
228 {
229         int readlen = -1;
230         char buf[SOCK_INT_LEN];
231
232         readlen = socket_read(sock_fd, buf, SOCK_INT_LEN, NULL);
233         return getInt(buf, readlen);
234 }
235
236 static int sock_wait_for_connect_signal(int sock_fd,
237                 int *data_fd, bt_bdaddr_t *bd_addr)
238 {
239         int readlen = -1;
240         char buf[SOCK_CONNECT_INFO_LEN];
241         int size = -1, channel = -1, status = -1;
242         int len = 0;
243
244         readlen = socket_read(sock_fd, buf, SOCK_CONNECT_INFO_LEN, data_fd);
245         BT_DBG("Socket Read len: %d", readlen);
246         if (readlen == 0) {
247                 BT_WARN("Listen stopped");
248                 return -1; /* This essentially means that the listen is stopped */
249         }
250
251         if (readlen != SOCK_CONNECT_INFO_LEN) {
252                 BT_ERR("Read length is not same as socket info length");
253                 return -2;
254         }
255
256         size = getShort(&buf[len], SOCK_SHORT_LEN);
257         len += SOCK_SHORT_LEN;
258         if (size != SOCK_CONNECT_INFO_LEN)
259                 return -3;
260
261         getBdaddr(&buf[len], SOCK_BD_ADDR_LEN, bd_addr); len += SOCK_BD_ADDR_LEN;
262         channel = getInt(&buf[len], SOCK_INT_LEN); len += SOCK_INT_LEN;
263         status = getInt(&buf[len], SOCK_INT_LEN);
264
265         BT_INFO("BTSOCK CONNECTION ESTABLISHED REMOTE Channel:%d, Status:%d",
266                         channel, status);
267         return 0;
268 }
269
270 static int sock_wait_for_connection_setup(oal_client_info_t *p_oal_client_info)
271 {
272         int channel = -1;
273         int ret = -1;
274
275         /* First, wait for channel number */
276         channel = sock_wait_for_channel(p_oal_client_info->fd);
277         if (channel < 0) {
278                 BT_ERR("ERROR, incorrect channel= %d", channel);
279                 return OAL_STATUS_INTERNAL_ERROR;
280         }
281
282         BT_INFO("client channel= %d", channel);
283
284         /* Now, wait for connection signal */
285         ret = sock_wait_for_connect_signal(p_oal_client_info->fd,
286                         NULL, (bt_bdaddr_t *)&p_oal_client_info->address);
287         if (0 > ret) {
288                 BT_ERR("ERROR, sock_wait_for_connect_signal failed");
289                 return OAL_STATUS_INTERNAL_ERROR;
290         }
291
292         return OAL_STATUS_SUCCESS;
293 }
294
295 /*
296  * This function will be called only once as connection setup is done here
297  * and then data will be received directly in application context using fd
298  * passed in socket connection event.
299  */
300 static gboolean sockclient_thread(GIOChannel *gio, GIOCondition cond, gpointer data)
301 {
302         event_socket_client_conn_t *client_info_ev;
303         oal_client_info_t *p_oal_client_info = (oal_client_info_t *)data;
304
305         retv_if(p_oal_client_info == NULL, FALSE);
306         retv_if(p_oal_client_info->fd < 0, FALSE);
307
308         BT_DBG("Client fd= %d", p_oal_client_info->fd);
309
310         /* This memory will be freed by event dispatcher */
311         client_info_ev = g_new0(event_socket_client_conn_t, 1);
312         client_info_ev->fd = p_oal_client_info->fd;
313         client_info_ev->sock_type = p_oal_client_info->sock_type;
314         memcpy(&client_info_ev->address, &p_oal_client_info->address, sizeof(bt_address_t));
315
316         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
317                 BT_INFO("Client disconnected-0x%X (fd = %d)",
318                                 cond, p_oal_client_info->fd);
319                 goto failed;
320         }
321
322         if (OAL_STATUS_SUCCESS == sock_wait_for_connection_setup(p_oal_client_info)) {
323                 BT_INFO("connection setup success");
324                 send_event_bda_trace(OAL_EVENT_SOCKET_OUTGOING_CONNECTED, client_info_ev,
325                                 sizeof(event_socket_client_conn_t), &p_oal_client_info->address);
326                 goto done;
327         }
328
329         BT_ERR("ERROR, incorrect connection setup");
330
331 failed:
332         remove_io_channel(p_oal_client_info->control_id, p_oal_client_info->control_io);
333         send_event_bda_trace(OAL_EVENT_SOCKET_DISCONNECTED, client_info_ev,
334                         sizeof(event_socket_client_conn_t), &p_oal_client_info->address);
335 done:
336         g_free(p_oal_client_info);
337         return FALSE;
338 }
339
340 int socket_connect(oal_sock_type_t sock_type, oal_uuid_t *p_uuid, int channel, bt_address_t* bd)
341 {
342         oal_client_info_t *p_oal_client_info = NULL;
343         int sock_fd = -1;
344         bdstr_t bdstr;
345
346         API_TRACE("Socket connect: %s", bdt_bd2str(bd, &bdstr));
347
348         CHECK_OAL_SOCKET_ENABLED();
349
350         p_oal_client_info = g_new0(oal_client_info_t, 1);
351
352         switch (sock_type) {
353         case OAL_SOCK_RFCOMM:
354                 if (channel < 0)
355                         socket_api->connect((const bt_bdaddr_t *)bd,
356                                 BTSOCK_RFCOMM, p_uuid->uuid, 0, &sock_fd, 0);
357                 else
358                         socket_api->connect((const bt_bdaddr_t *)bd,
359                                 BTSOCK_RFCOMM, NULL, channel, &sock_fd, 0);
360                 break;
361         default:
362                 BT_ERR("Socket type: %d not supported", sock_type);
363         }
364
365         if (sock_fd < 0) {
366                 BT_ERR("Bluetooth socket connect failed");
367                 g_free(p_oal_client_info);
368                 return sock_fd;
369         }
370
371         BT_INFO("Bluetooth client socket created, sock_fd=%d", sock_fd);
372
373         p_oal_client_info->fd = sock_fd;
374         p_oal_client_info->sock_type = sock_type;
375         memcpy(&p_oal_client_info->address, bd, sizeof(bt_address_t));
376         p_oal_client_info->control_io = g_io_channel_unix_new(p_oal_client_info->fd);
377         p_oal_client_info->control_id = g_io_add_watch(p_oal_client_info->control_io,
378                         G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
379                         sockclient_thread, p_oal_client_info);
380         g_io_channel_set_close_on_unref(p_oal_client_info->control_io, FALSE);
381         g_io_channel_unref(p_oal_client_info->control_io);
382
383         BT_DBG("Client watch added");
384         return sock_fd;
385 }
386
387 int socket_listen(oal_sock_type_t sock_type, oal_uuid_t *p_uuid, char *svc_name, int channel)
388 {
389         int sock_fd = -1;
390         int srv_channel;
391         int ret = BT_STATUS_FAIL;
392
393         CHECK_OAL_SOCKET_ENABLED();
394         OAL_CHECK_PARAMETER(svc_name, return);
395         API_TRACE("svc_name: %s", svc_name);
396
397         switch (sock_type) {
398         case OAL_SOCK_RFCOMM:
399                 if (channel < 0)
400                         ret = socket_api->listen(BTSOCK_RFCOMM,
401                                         svc_name, p_uuid->uuid, 0, &sock_fd, 0);
402                 else
403                         ret = socket_api->listen(BTSOCK_RFCOMM,
404                                         svc_name, p_uuid->uuid, channel, &sock_fd, 0);
405                 break;
406         default:
407                 BT_ERR("Socket type: %d not supported", sock_type);
408         }
409
410         if (sock_fd < 0 || ret != BT_STATUS_SUCCESS) {
411                 BT_ERR("Bluetooth socket creation failed");
412                 return sock_fd;
413         }
414
415         BT_INFO("Bluetooth server socket created, sock_fd=%d", sock_fd);
416
417         /* Read server channel number sent by stack */
418         srv_channel = sock_wait_for_channel(sock_fd);
419         if (srv_channel < 0) {
420                 BT_ERR("incorrect channel= %d", srv_channel);
421                 return  -1;
422         }
423
424         BT_INFO("server channel= %d", srv_channel);
425
426         return sock_fd;
427 }
428
429 oal_status_t socket_enable()
430 {
431         const bt_interface_t *blued_api;
432
433         API_TRACE("Socket Init");
434
435         blued_api = adapter_get_stack_interface();
436         if (blued_api == NULL) {
437                 BT_ERR("Stack is not initialized");
438                 return OAL_STATUS_NOT_READY;
439         }
440
441         if (socket_api != NULL) {
442                 BT_WARN("Socket Interface is already initialized...");
443                 return OAL_STATUS_ALREADY_DONE;
444         }
445
446         socket_api = (const btsock_interface_t*)blued_api->get_profile_interface(BT_PROFILE_SOCKETS_ID);
447         if (!socket_api) {
448                 BT_ERR("OAL Socket failed to initialize");
449                 return OAL_STATUS_INTERNAL_ERROR;
450         }
451
452         BT_DBG("Socket successfully initiated");
453         return OAL_STATUS_SUCCESS ;
454 }
455
456 oal_status_t socket_disable(void)
457 {
458
459         API_TRACE("Socket Deinit");
460
461         CHECK_OAL_SOCKET_ENABLED();
462         socket_api = NULL;
463         return OAL_STATUS_SUCCESS;
464 }