Fix infinite callback issue in EOF status
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-l2cap-le-server.c
1 /*
2  * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *              http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <string.h>
19 #include <sys/socket.h>
20 #include <gio/gunixfdlist.h>
21 #include "bluetooth-api.h"
22 #include "bt-internal-types.h"
23 #include "bt-common.h"
24 #include "bt-request-sender.h"
25 #include "bt-event-handler.h"
26
27 #define SOCK_INT_LEN 4
28
29 #ifdef TIZEN_BLUEDROID_PORTING
30 #define BLUETOOTH_SOCK_CONNECT_INFO_LEN 20
31 #else
32 #define BLUETOOTH_SOCK_CONNECT_INFO_LEN 16
33 #endif
34
35 #define BT_L2CAP_LE_SERVER_ID_MAX 254
36
37 typedef struct {
38         char addr[BT_ADDRESS_STRING_SIZE];
39         int sock_fd;
40         int watch_id;
41         int server_id;
42 } l2cap_le_remote_client_info_t;
43
44 typedef struct {
45         int psm;
46         int server_id;
47         int server_fd;
48         int watch_id;
49         int max_pending_conn;
50         gboolean auto_accept;
51         char pending_addr[BT_ADDRESS_STRING_SIZE];
52         GSList *conn_list;
53 } l2cap_le_server_info_t;
54
55 static GSList *l2cap_le_servers;
56 static gboolean id_used[BT_L2CAP_LE_SERVER_ID_MAX];
57 static int latest_id = 0;
58
59 int __l2cap_le_assign_server_id(void)
60 {
61         int index;
62
63         BT_DBG("latest_id: %d", latest_id);
64
65         index = latest_id + 1;
66         if (index >= BT_L2CAP_LE_SERVER_ID_MAX)
67                 index = 0;
68
69         BT_DBG("index: %d", index);
70
71         while (id_used[index] == TRUE) {
72                 if (index == latest_id) {
73                         /* No available ID */
74                         BT_ERR("All request ID is used");
75                         return -1;
76                 }
77
78                 index++;
79                 if (index >= BT_L2CAP_LE_SERVER_ID_MAX)
80                         index = 0;
81         }
82
83         latest_id = index;
84         id_used[index] = TRUE;
85         BT_DBG("Assigned Id: %d", latest_id);
86
87         return latest_id;
88 }
89
90 void __l2cap_le_delete_server_id(int id)
91 {
92         ret_if(id >= BT_L2CAP_LE_SERVER_ID_MAX);
93         ret_if(id < 0);
94
95         id_used[id] = FALSE;
96
97         /* Next server will use this ID */
98         latest_id = id - 1;
99 }
100
101 static l2cap_le_server_info_t *__get_l2cap_le_server_info_from_psm(int psm)
102 {
103         GSList *l;
104
105         if (psm < 0)
106                 return NULL;
107
108         for (l = l2cap_le_servers; l != NULL; l = l->next) {
109                 l2cap_le_server_info_t *info = l->data;
110
111                 if (info->psm == psm) {
112                         BT_INFO("server found with psm %d fd %d", info->psm,
113                                         info->server_fd);
114                         return info;
115                 }
116         }
117
118         return NULL;
119 }
120
121 int _get_l2cap_le_server_id(int psm, gboolean *auto_accept)
122 {
123         l2cap_le_server_info_t *server_info;
124
125         server_info = __get_l2cap_le_server_info_from_psm(psm);
126         if (!server_info)
127                 return -1;
128
129         *auto_accept = server_info->auto_accept;
130         return server_info->server_id;
131 }
132
133 static l2cap_le_server_info_t *__get_l2cap_le_server_info_with_id(int server_id)
134 {
135         GSList *l;
136
137         for (l = l2cap_le_servers; l != NULL; l = l->next) {
138                 l2cap_le_server_info_t *info = l->data;
139                 if (!info)
140                         continue;
141
142                 BT_DBG("info->server_fd: %d, sock_fd:%d", info->server_id, server_id);
143                 if (info->server_id == server_id)
144                         return info;
145         }
146
147         return NULL;
148 }
149
150 void _bt_l2cap_le_server_set_pending_conn(int server_id, char *address)
151 {
152         l2cap_le_server_info_t *server_info;
153
154         if (!address)
155                 return;
156
157         server_info = __get_l2cap_le_server_info_with_id(server_id);
158         if (!server_info)
159                 return;
160
161         g_strlcpy(server_info->pending_addr, address, BT_ADDRESS_STRING_SIZE);
162 }
163
164 static l2cap_le_remote_client_info_t *__get_l2cap_le_rem_client_info_with_fd(
165                                                 int sock_fd)
166 {
167         GSList *l;
168         GSList *l1;
169
170         for (l = l2cap_le_servers; l != NULL; l = l->next) {
171                 l2cap_le_server_info_t *info = l->data;
172
173                 if (!info)
174                         continue;
175
176                 for (l1 = info->conn_list; l1 != NULL; l1 = l1->next) {
177                         l2cap_le_remote_client_info_t *client_info = l1->data;
178                         if (!client_info)
179                                 continue;
180
181                         if (client_info->sock_fd == sock_fd)
182                                 return client_info;
183                 }
184         }
185
186         return NULL;
187 }
188
189 static l2cap_le_remote_client_info_t *__get_l2cap_le_rem_client_info_with_addr(
190                                                 char *addr)
191 {
192         GSList *l;
193         GSList *l1;
194
195         retv_if(NULL == addr, NULL);
196
197         for (l = l2cap_le_servers; l != NULL; l = l->next) {
198                 l2cap_le_server_info_t *info = l->data;
199
200                 if (!info)
201                         continue;
202
203                 for (l1 = info->conn_list; l1 != NULL; l1 = l1->next) {
204                         l2cap_le_remote_client_info_t *client_info = l1->data;
205                         if (!client_info)
206                                 continue;
207
208                         if (!strncasecmp(client_info->addr, addr, strlen(client_info->addr)))
209                                 return client_info;
210                 }
211         }
212
213         return NULL;
214 }
215
216 static void __remove_remote_client_info(l2cap_le_remote_client_info_t *rem_client)
217 {
218         BT_DBG("+");
219
220         if (rem_client == NULL)
221                 return;
222
223         if (0 < rem_client->sock_fd) {
224                 shutdown(rem_client->sock_fd, SHUT_RDWR);
225                 close(rem_client->sock_fd);
226         }
227
228         if (rem_client->watch_id > 0)
229                 g_source_remove(rem_client->watch_id);
230
231         g_free(rem_client);
232
233         BT_DBG("-");
234 }
235
236 static void __handle_l2cap_le_client_disconnected(
237                 l2cap_le_server_info_t *server_info, l2cap_le_remote_client_info_t *rem_client)
238 {
239         bluetooth_l2cap_le_disconnection_t disconn_info;
240         bt_event_info_t *event_info;
241
242         BT_DBG("+");
243
244         if (rem_client == NULL || server_info == NULL)
245                 return;
246
247         event_info = _bt_event_get_cb_data(BT_L2CAP_LE_SERVER_EVENT);
248         if (event_info == NULL)
249                 return;
250
251         memset(&disconn_info, 0x00, sizeof(bluetooth_l2cap_le_disconnection_t));
252         disconn_info.device_role = L2CAP_LE_ROLE_SERVER;
253         disconn_info.psm = server_info->psm;
254         _bt_convert_addr_string_to_type(disconn_info.device_addr.addr, rem_client->addr);
255         BT_DBG("Disconnected FD [%d] PSM [%d]", rem_client->sock_fd, server_info->psm);
256         disconn_info.socket_fd = rem_client->sock_fd;
257
258         _bt_common_event_cb(BLUETOOTH_EVENT_L2CAP_LE_DISCONNECTED,
259                         BLUETOOTH_ERROR_NONE, &disconn_info,
260                         event_info->cb, event_info->user_data);
261         BT_DBG("-");
262 }
263
264 static void __remove_l2cap_le_server(l2cap_le_server_info_t *info)
265 {
266         l2cap_le_remote_client_info_t *client_info;
267
268         BT_DBG("+");
269
270         if (!info)
271                 return;
272
273         l2cap_le_servers = g_slist_remove(l2cap_le_servers, info);
274         if (info->conn_list) {
275                 do {
276                         client_info = info->conn_list->data;
277                         if (!client_info)
278                                 break;
279
280                         BT_INFO("Disconnect l2cap_le client fd %d", client_info->sock_fd);
281                         info->conn_list = g_slist_remove(info->conn_list, client_info);
282                         __handle_l2cap_le_client_disconnected(info, client_info);
283                         __remove_remote_client_info(client_info);
284                 } while (info->conn_list);
285         }
286
287         if (info->server_fd) {
288                 shutdown(info->server_fd, SHUT_RDWR);
289                 close(info->server_fd);
290         }
291
292         if (info->watch_id)
293                 g_source_remove(info->watch_id);
294
295         __l2cap_le_delete_server_id(info->server_id);
296         g_free(info);
297
298         BT_DBG("-");
299 }
300
301 static void __connected_cb(l2cap_le_remote_client_info_t *client_info,
302                                         bt_event_info_t *event_info)
303 {
304         bluetooth_l2cap_le_connection_t conn_info;
305         l2cap_le_server_info_t *server_info;
306
307         server_info = __get_l2cap_le_server_info_with_id(client_info->server_id);
308         ret_if(server_info == NULL);
309
310         memset(&conn_info, 0x00, sizeof(bluetooth_l2cap_le_connection_t));
311         conn_info.device_role = L2CAP_LE_ROLE_SERVER;
312         conn_info.socket_fd = client_info->sock_fd;
313         conn_info.psm = server_info->psm;
314         _bt_convert_addr_string_to_type(conn_info.device_addr.addr, client_info->addr);
315         conn_info.server_id = server_info->server_id;
316
317         BT_INFO_C("Connected [L2CAP_LE Server] psm %d", server_info->psm);
318         _bt_common_event_cb(BLUETOOTH_EVENT_L2CAP_LE_CONNECTED,
319                         BLUETOOTH_ERROR_NONE, &conn_info,
320                         event_info->cb, event_info->user_data);
321 }
322
323 static int __process_cmsg(struct msghdr *msg)
324 {
325         int sock_fd = -1;
326         struct cmsghdr *cmsg_ptr = NULL;
327
328         for (cmsg_ptr = CMSG_FIRSTHDR(msg); cmsg_ptr != NULL;
329                         cmsg_ptr = CMSG_NXTHDR(msg, cmsg_ptr)) {
330
331                 if (cmsg_ptr->cmsg_level != SOL_SOCKET)
332                         continue;
333
334                 if (cmsg_ptr->cmsg_type == SCM_RIGHTS) {
335                         int count
336                                 = ((cmsg_ptr->cmsg_len - CMSG_LEN(0)) / sizeof(int));
337
338                         if (count < 0) {
339                                 BT_ERR("ERROR Invalid count of descriptors");
340                                 continue;
341                         }
342
343                         memcpy(&sock_fd, CMSG_DATA(cmsg_ptr), sizeof(sock_fd));
344                         BT_DBG("Remote client fd: %d", sock_fd);
345                 }
346         }
347         return sock_fd;
348 }
349
350 static int __sock_read(int server_fd, char *buf, unsigned int len,
351                                         int *client_fd)
352 {
353         int ret;
354         struct msghdr msg;
355         struct iovec iv;
356         struct cmsghdr cmsgbuf[2 * sizeof(struct cmsghdr) + 4];
357         int retryCount = 0;
358
359         retv_if(0 > server_fd, -1);
360
361         BT_INFO("server_fd = %d", server_fd);
362
363         memset(&msg, 0, sizeof(msg));
364         memset(&iv, 0, sizeof(iv));
365
366         iv.iov_base = buf;
367         iv.iov_len = len;
368         msg.msg_iov = &iv;
369         msg.msg_iovlen = 1;
370         msg.msg_control = cmsgbuf;
371         msg.msg_controllen = sizeof(cmsgbuf);
372
373         for (retryCount = 0; retryCount < 5; retryCount++) {
374                 ret = recvmsg(server_fd, &msg, 0);
375                 BT_DBG("recvmsg ret = %d", ret);
376                 if (ret < 0 && errno == EINTR)
377                         continue;
378                 else
379                         break;
380         }
381
382         if (ret < 0 && errno == EPIPE) {
383                 /* End of stream, server listining stopped */
384                 BT_ERR("EOS errno: %d", errno);
385                 return 0;
386         }
387
388         if (ret < 0) {
389                 BT_ERR("Ret errno: %d", errno);
390                 return -1;
391         }
392
393         if ((msg.msg_flags & (MSG_CTRUNC | MSG_OOB | MSG_ERRQUEUE)) != 0) {
394                 BT_ERR("MSG Flags errno: %d", errno);
395                 return -1;
396         }
397
398         if (ret >= 0 && client_fd) {
399                 BT_INFO("Connection received");
400                 *client_fd = __process_cmsg(&msg);
401                 if (*client_fd < 0)
402                         BT_ERR("Invalid client_fd received");
403         }
404
405         return ret;
406 }
407
408 static gboolean __data_received_cb(GIOChannel *chan, GIOCondition cond,
409                                                 gpointer data)
410 {
411         char *buffer = NULL;
412         gsize len = 0;
413         int result = BLUETOOTH_ERROR_NONE;
414         bt_event_info_t *event_info;
415         bluetooth_l2cap_le_received_data_t data_r;
416         GIOStatus status = G_IO_STATUS_NORMAL;
417         GError *err = NULL;
418         l2cap_le_remote_client_info_t *client_info = data;
419         l2cap_le_server_info_t *server_info;
420
421         retv_if(client_info == NULL, FALSE);
422
423         server_info = __get_l2cap_le_server_info_with_id(client_info->server_id);
424
425         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
426                 BT_ERR_C("l2cap_le Server disconnected: %d", client_info->sock_fd);
427                 goto fail;
428         }
429
430         buffer = g_malloc0(BT_L2CAP_LE_BUFFER_LEN + 1);
431         status = g_io_channel_read_chars(chan, buffer,
432                         BT_L2CAP_LE_BUFFER_LEN, &len, &err);
433         if (status != G_IO_STATUS_NORMAL) {
434                 BT_ERR("IO Channel read is failed with %d(%s)", status, _bt_print_gio_status(status));
435                 g_free(buffer);
436
437                 if (status == G_IO_STATUS_AGAIN)
438                         return TRUE;
439
440                 if (err) {
441                         BT_ERR("IO Channel read error [%s]", err->message);
442                         g_error_free(err);
443                 }
444                 goto fail;
445         }
446
447         if (len == 0) {
448                 BT_ERR("Length is zero, remote end hang up");
449                 g_free(buffer);
450                 goto fail;
451         }
452
453         event_info = _bt_event_get_cb_data(BT_L2CAP_LE_SERVER_EVENT);
454         if (event_info == NULL) {
455                 g_free(buffer);
456                 return TRUE;
457         }
458
459         data_r.socket_fd = client_info->sock_fd;
460         data_r.buffer_size = len;
461         data_r.buffer = buffer;
462
463         _bt_common_event_cb(BLUETOOTH_EVENT_L2CAP_LE_DATA_RECEIVED,
464                         result, &data_r, event_info->cb, event_info->user_data);
465
466         g_free(buffer);
467         return TRUE;
468 fail:
469         BT_ERR("Failure occured, remove client connection");
470         if (server_info)
471                 server_info->conn_list = g_slist_remove(
472                         server_info->conn_list, client_info);
473         __handle_l2cap_le_client_disconnected(server_info, client_info);
474         client_info->watch_id = -1;
475         __remove_remote_client_info(client_info);
476         return FALSE;
477 }
478
479 static gboolean __new_connection_request_cb(GIOChannel *chan,
480                                                 GIOCondition cond, gpointer data)
481 {
482         int len;
483         int size;
484         int channel;
485         int status;
486         int client_fd;
487         char buf[BLUETOOTH_SOCK_CONNECT_INFO_LEN];
488         unsigned char addr[BT_ADDRESS_LENGTH_MAX];
489
490         bt_event_info_t *event_info;
491         GIOChannel *io;
492         l2cap_le_remote_client_info_t *rem_client;
493         l2cap_le_server_info_t *server_info = data;
494
495         if (!server_info) {
496                 BT_ERR("Server info is invalid");
497                 return FALSE;
498         }
499
500         if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
501                 BT_INFO("l2cap_le Server with fd:%d is closed with cond:0x%X",
502                                 server_info->server_fd, cond);
503                 goto err;
504         }
505
506         BT_INFO("Server fd: %d", server_info->server_fd);
507         len = __sock_read( server_info->server_fd, buf,
508                                         BLUETOOTH_SOCK_CONNECT_INFO_LEN, &client_fd);
509         BT_DBG("Socket Read len: %d", len);
510         if (len == 0) {
511                 BT_ERR("Listen stopped");
512                 goto err;
513         } else if (len != BLUETOOTH_SOCK_CONNECT_INFO_LEN) {
514                 BT_ERR("Read length is not same as socket info length");
515                 goto err;
516         }
517
518         len = 0;
519         /* Read size of data */
520         size = buf[len] | (buf[len + 1] << 8);
521         len += 2;
522
523         /* Read bluetooth address */
524         memcpy(addr, buf + len, BT_ADDRESS_LENGTH_MAX);
525         len += BT_ADDRESS_LENGTH_MAX;
526
527         /* Read channel */
528         channel = buf[len] | (buf[len + 1] << 8) |
529                 (buf[len + 2] << 16) | (buf[len + 3] << 24);
530         len += 4;
531
532         /* Read status */
533         status = buf[len] | (buf[len + 1] << 8) |
534                 (buf[len + 2] << 16) | (buf[len + 3] << 24);
535         len += 4;
536
537         BT_DBG("size: %d, channel: %d, status: %d", size, channel, status);
538
539         rem_client = g_malloc0(sizeof(l2cap_le_remote_client_info_t));
540         rem_client->sock_fd = client_fd;
541         rem_client->server_id = server_info->server_id;
542         _bt_convert_addr_type_to_string(rem_client->addr, addr);
543
544         BT_INFO("New client [%s] connection with socket_fd: %d, server_id: %d",
545                         rem_client->addr, rem_client->sock_fd, rem_client->server_id);
546
547         io = g_io_channel_unix_new(rem_client->sock_fd);
548         g_io_channel_set_encoding(io, NULL, NULL);
549         g_io_channel_set_flags(io, G_IO_FLAG_NONBLOCK, NULL);
550         rem_client->watch_id = g_io_add_watch(io,
551                         G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
552                         __data_received_cb, rem_client);
553         g_io_channel_unref(io);
554
555         server_info->conn_list = g_slist_append(server_info->conn_list, rem_client);
556         event_info = _bt_event_get_cb_data(BT_L2CAP_LE_SERVER_EVENT);
557         if (event_info)
558                 __connected_cb(rem_client, event_info);
559
560         return TRUE;
561
562 err:
563         /* Error occurred, Remove l2cap_le server*/
564         BT_ERR("some error has occured, remove server");
565         __remove_l2cap_le_server(server_info);
566         return FALSE;
567 }
568
569 static int __getInt(char *buf, int len)
570 {
571         int val = 0;
572
573         if (len != SOCK_INT_LEN)
574                 return -1;
575
576         val = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
577         return val;
578 }
579
580 static int __sock_wait_for_psm(int sock_fd)
581 {
582         int readlen = -1;
583         char buf[SOCK_INT_LEN];
584
585         readlen = __sock_read(sock_fd, buf, SOCK_INT_LEN, NULL);
586         return __getInt(buf, readlen);
587 }
588
589 static int __l2cap_le_listen(l2cap_le_server_info_t *server_info, bool accept)
590 {
591         int result;
592         GUnixFDList *out_fd_list = NULL;
593         GIOChannel *server_io;
594         int psm;
595
596         retv_if(server_info == NULL, BLUETOOTH_ERROR_INTERNAL);
597
598         BT_INIT_PARAMS();
599         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
600
601         psm = server_info->psm;
602         g_array_append_vals(in_param1, &psm, sizeof(int));
603
604         if (accept == false)
605                 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_L2CAP_LE_LISTEN,
606                                 in_param1, in_param2, in_param3, in_param4, NULL, &out_param, &out_fd_list);
607         else
608                 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_L2CAP_LE_LISTEN_AND_ACCEPT,
609                                 in_param1, in_param2, in_param3, in_param4, NULL, &out_param, &out_fd_list);
610
611         BT_INFO("result: %x", result);
612         if (result != BLUETOOTH_ERROR_NONE) {
613                 BT_ERR("Fail to send request");
614                 return result;
615         } else if (NULL == out_fd_list) {
616                 BT_ERR("out_fd_list is NULL");
617                 return BLUETOOTH_ERROR_INTERNAL;
618         } else {
619                 int *fd_list_array;
620                 int len = 0;
621
622                 fd_list_array = g_unix_fd_list_steal_fds(out_fd_list, &len);
623                 BT_INFO("Num fds in fd_list is : %d, fd_list[0]: %d", len, fd_list_array[0]);
624                 server_info->server_fd = fd_list_array[0];
625                 BT_INFO("Socket fd: %d", server_info->server_fd);
626
627                 g_free(fd_list_array);
628                 g_object_unref(out_fd_list);
629         }
630
631         psm = __sock_wait_for_psm(server_info->server_fd);
632         if (psm < 0) {
633                 BT_ERR("Reading PSM failed, psm %d", psm);
634                 return BLUETOOTH_ERROR_INTERNAL;
635         }
636         server_info->psm = psm;
637
638         BT_INFO("socket fd: %d psm %d", server_info->server_fd, server_info->psm);
639         server_io = g_io_channel_unix_new(server_info->server_fd);
640         g_io_channel_set_encoding(server_io, NULL, NULL);
641         g_io_channel_set_flags(server_io, G_IO_FLAG_NONBLOCK, NULL);
642         server_info->watch_id = g_io_add_watch(server_io,
643                         G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
644                         __new_connection_request_cb, server_info);
645         g_io_channel_unref(server_io);
646
647         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
648
649         return BLUETOOTH_ERROR_NONE;
650 }
651
652 BT_EXPORT_API int bluetooth_l2cap_le_create_socket(int psm)
653 {
654         l2cap_le_server_info_t *server_info;
655
656         BT_CHECK_ENABLED_LE(return);
657
658         if (_bt_check_privilege_le(BT_CHECK_PRIVILEGE, BT_L2CAP_LE_CREATE_SOCKET)
659                 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
660                 BT_ERR("Don't have a privilege to use this API");
661                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
662         }
663
664         BT_INFO("<<<<<<<<< L2CAP_LE Create socket from app, psm %d >>>>>>>>>", psm);
665
666         server_info = __get_l2cap_le_server_info_from_psm(psm);
667         if (!server_info) {
668                 server_info = g_malloc0(sizeof(l2cap_le_server_info_t));
669                 server_info->psm = psm;
670                 server_info->server_id = __l2cap_le_assign_server_id();
671                 server_info->server_fd = -1;
672                 server_info->watch_id = -1;
673                 server_info->auto_accept = FALSE;
674                 l2cap_le_servers = g_slist_append(l2cap_le_servers, server_info);
675         }
676
677         return server_info->server_id;
678 }
679
680 BT_EXPORT_API int bluetooth_l2cap_le_remove_socket(int id)
681 {
682         l2cap_le_server_info_t *server_info;
683
684         BT_CHECK_ENABLED_LE(return);
685
686         if (_bt_check_privilege_le(BT_CHECK_PRIVILEGE, BT_L2CAP_LE_REMOVE_SOCKET)
687                 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
688                 BT_ERR("Don't have a privilege to use this API");
689                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
690         }
691
692         if (id < 0) {
693                 BT_ERR("Invalid ID");
694                 return BLUETOOTH_ERROR_INVALID_PARAM;
695         }
696
697         BT_INFO("<<<<<< L2CAP_LE Remove socket request from app, fd=[%d] >>>>>>", id);
698
699         server_info = __get_l2cap_le_server_info_with_id(id);
700         if (!server_info) {
701                 BT_ERR("server_info not found for socket_fd: %d", id);
702                 return BLUETOOTH_ERROR_INVALID_PARAM;
703         }
704
705         __remove_l2cap_le_server(server_info);
706
707         return BLUETOOTH_ERROR_NONE;
708 }
709
710 BT_EXPORT_API int bluetooth_l2cap_le_server_disconnect(int socket_fd)
711 {
712         l2cap_le_remote_client_info_t *client_info;
713
714         BT_CHECK_ENABLED_LE(return);
715
716         BT_INFO("<<<<<< L2CAP_LE server disconnect request from APP >>>>>>");
717         if (socket_fd < 0) {
718                 BT_ERR("Invalid FD");
719                 return BLUETOOTH_ERROR_INVALID_PARAM;
720         }
721
722         client_info = __get_l2cap_le_rem_client_info_with_fd(socket_fd);
723         if (!client_info) {
724                 BT_ERR("client_info not found for socket_fd: %d", socket_fd);
725                 return BLUETOOTH_ERROR_NOT_CONNECTED;
726         }
727
728         if (0 < client_info->sock_fd) {
729                 l2cap_le_server_info_t *server_info;
730
731                 /* Remove IO watch for client socket */
732                 if (0 < client_info->watch_id)
733                         g_source_remove(client_info->watch_id);
734                 client_info->watch_id = -1;
735
736                 /* close client socket and send L2CAP_LE disconneted event */
737                 shutdown(client_info->sock_fd, SHUT_RDWR);
738                 close(client_info->sock_fd);
739                 server_info = __get_l2cap_le_server_info_with_id(
740                                 client_info->server_id);
741                 __handle_l2cap_le_client_disconnected(
742                                 server_info, client_info);
743                 client_info->sock_fd = -1;
744
745                 /* Remove remote client info from l2cap_le server context */
746                 if (server_info)
747                         server_info->conn_list = g_slist_remove(
748                                 server_info->conn_list, client_info);
749
750                 /* Release remote client info */
751                 __remove_remote_client_info(client_info);
752         }
753
754         return BLUETOOTH_ERROR_NONE;
755 }
756
757 BT_EXPORT_API gboolean bluetooth_l2cap_le_is_server_psm_available(int psm)
758 {
759         int result;
760         gboolean available = TRUE;
761         int t_psm;
762
763         retv_if(bluetooth_check_adapter_le() ==
764                                 BLUETOOTH_ADAPTER_DISABLED, FALSE);
765
766         BT_INIT_PARAMS();
767         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
768
769         t_psm = psm;
770         g_array_append_vals(in_param1, &t_psm, sizeof(int));
771
772         /* TODO: Need to implement BT_L2CAP_LE_IS_PSM_AVAILABLE in BT-Service  */
773         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_L2CAP_LE_IS_PSM_AVAILABLE,
774                 in_param1, in_param2, in_param3, in_param4, &out_param);
775
776         BT_DBG("result: %x", result);
777
778         if (result == BLUETOOTH_ERROR_NONE)
779                 available = g_array_index(out_param, gboolean, 0);
780
781         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
782
783         BT_DBG("available: %d", available);
784
785         return available;
786 }
787
788 BT_EXPORT_API int bluetooth_l2cap_le_server_is_connected(
789                                         const bluetooth_device_address_t *device_address, gboolean *connected)
790 {
791         char input_addr[BT_ADDRESS_STRING_SIZE] = { 0 };
792         l2cap_le_remote_client_info_t *info;
793
794         BT_CHECK_PARAMETER(device_address, return);
795         BT_CHECK_PARAMETER(connected, return);
796
797         *connected = FALSE;
798
799         _bt_convert_addr_type_to_string(input_addr,
800                                         (unsigned char *)device_address->addr);
801         info = __get_l2cap_le_rem_client_info_with_addr(input_addr);
802         if (info)
803                 *connected = TRUE;
804
805         return BLUETOOTH_ERROR_NONE;
806 }
807
808 BT_EXPORT_API int bluetooth_l2cap_le_listen_and_accept(int id, int max_pending_connection)
809 {
810         l2cap_le_server_info_t *server_info;
811
812         BT_CHECK_ENABLED_LE(return);
813         if (id < 0) {
814                 BT_ERR("Invalid ID");
815                 return BLUETOOTH_ERROR_INVALID_PARAM;
816         }
817
818         BT_INFO("<<<<<<<<< L2CAP_LE Listen & accept from app >>>>>>>>>>>");
819
820         server_info = __get_l2cap_le_server_info_with_id(id);
821         if (!server_info) {
822                 BT_ERR("server_info not found for id: %d", id);
823                 return BLUETOOTH_ERROR_INVALID_PARAM;
824         }
825
826         if (server_info->server_fd >= 0) {
827                 BT_ERR("server already listening");
828                 return BLUETOOTH_ERROR_DEVICE_BUSY;
829         }
830
831         server_info->max_pending_conn = max_pending_connection;
832         server_info->auto_accept = TRUE;
833
834         return __l2cap_le_listen(server_info, true);
835 }
836
837 BT_EXPORT_API int bluetooth_l2cap_le_listen(int id, int max_pending_connection)
838 {
839         l2cap_le_server_info_t *server_info;
840
841         BT_CHECK_ENABLED_LE(return);
842         if (id < 0) {
843                 BT_ERR("Invalid ID");
844                 return BLUETOOTH_ERROR_INVALID_PARAM;
845         }
846
847         BT_INFO("<<<<<<<<< L2CAP_LE Listen >>>>>>>>>>>");
848
849         server_info = __get_l2cap_le_server_info_with_id(id);
850         if (!server_info) {
851                 BT_ERR("server_info not found for id: %d", id);
852                 return BLUETOOTH_ERROR_INVALID_PARAM;
853         }
854
855         if (server_info->server_fd >= 0) {
856                 BT_ERR("server already listening");
857                 return BLUETOOTH_ERROR_DEVICE_BUSY;
858         }
859
860         server_info->max_pending_conn = max_pending_connection;
861         server_info->auto_accept = FALSE;
862
863         return __l2cap_le_listen(server_info, false);
864 }
865
866
867 BT_EXPORT_API int bluetooth_l2cap_le_accept_connection(int server_fd)
868 {
869         int result;
870         l2cap_le_server_info_t *server_info;
871
872         BT_CHECK_ENABLED_LE(return);
873
874         if (server_fd < 0) {
875                 BT_ERR("Invalid FD");
876                 return BLUETOOTH_ERROR_INVALID_PARAM;
877         }
878
879         BT_INIT_PARAMS();
880         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
881
882         server_info = __get_l2cap_le_server_info_with_id(server_fd);
883         if (!server_info) {
884                 BT_ERR("No server with fd: %d", server_fd);
885                 return BLUETOOTH_ERROR_INVALID_PARAM;
886         }
887
888         g_array_append_vals(in_param1, server_info->pending_addr, BT_ADDRESS_STRING_SIZE);
889
890         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_L2CAP_LE_ACCEPT_CONNECTION,
891                 in_param1, in_param2, in_param3, in_param4, &out_param);
892
893         BT_DBG("result: %x", result);
894         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
895
896         return result;
897 }
898
899 BT_EXPORT_API int bluetooth_l2cap_le_reject_connection(int server_fd)
900 {
901         int result;
902         l2cap_le_server_info_t *server_info;
903
904         BT_CHECK_ENABLED_LE(return);
905
906         if (server_fd < 0) {
907                 BT_ERR("Invalid FD");
908                 return BLUETOOTH_ERROR_INVALID_PARAM;
909         }
910
911         BT_INIT_PARAMS();
912         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
913
914         server_info = __get_l2cap_le_server_info_with_id(server_fd);
915         if (!server_info) {
916                 BT_ERR("No server with fd: %d", server_fd);
917                 return BLUETOOTH_ERROR_INVALID_PARAM;
918         }
919
920         g_array_append_vals(in_param1, server_info->pending_addr, BT_ADDRESS_STRING_SIZE);
921
922         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_L2CAP_LE_REJECT_CONNECTION,
923                 in_param1, in_param2, in_param3, in_param4, &out_param);
924
925         BT_DBG("result: %x", result);
926         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
927
928         return result;
929 }
930
931 BT_EXPORT_API int bluetooth_l2cap_le_get_psm(int id, int *psm)
932 {
933         l2cap_le_server_info_t *server_info;
934
935         BT_CHECK_ENABLED_LE(return);
936
937         if (id < 0) {
938                 BT_ERR("Invalid ID");
939                 return BLUETOOTH_ERROR_INVALID_PARAM;
940         }
941
942         server_info = __get_l2cap_le_server_info_with_id(id);
943         if (!server_info) {
944                 BT_ERR("server_info not found for sock_fd: %d", id);
945                 return BLUETOOTH_ERROR_INVALID_PARAM;
946         }
947
948         *psm = server_info->psm;
949
950         return BLUETOOTH_ERROR_NONE;
951 }