240b66d29034c282ccd1ab70c40e59ba03f804ee
[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
129         BT_DBG("+");
130
131         _bt_convert_addr_type_to_string(address, auth_event->address.addr);
132         _bt_service_convert_uuid_type_to_string(uuid_str, auth_event->uuid.uuid);
133         BT_INFO("Address: %s, UUID: %s", address, uuid_str);
134         _bt_send_event(BT_RFCOMM_SERVER_EVENT,
135                         BLUETOOTH_EVENT_RFCOMM_AUTHORIZE,
136                         g_variant_new("(iss)", result, address, uuid_str));
137         BT_DBG("-");
138 }
139
140 static void __bt_socket_event_handler(int event_type, gpointer event_data)
141 {
142         BT_INFO("OAL event = 0x%x, \n", event_type);
143
144         switch (event_type) {
145         case OAL_EVENT_SOCKET_OUTGOING_CONNECTED: {
146                 event_socket_client_conn_t *client_info = event_data;
147
148                 __handle_outgoing_client_socket_connected(client_info);
149                 break;
150         }
151         case OAL_EVENT_SOCKET_DISCONNECTED: {
152                 event_socket_client_conn_t *client_info = event_data;
153
154                 __handle_socket_disconnected(client_info);
155                 break;
156         }
157         case OAL_EVENT_SOCKET_AUTHORIZE_REQUEST: {
158                 BT_INFO("Socket Authorization Request");
159                 __handle_socket_authorization_request((event_socket_authorize_req_t *)event_data);
160                 break;
161         }
162         default:
163                 BT_ERR("Invalid event:%d\n", event_type);
164                 break;
165         }
166 }
167
168 int _bt_socket_client_connect(int sock_type, char *address,
169                 char *remote_uuid, int channel, bt_socket_client_conn_cb cb)
170 {
171         int sock_fd = -1;
172         bt_address_t bd;
173         oal_uuid_t uuid;
174
175         retv_if(NULL == address, BLUETOOTH_ERROR_INVALID_PARAM);
176         retv_if(NULL != pending_conn_info, BLUETOOTH_ERROR_DEVICE_BUSY);
177
178         BT_DBG("+");
179
180
181         BT_INFO("sock_type: %d, address: %s, remote_uuid: %s, channel: %d",
182                         sock_type, address, remote_uuid, channel);
183
184         _bt_convert_addr_string_to_type(bd.addr, address);
185         if (remote_uuid)
186                 _bt_service_convert_uuid_string_to_type(uuid.uuid, remote_uuid);
187         else
188                 memset(&uuid, 0x00, sizeof(oal_uuid_t));
189
190         switch (sock_type) {
191         case SOCK_TYPE_RFCOMM:
192                 sock_fd = socket_connect(OAL_SOCK_RFCOMM, &uuid, channel, &bd);
193                 break;
194         default:
195                 BT_ERR("Socket type: %d not supported");
196                 return BLUETOOTH_ERROR_NOT_SUPPORT;
197         }
198
199         if (0 > sock_fd) {
200                 BT_ERR("Bluetooth socket connect failed");
201                 return BLUETOOTH_ERROR_CONNECTION_ERROR;
202         }
203
204         pending_conn_info = g_malloc0(sizeof(bt_socket_info_t));
205         pending_conn_info->sock_fd = sock_fd;
206         pending_conn_info->chan = channel;
207         pending_conn_info->conn_cb = cb;
208         g_strlcpy(pending_conn_info->address, address, BT_ADDRESS_STRING_SIZE);
209         g_strlcpy(pending_conn_info->uuid, remote_uuid, BT_UUID_STRING_SIZE);
210
211         BT_DBG("-");
212         return BLUETOOTH_ERROR_NONE;
213 }
214
215 int _bt_socket_listen(int sock_type, char *svc_name, char *server_uuid, int channel)
216 {
217         int sock_fd;
218         oal_uuid_t uuid;
219
220         retv_if(NULL == svc_name, BLUETOOTH_ERROR_INVALID_PARAM);
221         retv_if(NULL == server_uuid, BLUETOOTH_ERROR_INVALID_PARAM);
222
223         BT_INFO("sock_type: %d, svc_name: %s, uuid: %s, channel: %d",
224                         sock_type, svc_name, server_uuid, channel);
225
226         _bt_service_convert_uuid_string_to_type(uuid.uuid, server_uuid);
227
228         switch (sock_type) {
229         case SOCK_TYPE_RFCOMM:
230                 sock_fd = socket_listen(OAL_SOCK_RFCOMM, &uuid, svc_name, channel);
231                 break;
232         default:
233                 BT_ERR("Socket type: %d not supported");
234                 return BLUETOOTH_ERROR_NOT_SUPPORT;
235         }
236
237         if (0 > sock_fd) {
238                 BT_ERR("Bluetooth socket create failed");
239                 return BLUETOOTH_ERROR_INTERNAL;
240         }
241
242         return sock_fd;
243 }
244
245 int _bt_socket_init(void)
246 {
247         BT_INFO("Socket Init");
248
249         if (OAL_STATUS_SUCCESS != socket_enable()) {
250                 BT_ERR("Socket init failed");
251                 return BLUETOOTH_ERROR_INTERNAL;
252         }
253
254         /* Register SOCKET event handler */
255         _bt_service_register_event_handler_callback(BT_SOCKET_MODULE, __bt_socket_event_handler);
256         return BLUETOOTH_ERROR_NONE;
257 }
258
259 void _bt_socket_deinit(void)
260 {
261         BT_INFO("Socket de-init");
262
263         if (OAL_STATUS_SUCCESS != socket_disable())
264                 BT_ERR("Socket de-init failed");
265
266         /* Un-register SOCKET event handler */
267         _bt_service_unregister_event_handler_callback(BT_SOCKET_MODULE);
268 }