71d9c3cf4d9d9b59ef7693a0255d4e86fc6dc835
[platform/core/connectivity/bluetooth-frwk.git] / bt-service-adaptation / 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 typedef struct {
40         int sock_fd;
41         int chan;
42         char uuid[BT_UUID_STRING_SIZE];
43         char address[BT_ADDRESS_STRING_SIZE];
44         bt_socket_client_conn_cb conn_cb;
45 } bt_socket_info_t;
46
47 bt_socket_info_t *pending_conn_info;
48
49 /* Function to handle socket disconnection */
50 void __handle_socket_disconnected(event_socket_client_conn_t *client_info)
51 {
52         char address[BT_ADDRESS_STRING_SIZE];
53
54         ret_if(NULL == client_info);
55
56         BT_DBG("+");
57
58         _bt_convert_addr_type_to_string(address, client_info->address.addr);
59
60         /*
61          * In case of an already connected socket, if disconnection happens, it will
62          * automatically detected in corresponding i/o handler and events will be sent
63          * from there. So here we only handle connection fail case.
64          */
65         if (NULL != pending_conn_info &&
66                         !strncasecmp(address, pending_conn_info->address, strlen(address))) {
67                 /*
68                  * Disconnection event is received for ongoing connection, invoke connection
69                  * state callback with error.
70                  */
71                 BT_INFO("socket_fd: %d, address: %s, uuid: %s, channel: %d",
72                                 client_info->fd, address,
73                                 pending_conn_info->uuid,
74                                 pending_conn_info->chan);
75
76                 pending_conn_info->conn_cb(BLUETOOTH_ERROR_INTERNAL, client_info->fd, address,
77                                 pending_conn_info->uuid, pending_conn_info->chan);
78
79                 g_free(pending_conn_info);
80                 pending_conn_info = NULL;
81         } else {
82                 BT_INFO("Disconnected Address: [%s], socket_fd: %d", address, client_info->fd);
83         }
84
85         BT_DBG("-");
86 }
87
88 /* Handle outgoing client socket connection event */
89 static void __handle_outgoing_client_socket_connected(event_socket_client_conn_t *client_info)
90 {
91         char address[BT_ADDRESS_STRING_SIZE];
92
93         ret_if(NULL == client_info);
94         ret_if(NULL == pending_conn_info);
95
96         BT_DBG("+");
97
98         /*
99          * Only one socket connect req at a time is allowed, so received address
100          * should match with pending request.
101          */
102         _bt_convert_addr_type_to_string(address, client_info->address.addr);
103         if (strncasecmp(address, pending_conn_info->address, strlen(address))) {
104                 BT_ERR("Address mismatch, Pending connection address: [%s]",
105                                 pending_conn_info->address);
106                 BT_ERR("Client connection callback called with address: [%s]", address);
107                 return;
108         }
109
110         BT_INFO("socket_fd: %d, address: %s, uuid: %s, channel: %d",
111                         client_info->fd, address,
112                         pending_conn_info->uuid,
113                         pending_conn_info->chan);
114
115         pending_conn_info->conn_cb(BLUETOOTH_ERROR_NONE, client_info->fd, address,
116                         pending_conn_info->uuid, pending_conn_info->chan);
117
118         g_free(pending_conn_info);
119         pending_conn_info = NULL;
120         BT_DBG("-");
121 }
122
123 static void __handle_socket_authorization_request(event_socket_authorize_req_t *auth_event)
124 {
125         char address[BT_ADDRESS_STRING_SIZE];
126         char uuid_str[BT_UUID_STRING_SIZE];
127         int result = BLUETOOTH_ERROR_NONE;
128         char name[249] = {0, };
129         char path[249] = {0, };
130         int fd;
131
132         BT_DBG("+");
133
134         _bt_convert_addr_type_to_string(address, auth_event->address.addr);
135         _bt_service_convert_uuid_type_to_string(uuid_str, auth_event->uuid.uuid);
136         memcpy(name, auth_event->name, sizeof(auth_event->name) - 1);
137         memcpy(path, auth_event->path, sizeof(auth_event->path) - 1);
138         fd = auth_event->fd;
139         BT_INFO("Address: %s, UUID: %s, Name: %s, Path: %s, Fd: %d", address, uuid_str, name, path, fd);
140         _bt_send_event(BT_RFCOMM_SERVER_EVENT,
141                         BLUETOOTH_EVENT_RFCOMM_AUTHORIZE,
142                         g_variant_new("(issssn)", result, address, uuid_str, name, path, fd));
143         BT_DBG("-");
144 }
145
146 static void __bt_socket_event_handler(int event_type, gpointer event_data)
147 {
148         BT_INFO("OAL event = 0x%x, \n", event_type);
149
150         switch (event_type) {
151         case OAL_EVENT_SOCKET_OUTGOING_CONNECTED: {
152                 event_socket_client_conn_t *client_info = event_data;
153
154                 __handle_outgoing_client_socket_connected(client_info);
155                 break;
156         }
157         case OAL_EVENT_SOCKET_DISCONNECTED: {
158                 event_socket_client_conn_t *client_info = event_data;
159
160                 __handle_socket_disconnected(client_info);
161                 break;
162         }
163         case OAL_EVENT_SOCKET_AUTHORIZE_REQUEST: {
164                 BT_INFO("Socket Authorization Request");
165                 __handle_socket_authorization_request((event_socket_authorize_req_t *)event_data);
166                 break;
167         }
168         default:
169                 BT_ERR("Invalid event:%d\n", event_type);
170                 break;
171         }
172 }
173
174 int _bt_socket_client_connect(int sock_type, char *address,
175                 char *remote_uuid, int channel, bt_socket_client_conn_cb cb)
176 {
177         int sock_fd = -1;
178         bt_address_t bd;
179         oal_uuid_t uuid;
180
181         retv_if(NULL == address, BLUETOOTH_ERROR_INVALID_PARAM);
182         retv_if(NULL != pending_conn_info, BLUETOOTH_ERROR_DEVICE_BUSY);
183
184         BT_DBG("+");
185
186
187         BT_INFO("sock_type: %d, address: %s, remote_uuid: %s, channel: %d",
188                         sock_type, address, remote_uuid, channel);
189
190         _bt_convert_addr_string_to_type(bd.addr, address);
191         if (remote_uuid)
192                 _bt_service_convert_uuid_string_to_type(uuid.uuid, remote_uuid);
193         else
194                 memset(&uuid, 0x00, sizeof(oal_uuid_t));
195
196         switch (sock_type) {
197         case SOCK_TYPE_RFCOMM:
198                 sock_fd = socket_connect(OAL_SOCK_RFCOMM, &uuid, channel, &bd);
199                 break;
200         default:
201                 BT_ERR("Socket type: %d not supported", sock_type);
202                 return BLUETOOTH_ERROR_NOT_SUPPORT;
203         }
204
205         if (0 > sock_fd) {
206                 BT_ERR("Bluetooth socket connect failed");
207                 return BLUETOOTH_ERROR_CONNECTION_ERROR;
208         }
209
210         pending_conn_info = g_malloc0(sizeof(bt_socket_info_t));
211         pending_conn_info->sock_fd = sock_fd;
212         pending_conn_info->chan = channel;
213         pending_conn_info->conn_cb = cb;
214         g_strlcpy(pending_conn_info->address, address, BT_ADDRESS_STRING_SIZE);
215
216         if (remote_uuid != NULL)
217                 g_strlcpy(pending_conn_info->uuid, remote_uuid, BT_UUID_STRING_SIZE);
218         else
219                 memset(pending_conn_info->uuid, 0x00, BT_UUID_STRING_SIZE);
220
221         BT_DBG("-");
222         return BLUETOOTH_ERROR_NONE;
223 }
224
225 int _bt_socket_listen(int sock_type, char *svc_name, char *server_uuid, int channel)
226 {
227         int sock_fd;
228         oal_uuid_t uuid;
229
230         retv_if(NULL == svc_name, BLUETOOTH_ERROR_INVALID_PARAM);
231         retv_if(NULL == server_uuid, BLUETOOTH_ERROR_INVALID_PARAM);
232
233         BT_INFO("sock_type: %d, svc_name: %s, uuid: %s, channel: %d",
234                         sock_type, svc_name, server_uuid, channel);
235
236         _bt_service_convert_uuid_string_to_type(uuid.uuid, server_uuid);
237
238         switch (sock_type) {
239         case SOCK_TYPE_RFCOMM:
240                 sock_fd = socket_listen(OAL_SOCK_RFCOMM, &uuid, svc_name, channel);
241                 break;
242         default:
243                 BT_ERR("Socket type: %d not supported", sock_type);
244                 return BLUETOOTH_ERROR_NOT_SUPPORT;
245         }
246
247         if (0 > sock_fd) {
248                 BT_ERR("Bluetooth socket create failed");
249                 return BLUETOOTH_ERROR_INTERNAL;
250         }
251
252         return sock_fd;
253 }
254
255 int _bt_socket_init(void)
256 {
257         BT_INFO("Socket Init");
258
259         if (OAL_STATUS_SUCCESS != socket_enable()) {
260                 BT_ERR("Socket init failed");
261                 return BLUETOOTH_ERROR_INTERNAL;
262         }
263
264         /* Register SOCKET event handler */
265         _bt_service_register_event_handler_callback(BT_SOCKET_MODULE, __bt_socket_event_handler);
266         return BLUETOOTH_ERROR_NONE;
267 }
268
269 void _bt_socket_deinit(void)
270 {
271         BT_INFO("Socket de-init");
272
273         if (OAL_STATUS_SUCCESS != socket_disable())
274                 BT_ERR("Socket de-init failed");
275
276         /* Un-register SOCKET event handler */
277         _bt_service_unregister_event_handler_callback(BT_SOCKET_MODULE);
278 }