LE CoC: Add FRWK APIs for L2CAP_LE type socket
[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 #ifdef TIZEN_BLUEDROID_PORTING
412         char len_buf[2] = {0, 0};
413 #endif
414         char *buffer = NULL;
415         gsize len = 0;
416         int result = BLUETOOTH_ERROR_NONE;
417         bt_event_info_t *event_info;
418         bluetooth_l2cap_le_received_data_t data_r;
419         GIOStatus status = G_IO_STATUS_NORMAL;
420         GError *err = NULL;
421         l2cap_le_remote_client_info_t *client_info = data;
422         l2cap_le_server_info_t *server_info;
423
424         retv_if(client_info == NULL, FALSE);
425
426         server_info = __get_l2cap_le_server_info_with_id(client_info->server_id);
427
428         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
429                 BT_ERR_C("l2cap_le Server disconnected: %d", client_info->sock_fd);
430                 goto fail;
431         }
432
433 #ifdef TIZEN_BLUEDROID_PORTING
434         /* Read buffer length from socket */
435         status = g_io_channel_read_chars(chan, len_buf, sizeof(len_buf), &len, &err);
436         if (status != G_IO_STATUS_NORMAL) {
437                 BT_ERR("IO Channel read is failed with %d", status);
438                 if (err) {
439                         BT_ERR("IO Channel read error [%s]", err->message);
440                         if (status == G_IO_STATUS_ERROR &&
441                                         !g_strcmp0(err->message,
442                                                 "Connection reset by peer"))
443                                 BT_ERR("cond : %d", cond);
444
445                         g_error_free(err);
446                 }
447                 goto fail;
448         }
449
450         if (len == 0) {
451                 BT_ERR("Length is zero, remote end hang up");
452                 goto fail;
453         }
454
455         len = (unsigned char)len_buf[0] + ((unsigned char)len_buf[1] << 8);
456         BT_INFO("Recieved buffer len: %d", len);
457
458         /* Read len bytes in buffer from socket */
459         buffer = g_malloc0(len + 1);
460         status = g_io_channel_read_chars(chan, buffer, len, &len, &err);
461 #else
462         buffer = g_malloc0(BT_L2CAP_LE_BUFFER_LEN + 1);
463         status = g_io_channel_read_chars(chan, buffer,
464                         BT_L2CAP_LE_BUFFER_LEN, &len, &err);
465 #endif
466
467         if (status != G_IO_STATUS_NORMAL) {
468                 BT_ERR("IO Channel read is failed with %d", status);
469                 g_free(buffer);
470                 if (err) {
471                         BT_ERR("IO Channel read error [%s]", err->message);
472                         if (status == G_IO_STATUS_ERROR &&
473                                         !g_strcmp0(err->message, "Connection reset by peer")) {
474                                 BT_ERR("cond : %d", cond);
475                                 g_error_free(err);
476                                 goto fail;
477                         }
478                         g_error_free(err);
479                 }
480
481                 return TRUE;
482         }
483
484         if (len == 0) {
485                 BT_ERR("Length is zero, remote end hang up");
486                 g_free(buffer);
487                 goto fail;
488         }
489
490         event_info = _bt_event_get_cb_data(BT_L2CAP_LE_SERVER_EVENT);
491         if (event_info == NULL) {
492                 g_free(buffer);
493                 return TRUE;
494         }
495
496         data_r.socket_fd = client_info->sock_fd;
497         data_r.buffer_size = len;
498         data_r.buffer = buffer;
499
500         _bt_common_event_cb(BLUETOOTH_EVENT_L2CAP_LE_DATA_RECEIVED,
501                         result, &data_r, event_info->cb, event_info->user_data);
502
503         g_free(buffer);
504         return TRUE;
505 fail:
506         BT_ERR("Failure occured, remove client connection");
507         server_info->conn_list = g_slist_remove(
508                         server_info->conn_list, client_info);
509         __handle_l2cap_le_client_disconnected(server_info, client_info);
510         client_info->watch_id = -1;
511         __remove_remote_client_info(client_info);
512         return FALSE;
513 }
514
515 static gboolean __new_connection_request_cb(GIOChannel *chan,
516                                                 GIOCondition cond, gpointer data)
517 {
518         int len;
519         int size;
520         int channel;
521         int status;
522         int client_fd;
523         char buf[BLUETOOTH_SOCK_CONNECT_INFO_LEN];
524         unsigned char addr[BT_ADDRESS_LENGTH_MAX];
525
526         bt_event_info_t *event_info;
527         GIOChannel *io;
528         l2cap_le_remote_client_info_t *rem_client;
529         l2cap_le_server_info_t *server_info = data;
530
531         if (!server_info) {
532                 BT_ERR("Server info is invalid");
533                 return FALSE;
534         }
535
536         if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
537                 BT_INFO("l2cap_le Server with fd:%d is closed with cond:0x%X",
538                                 server_info->server_fd, cond);
539                 goto err;
540         }
541
542         BT_INFO("Server fd: %d", server_info->server_fd);
543         len = __sock_read( server_info->server_fd, buf,
544                                         BLUETOOTH_SOCK_CONNECT_INFO_LEN, &client_fd);
545         BT_DBG("Socket Read len: %d", len);
546         if (len == 0) {
547                 BT_ERR("Listen stopped");
548                 goto err;
549         } else if (len != BLUETOOTH_SOCK_CONNECT_INFO_LEN) {
550                 BT_ERR("Read length is not same as socket info length");
551                 goto err;
552         }
553
554         len = 0;
555         /* Read size of data */
556         size = buf[len] | (buf[len + 1] << 8);
557         len += 2;
558
559         /* Read bluetooth address */
560         memcpy(addr, buf + len, BT_ADDRESS_LENGTH_MAX);
561         len += BT_ADDRESS_LENGTH_MAX;
562
563         /* Read channel */
564         channel = buf[len] | (buf[len + 1] << 8) |
565                 (buf[len + 2] << 16) | (buf[len + 3] << 24);
566         len += 4;
567
568         /* Read status */
569         status = buf[len] | (buf[len + 1] << 8) |
570                 (buf[len + 2] << 16) | (buf[len + 3] << 24);
571         len += 4;
572
573         BT_DBG("size: %d, channel: %d, status: %d", size, channel, status);
574
575         rem_client = g_malloc0(sizeof(l2cap_le_remote_client_info_t));
576         rem_client->sock_fd = client_fd;
577         rem_client->server_id = server_info->server_id;
578         _bt_convert_addr_type_to_string(rem_client->addr, addr);
579
580         BT_INFO("New client [%s] connection with socket_fd: %d, server_id: %d",
581                         rem_client->addr, rem_client->sock_fd, rem_client->server_id);
582
583         io = g_io_channel_unix_new(rem_client->sock_fd);
584         g_io_channel_set_encoding(io, NULL, NULL);
585         g_io_channel_set_flags(io, G_IO_FLAG_NONBLOCK, NULL);
586         rem_client->watch_id = g_io_add_watch(io,
587                         G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
588                         __data_received_cb, rem_client);
589         g_io_channel_unref(io);
590
591         server_info->conn_list = g_slist_append(server_info->conn_list, rem_client);
592         event_info = _bt_event_get_cb_data(BT_L2CAP_LE_SERVER_EVENT);
593         if (event_info)
594                 __connected_cb(rem_client, event_info);
595
596         return TRUE;
597
598 err:
599         /* Error occurred, Remove l2cap_le server*/
600         BT_ERR("some error has occured, remove server");
601         __remove_l2cap_le_server(server_info);
602         return FALSE;
603 }
604
605 static int __getInt(char *buf, int len)
606 {
607         int val = 0;
608
609         if (len != SOCK_INT_LEN)
610                 return -1;
611
612         val = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
613         return val;
614 }
615
616 static int __sock_wait_for_psm(int sock_fd)
617 {
618         int readlen = -1;
619         char buf[SOCK_INT_LEN];
620
621         readlen = __sock_read(sock_fd, buf, SOCK_INT_LEN, NULL);
622         return __getInt(buf, readlen);
623 }
624
625 static int __l2cap_le_listen(l2cap_le_server_info_t *server_info, bool accept)
626 {
627         int result;
628         GUnixFDList *out_fd_list = NULL;
629         GIOChannel *server_io;
630         int psm;
631
632         retv_if(server_info == NULL, BLUETOOTH_ERROR_INTERNAL);
633
634         BT_INIT_PARAMS();
635         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
636
637         psm = server_info->psm;
638         g_array_append_vals(in_param1, &psm, sizeof(int));
639
640         if (accept == false)
641                 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_L2CAP_LE_LISTEN,
642                                 in_param1, in_param2, in_param3, in_param4, NULL, &out_param, &out_fd_list);
643         else
644                 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_L2CAP_LE_LISTEN_AND_ACCEPT,
645                                 in_param1, in_param2, in_param3, in_param4, NULL, &out_param, &out_fd_list);
646
647         BT_INFO("result: %x", result);
648         if (result != BLUETOOTH_ERROR_NONE) {
649                 BT_ERR("Fail to send request");
650                 return result;
651         } else if (NULL == out_fd_list) {
652                 BT_ERR("out_fd_list is NULL");
653                 return BLUETOOTH_ERROR_INTERNAL;
654         } else {
655                 int *fd_list_array;
656                 int len = 0;
657
658                 if (!out_fd_list)
659                         return BLUETOOTH_ERROR_INTERNAL;
660
661                 fd_list_array = g_unix_fd_list_steal_fds(out_fd_list, &len);
662                 BT_INFO("Num fds in fd_list is : %d, fd_list[0]: %d", len, fd_list_array[0]);
663                 server_info->server_fd = fd_list_array[0];
664                 BT_INFO("Socket fd: %d", server_info->server_fd);
665
666                 g_free(fd_list_array);
667                 g_object_unref(out_fd_list);
668         }
669
670         psm = __sock_wait_for_psm(server_info->server_fd);
671         if (psm < 0) {
672                 BT_ERR("Reading PSM failed, psm %d", psm);
673                 return BLUETOOTH_ERROR_INTERNAL;
674         }
675         server_info->psm = psm;
676
677         BT_INFO("socket fd: %d psm %d", server_info->server_fd, server_info->psm);
678         server_io = g_io_channel_unix_new(server_info->server_fd);
679         g_io_channel_set_encoding(server_io, NULL, NULL);
680         g_io_channel_set_flags(server_io, G_IO_FLAG_NONBLOCK, NULL);
681         server_info->watch_id = g_io_add_watch(server_io,
682                         G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
683                         __new_connection_request_cb, server_info);
684         g_io_channel_unref(server_io);
685
686         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
687
688         return BLUETOOTH_ERROR_NONE;
689 }
690
691 BT_EXPORT_API int bluetooth_l2cap_le_create_socket(int psm)
692 {
693         l2cap_le_server_info_t *server_info;
694
695         BT_CHECK_ENABLED_LE(return);
696
697         if (_bt_check_privilege_le(BT_CHECK_PRIVILEGE, BT_L2CAP_LE_CREATE_SOCKET)
698                 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
699                 BT_ERR("Don't have a privilege to use this API");
700                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
701         }
702
703         BT_INFO("<<<<<<<<< L2CAP_LE Create socket from app, psm %d >>>>>>>>>", psm);
704
705         server_info = __get_l2cap_le_server_info_from_psm(psm);
706         if (!server_info) {
707                 server_info = g_malloc0(sizeof(l2cap_le_server_info_t));
708                 server_info->psm = psm;
709                 server_info->server_id = __l2cap_le_assign_server_id();
710                 server_info->server_fd = -1;
711                 server_info->watch_id = -1;
712                 server_info->auto_accept = FALSE;
713                 l2cap_le_servers = g_slist_append(l2cap_le_servers, server_info);
714         }
715
716         return server_info->server_id;
717 }
718
719 BT_EXPORT_API int bluetooth_l2cap_le_remove_socket(int id)
720 {
721         l2cap_le_server_info_t *server_info;
722
723         BT_CHECK_ENABLED_LE(return);
724
725         if (_bt_check_privilege_le(BT_CHECK_PRIVILEGE, BT_L2CAP_LE_REMOVE_SOCKET)
726                 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
727                 BT_ERR("Don't have a privilege to use this API");
728                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
729         }
730
731         if (id < 0) {
732                 BT_ERR("Invalid ID");
733                 return BLUETOOTH_ERROR_INVALID_PARAM;
734         }
735
736         BT_INFO("<<<<<< L2CAP_LE Remove socket request from app, fd=[%d] >>>>>>", id);
737
738         server_info = __get_l2cap_le_server_info_with_id(id);
739         if (!server_info) {
740                 BT_ERR("server_info not found for socket_fd: %d", id);
741                 return BLUETOOTH_ERROR_INVALID_PARAM;
742         }
743
744         __remove_l2cap_le_server(server_info);
745
746         return BLUETOOTH_ERROR_NONE;
747 }
748
749 BT_EXPORT_API int bluetooth_l2cap_le_server_disconnect(int socket_fd)
750 {
751         l2cap_le_remote_client_info_t *client_info;
752
753         BT_CHECK_ENABLED_LE(return);
754
755         BT_INFO("<<<<<< L2CAP_LE server disconnect request from APP >>>>>>");
756         if (socket_fd < 0) {
757                 BT_ERR("Invalid FD");
758                 return BLUETOOTH_ERROR_INVALID_PARAM;
759         }
760
761         client_info = __get_l2cap_le_rem_client_info_with_fd(socket_fd);
762         if (!client_info) {
763                 BT_ERR("client_info not found for socket_fd: %d", socket_fd);
764                 return BLUETOOTH_ERROR_NOT_CONNECTED;
765         }
766
767         if (0 < client_info->sock_fd) {
768                 l2cap_le_server_info_t *server_info;
769
770                 /* Remove IO watch for client socket */
771                 if (0 < client_info->watch_id)
772                         g_source_remove(client_info->watch_id);
773                 client_info->watch_id = -1;
774
775                 /* close client socket and send L2CAP_LE disconneted event */
776                 shutdown(client_info->sock_fd, SHUT_RDWR);
777                 close(client_info->sock_fd);
778                 server_info = __get_l2cap_le_server_info_with_id(
779                                 client_info->server_id);
780                 __handle_l2cap_le_client_disconnected(
781                                 server_info, client_info);
782                 client_info->sock_fd = -1;
783
784                 /* Remove remote client info from l2cap_le server context */
785                 server_info->conn_list = g_slist_remove(
786                                 server_info->conn_list, client_info);
787
788                 /* Release remote client info */
789                 __remove_remote_client_info(client_info);
790         }
791
792         return BLUETOOTH_ERROR_NONE;
793 }
794
795 BT_EXPORT_API gboolean bluetooth_l2cap_le_is_server_psm_available(int psm)
796 {
797         int result;
798         gboolean available = TRUE;
799         int t_psm;
800
801         retv_if(bluetooth_check_adapter_le() ==
802                                 BLUETOOTH_ADAPTER_DISABLED, FALSE);
803
804         BT_INIT_PARAMS();
805         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
806
807         t_psm = psm;
808         g_array_append_vals(in_param1, &t_psm, sizeof(int));
809
810         /* TODO: Need to implement BT_L2CAP_LE_IS_PSM_AVAILABLE in BT-Service  */
811         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_L2CAP_LE_IS_PSM_AVAILABLE,
812                 in_param1, in_param2, in_param3, in_param4, &out_param);
813
814         BT_DBG("result: %x", result);
815
816         if (result == BLUETOOTH_ERROR_NONE)
817                 available = g_array_index(out_param, gboolean, 0);
818
819         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
820
821         BT_DBG("available: %d", available);
822
823         return available;
824 }
825
826 BT_EXPORT_API int bluetooth_l2cap_le_server_is_connected(
827                                         const bluetooth_device_address_t *device_address, gboolean *connected)
828 {
829         char input_addr[BT_ADDRESS_STRING_SIZE] = { 0 };
830         l2cap_le_remote_client_info_t *info;
831
832         BT_CHECK_PARAMETER(device_address, return);
833         BT_CHECK_PARAMETER(connected, return);
834
835         *connected = FALSE;
836
837         _bt_convert_addr_type_to_string(input_addr,
838                                         (unsigned char *)device_address->addr);
839         info = __get_l2cap_le_rem_client_info_with_addr(input_addr);
840         if (info)
841                 *connected = TRUE;
842
843         return BLUETOOTH_ERROR_NONE;
844 }
845
846 BT_EXPORT_API int bluetooth_l2cap_le_listen_and_accept(int id, int max_pending_connection)
847 {
848         l2cap_le_server_info_t *server_info;
849
850         BT_CHECK_ENABLED_LE(return);
851         if (id < 0) {
852                 BT_ERR("Invalid ID");
853                 return BLUETOOTH_ERROR_INVALID_PARAM;
854         }
855
856         BT_INFO("<<<<<<<<< L2CAP_LE Listen & accept from app >>>>>>>>>>>");
857
858         server_info = __get_l2cap_le_server_info_with_id(id);
859         if (!server_info) {
860                 BT_ERR("server_info not found for id: %d", id);
861                 return BLUETOOTH_ERROR_INVALID_PARAM;
862         }
863
864         if (server_info->server_fd >= 0) {
865                 BT_ERR("server already listening");
866                 return BLUETOOTH_ERROR_DEVICE_BUSY;
867         }
868
869         server_info->max_pending_conn = max_pending_connection;
870         server_info->auto_accept = TRUE;
871
872         return __l2cap_le_listen(server_info, true);
873 }
874
875 BT_EXPORT_API int bluetooth_l2cap_le_listen(int id, int max_pending_connection)
876 {
877         l2cap_le_server_info_t *server_info;
878
879         BT_CHECK_ENABLED_LE(return);
880         if (id < 0) {
881                 BT_ERR("Invalid ID");
882                 return BLUETOOTH_ERROR_INVALID_PARAM;
883         }
884
885         BT_INFO("<<<<<<<<< L2CAP_LE Listen >>>>>>>>>>>");
886
887         server_info = __get_l2cap_le_server_info_with_id(id);
888         if (!server_info) {
889                 BT_ERR("server_info not found for id: %d", id);
890                 return BLUETOOTH_ERROR_INVALID_PARAM;
891         }
892
893         if (server_info->server_fd >= 0) {
894                 BT_ERR("server already listening");
895                 return BLUETOOTH_ERROR_DEVICE_BUSY;
896         }
897
898         server_info->max_pending_conn = max_pending_connection;
899         server_info->auto_accept = FALSE;
900
901         return __l2cap_le_listen(server_info, false);
902 }
903
904
905 BT_EXPORT_API int bluetooth_l2cap_le_accept_connection(int server_fd)
906 {
907         int result;
908         l2cap_le_server_info_t *server_info;
909
910         BT_CHECK_ENABLED_LE(return);
911
912         if (server_fd < 0) {
913                 BT_ERR("Invalid FD");
914                 return BLUETOOTH_ERROR_INVALID_PARAM;
915         }
916
917         BT_INIT_PARAMS();
918         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
919
920         server_info = __get_l2cap_le_server_info_with_id(server_fd);
921         if (!server_info) {
922                 BT_ERR("No server with fd: %d", server_fd);
923                 return BLUETOOTH_ERROR_INVALID_PARAM;
924         }
925
926         g_array_append_vals(in_param1, server_info->pending_addr, BT_ADDRESS_STRING_SIZE);
927
928         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_L2CAP_LE_ACCEPT_CONNECTION,
929                 in_param1, in_param2, in_param3, in_param4, &out_param);
930
931         BT_DBG("result: %x", result);
932         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
933
934         return result;
935 }
936
937 BT_EXPORT_API int bluetooth_l2cap_le_reject_connection(int server_fd)
938 {
939         int result;
940         l2cap_le_server_info_t *server_info;
941
942         BT_CHECK_ENABLED_LE(return);
943
944         if (server_fd < 0) {
945                 BT_ERR("Invalid FD");
946                 return BLUETOOTH_ERROR_INVALID_PARAM;
947         }
948
949         BT_INIT_PARAMS();
950         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
951
952         server_info = __get_l2cap_le_server_info_with_id(server_fd);
953         if (!server_info) {
954                 BT_ERR("No server with fd: %d", server_fd);
955                 return BLUETOOTH_ERROR_INVALID_PARAM;
956         }
957
958         g_array_append_vals(in_param1, server_info->pending_addr, BT_ADDRESS_STRING_SIZE);
959
960         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_L2CAP_LE_REJECT_CONNECTION,
961                 in_param1, in_param2, in_param3, in_param4, &out_param);
962
963         BT_DBG("result: %x", result);
964         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
965
966         return result;
967 }
968
969 BT_EXPORT_API int bluetooth_l2cap_le_get_psm(int id, int *psm)
970 {
971         l2cap_le_server_info_t *server_info;
972
973         BT_CHECK_ENABLED_LE(return);
974
975         if (id < 0) {
976                 BT_ERR("Invalid ID");
977                 return BLUETOOTH_ERROR_INVALID_PARAM;
978         }
979
980         server_info = __get_l2cap_le_server_info_with_id(id);
981         if (!server_info) {
982                 BT_ERR("server_info not found for sock_fd: %d", id);
983                 return BLUETOOTH_ERROR_INVALID_PARAM;
984         }
985
986         *psm = server_info->psm;
987
988         return BLUETOOTH_ERROR_NONE;
989 }