ef772a705fb89aa276d739b3a85b04359f240923
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / services / socket / bt-service-socket.c
1 /*
2  * Bluetooth-frwk
3  *
4  * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Author: Atul Rai <a.rai@samsung.com>
7  *
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
11  *
12  *              http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  */
20
21 #include <stdio.h>
22 #include <string.h>
23 #include <sys/types.h>
24 #include <glib.h>
25 #include <dlog.h>
26
27 /* OAL headers */
28 #include <oal-event.h>
29 #include <oal-socket.h>
30
31 /* bt-service headers */
32 #include "bt-internal-types.h"
33 #include "bt-service-common.h"
34 #include "bt-service-util.h"
35 #include "bt-service-event-receiver.h"
36 #include "bt-service-socket.h"
37 #include "bt-service-event.h"
38
39 #define L2CAP_LE_UUID_SUBSTR "FFFFFFFF-FFFF-FFFF-FFFF-"
40
41 typedef struct {
42         int sock_fd;
43         int chan;
44         char uuid[BT_UUID_STRING_SIZE];
45         char address[BT_ADDRESS_STRING_SIZE];
46         bt_socket_client_conn_cb conn_cb;
47 } bt_socket_info_t;
48
49 static bt_socket_info_t *pending_conn_info;
50
51 /* Function to handle socket disconnection */
52 void __handle_socket_disconnected(event_socket_client_conn_t *client_info)
53 {
54         char address[BT_ADDRESS_STRING_SIZE];
55
56         ret_if(NULL == client_info);
57
58         BT_DBG("+");
59
60         _bt_convert_addr_type_to_string(address, client_info->address.addr);
61
62         /*
63          * In case of an already connected socket, if disconnection happens, it will
64          * automatically detected in corresponding i/o handler and events will be sent
65          * from there. So here we only handle connection fail case.
66          */
67         if (NULL != pending_conn_info &&
68                         !strncasecmp(address, pending_conn_info->address, strlen(address))) {
69                 /*
70                  * Disconnection event is received for ongoing connection, invoke connection
71                  * state callback with error.
72                  */
73                 BT_INFO("socket_fd: %d, address: %s, uuid: %s, channel: %d",
74                                 client_info->fd, address,
75                                 pending_conn_info->uuid,
76                                 pending_conn_info->chan);
77
78                 pending_conn_info->conn_cb(BLUETOOTH_ERROR_INTERNAL, client_info->fd, address,
79                                 pending_conn_info->uuid, pending_conn_info->chan);
80
81                 g_free(pending_conn_info);
82                 pending_conn_info = NULL;
83         } else {
84                 BT_INFO("Disconnected Address: [%s], socket_fd: %d", address, client_info->fd);
85         }
86
87         BT_DBG("-");
88 }
89
90 /* Handle outgoing client socket connection event */
91 static void __handle_outgoing_client_socket_connected(event_socket_client_conn_t *client_info)
92 {
93         char address[BT_ADDRESS_STRING_SIZE];
94
95         ret_if(NULL == client_info);
96         ret_if(NULL == pending_conn_info);
97
98         BT_DBG("+");
99
100         /*
101          * Only one socket connect req at a time is allowed, so received address
102          * should match with pending request.
103          */
104         _bt_convert_addr_type_to_string(address, client_info->address.addr);
105         if (strncasecmp(address, pending_conn_info->address, strlen(address))) {
106                 BT_ERR("Address mismatch, Pending connection address: [%s]",
107                                 pending_conn_info->address);
108                 BT_ERR("Client connection callback called with address: [%s]", address);
109                 return;
110         }
111
112         BT_INFO("socket_fd: %d, address: %s, uuid: %s, channel: %d",
113                         client_info->fd, address,
114                         pending_conn_info->uuid,
115                         pending_conn_info->chan);
116
117         pending_conn_info->conn_cb(BLUETOOTH_ERROR_NONE, client_info->fd, address,
118                         pending_conn_info->uuid, pending_conn_info->chan);
119
120         g_free(pending_conn_info);
121         pending_conn_info = NULL;
122         BT_DBG("-");
123 }
124
125 static void __handle_socket_authorization_request(event_socket_authorize_req_t *auth_event)
126 {
127         char address[BT_ADDRESS_STRING_SIZE];
128         char uuid_str[BT_UUID_STRING_SIZE];
129         int result = BLUETOOTH_ERROR_NONE;
130         char name[BT_NAME_LENGTH_MAX + 1] = {0, };
131         char path[BT_NAME_LENGTH_MAX + 1] = {0, };
132         const char *value;
133         int fd, psm;
134
135         BT_DBG("+");
136
137         _bt_convert_addr_type_to_string(address, auth_event->address.addr);
138         _bt_service_convert_uuid_type_to_string(uuid_str, auth_event->uuid.uuid);
139         memcpy(name, auth_event->name, BT_NAME_LENGTH_MAX);
140         memcpy(path, auth_event->path, BT_NAME_LENGTH_MAX);
141         fd = auth_event->fd;
142         BT_INFO("Address: %s, UUID: %s, Name: %s, Path: %s, Fd: %d", address, uuid_str, name, path, fd);
143
144         if (!strncmp(uuid_str, L2CAP_LE_UUID_SUBSTR, strlen(L2CAP_LE_UUID_SUBSTR))) {
145                 BT_INFO("sending L2CAP_LE authorize event");
146                 value = uuid_str + strlen(L2CAP_LE_UUID_SUBSTR);
147                 psm = atoi(value);
148                 _bt_send_event(BT_L2CAP_LE_SERVER_EVENT,
149                                 BLUETOOTH_EVENT_L2CAP_LE_AUTHORIZE,
150                                 g_variant_new("(isi)", result, address, psm));
151         } else {
152                 BT_INFO("sending rfcomm authorize event");
153                 _bt_send_event(BT_RFCOMM_SERVER_EVENT,
154                                 BLUETOOTH_EVENT_RFCOMM_AUTHORIZE,
155                                 g_variant_new("(issssn)", result, address, uuid_str, name, path, fd));
156         }
157         BT_DBG("-");
158 }
159
160 static void __bt_socket_event_handler(int event_type, gpointer event_data)
161 {
162         BT_INFO("OAL event = 0x%x, \n", event_type);
163
164         switch (event_type) {
165         case OAL_EVENT_SOCKET_OUTGOING_CONNECTED: {
166                 event_socket_client_conn_t *client_info = event_data;
167
168                 __handle_outgoing_client_socket_connected(client_info);
169                 break;
170         }
171         case OAL_EVENT_SOCKET_DISCONNECTED: {
172                 event_socket_client_conn_t *client_info = event_data;
173
174                 __handle_socket_disconnected(client_info);
175                 break;
176         }
177         case OAL_EVENT_SOCKET_AUTHORIZE_REQUEST: {
178                 BT_INFO("Socket Authorization Request");
179                 __handle_socket_authorization_request((event_socket_authorize_req_t *)event_data);
180                 break;
181         }
182         default:
183                 BT_ERR("Invalid event:%d\n", event_type);
184                 break;
185         }
186 }
187
188 int _bt_socket_client_connect(int sock_type, char *address,
189                 char *remote_uuid, int channel, bt_socket_client_conn_cb cb)
190 {
191         int sock_fd = -1;
192         bt_address_t bd;
193         oal_uuid_t uuid;
194
195         retv_if(NULL == address, BLUETOOTH_ERROR_INVALID_PARAM);
196         retv_if(NULL != pending_conn_info, BLUETOOTH_ERROR_DEVICE_BUSY);
197
198         BT_DBG("+");
199
200
201         BT_INFO("sock_type: %d, address: %s, remote_uuid: %s, channel: %d",
202                         sock_type, address, remote_uuid, channel);
203
204         _bt_convert_addr_string_to_type(bd.addr, address);
205         if (remote_uuid)
206                 _bt_service_convert_uuid_string_to_type(uuid.uuid, remote_uuid);
207         else
208                 memset(&uuid, 0x00, sizeof(oal_uuid_t));
209
210         switch (sock_type) {
211         case SOCK_TYPE_RFCOMM:
212                 sock_fd = socket_connect(OAL_SOCK_RFCOMM, &uuid, channel, &bd);
213                 break;
214         case SOCK_TYPE_L2CAP_LE:
215                 sock_fd = socket_connect(OAL_SOCK_L2CAP_LE, NULL, channel, &bd);
216                 break;
217         default:
218                 BT_ERR("Socket type: %d not supported", sock_type);
219                 return BLUETOOTH_ERROR_NOT_SUPPORT;
220         }
221
222         if (0 > sock_fd) {
223                 BT_ERR("Bluetooth socket connect failed");
224                 return BLUETOOTH_ERROR_CONNECTION_ERROR;
225         }
226
227         pending_conn_info = g_malloc0(sizeof(bt_socket_info_t));
228         pending_conn_info->sock_fd = sock_fd;
229         pending_conn_info->chan = channel;
230         pending_conn_info->conn_cb = cb;
231         g_strlcpy(pending_conn_info->address, address, BT_ADDRESS_STRING_SIZE);
232
233         if (remote_uuid != NULL)
234                 g_strlcpy(pending_conn_info->uuid, remote_uuid, BT_UUID_STRING_SIZE);
235         else
236                 memset(pending_conn_info->uuid, 0x00, BT_UUID_STRING_SIZE);
237
238         BT_DBG("-");
239         return BLUETOOTH_ERROR_NONE;
240 }
241
242 int _bt_socket_listen(int sock_type, char *svc_name, char *server_uuid, int channel)
243 {
244         int sock_fd;
245         oal_uuid_t uuid;
246
247         if (sock_type != SOCK_TYPE_L2CAP_LE) {
248                 retv_if(NULL == svc_name, BLUETOOTH_ERROR_INVALID_PARAM);
249                 retv_if(NULL == server_uuid, BLUETOOTH_ERROR_INVALID_PARAM);
250
251                 BT_INFO("sock_type: %d, svc_name: %s, uuid: %s, channel: %d",
252                                 sock_type, svc_name, server_uuid, channel);
253
254                 _bt_service_convert_uuid_string_to_type(uuid.uuid, server_uuid);
255         }
256
257         switch (sock_type) {
258         case SOCK_TYPE_RFCOMM:
259                 sock_fd = socket_listen(OAL_SOCK_RFCOMM, &uuid, svc_name, channel);
260                 break;
261         case SOCK_TYPE_L2CAP_LE:
262                 sock_fd = socket_listen(OAL_SOCK_L2CAP_LE, NULL, NULL, channel);
263                 break;
264         default:
265                 BT_ERR("Socket type: %d not supported", sock_type);
266                 return BLUETOOTH_ERROR_NOT_SUPPORT;
267         }
268
269         if (0 > sock_fd) {
270                 BT_ERR("Bluetooth socket create failed");
271                 return BLUETOOTH_ERROR_INTERNAL;
272         }
273
274         return sock_fd;
275 }
276
277 int _bt_socket_init(void)
278 {
279         int result;
280         BT_INFO("Socket Init");
281
282         result = socket_enable();
283         if (result != OAL_STATUS_SUCCESS) {
284                 BT_ERR("Socket init failed");
285                 return _bt_convert_oal_status_to_bt_error(result);
286         }
287
288         /* Register SOCKET event handler */
289         _bt_service_register_event_handler_callback(BT_SOCKET_MODULE, __bt_socket_event_handler);
290         return BLUETOOTH_ERROR_NONE;
291 }
292
293 void _bt_socket_deinit(void)
294 {
295         BT_INFO("Socket de-init");
296
297         if (OAL_STATUS_SUCCESS != socket_disable())
298                 BT_ERR("Socket de-init failed");
299
300         /* Un-register SOCKET event handler */
301         _bt_service_unregister_event_handler_callback(BT_SOCKET_MODULE);
302 }