Fix the rfcomm server's callback issue
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-rfcomm-server.c
1 /*
2  * Copyright (c) 2011 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 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
20 #include <gio/gio.h>
21 #include <gio/gunixfdlist.h>
22 #include <sys/socket.h>
23 #endif
24
25 #include "bluetooth-api.h"
26 #include "bt-internal-types.h"
27
28 #include "bt-common.h"
29 #include "bt-request-sender.h"
30 #include "bt-event-handler.h"
31
32 #ifdef TIZEN_FEATURE_BT_DPM
33 #include "bt-dpm.h"
34 #endif
35
36 #define BLUETOOTH_SOCK_CONNECT_INFO_LEN 16
37
38 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
39
40 static GSList *rfcomm_nodes;
41
42 typedef struct {
43         bluetooth_device_address_t addr;
44         int fd;
45         guint watch_id;
46         gboolean disconnected;
47 } rfcomm_conn_t;
48
49 typedef struct {
50         guint object_id;
51         gchar *path;
52         int id;
53         char *uuid;
54         GSList *rfcomm_conns;
55         guint disconnect_idle_id;
56 } rfcomm_info_t;
57
58 static rfcomm_info_t *__find_rfcomm_info_with_id(int id)
59 {
60         GSList *l;
61
62         for (l = rfcomm_nodes; l != NULL; l = l->next) {
63                 rfcomm_info_t *info = l->data;
64
65                 if (info->id == id)
66                         return info;
67         }
68
69         return NULL;
70 }
71
72 static rfcomm_info_t *__find_rfcomm_info_with_fd(int fd)
73 {
74         GSList *l;
75         GSList *ll;
76
77         for (l = rfcomm_nodes; l != NULL; l = l->next) {
78                 rfcomm_info_t *info = l->data;
79
80                 for (ll = info->rfcomm_conns; ll; ll = ll->next) {
81                         rfcomm_conn_t *conn = ll->data;
82
83                         if (conn && conn->fd == fd)
84                                 return info;
85                 }
86         }
87
88         return NULL;
89 }
90
91 static rfcomm_info_t *__find_rfcomm_info_with_path(const gchar *path)
92 {
93         GSList *l;
94
95         for (l = rfcomm_nodes; l != NULL; l = l->next) {
96                 rfcomm_info_t *info = l->data;
97
98                 if (g_ascii_strcasecmp(info->path, path) == 0)
99                         return info;
100         }
101
102         return NULL;
103 }
104
105 static rfcomm_info_t *__find_rfcomm_info_with_uuid(const char *uuid)
106 {
107         GSList *l;
108
109         for (l = rfcomm_nodes; l != NULL; l = l->next) {
110                 rfcomm_info_t *info = l->data;
111
112                 if (g_ascii_strcasecmp(info->uuid, uuid) == 0)
113                         return info;
114         }
115
116         return NULL;
117 }
118
119 static rfcomm_conn_t *__find_rfcomm_conn_with_fd(rfcomm_info_t *info,
120                                                       int fd)
121 {
122         GSList *l;
123         rfcomm_conn_t *conn;
124
125         for (l = info->rfcomm_conns; l; l = l->next) {
126                 conn = l->data;
127
128                 if (conn && conn->fd == fd)
129                         return conn;
130         }
131
132         return NULL;
133 }
134
135 static void __rfcomm_remove_conn(rfcomm_info_t *info, int fd)
136 {
137         rfcomm_conn_t *conn;
138
139         conn = __find_rfcomm_conn_with_fd(info, fd);
140         if (conn == NULL)
141                 return;
142
143         info->rfcomm_conns = g_slist_remove(info->rfcomm_conns, conn);
144
145         if (conn->watch_id > 0)
146                 g_source_remove(conn->watch_id);
147         g_free(conn);
148 }
149
150 gboolean _check_uuid_path(char *path, char *uuid)
151 {
152         rfcomm_info_t *info = NULL;
153         info = __find_rfcomm_info_with_path(path);
154         if (!info)
155                 return FALSE;
156
157         if (g_ascii_strcasecmp(info->uuid, uuid) == 0)
158                 return TRUE;
159
160         return FALSE;
161 }
162
163 static void __connected_cb(rfcomm_info_t *info, rfcomm_conn_t *conn,
164                            bt_event_info_t *event_info)
165 {
166         bluetooth_rfcomm_connection_t conn_info;
167
168         memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t));
169
170         conn_info.device_role = RFCOMM_ROLE_SERVER;
171         g_strlcpy(conn_info.uuid, info->uuid, BLUETOOTH_UUID_STRING_MAX);
172         conn_info.socket_fd = conn->fd;
173         conn_info.device_addr = conn->addr;
174         conn_info.server_id = info->id;
175
176         BT_INFO_C("### Connected [RFCOMM Server]");
177         _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_CONNECTED,
178                         BLUETOOTH_ERROR_NONE, &conn_info,
179                         event_info->cb, event_info->user_data);
180 }
181
182 static void __rfcomm_server_disconnect_conn(rfcomm_conn_t *conn,
183                                             rfcomm_info_t *info)
184 {
185         bluetooth_rfcomm_disconnection_t disconn_info;
186         bt_event_info_t *event_info;
187
188         if (conn == NULL)
189                 return;
190
191         if (conn->disconnected == FALSE)
192                 return;
193
194         if (conn->watch_id > 0) {
195                 g_source_remove(conn->watch_id);
196                 conn->watch_id = 0;
197         }
198
199         event_info = _bt_event_get_cb_data(BT_RFCOMM_SERVER_EVENT);
200         if (event_info == NULL) {
201                 BT_ERR("event_info is NULL");
202                 __rfcomm_remove_conn(info, conn->fd);
203                 return;
204         }
205
206         memset(&disconn_info, 0x00, sizeof(bluetooth_rfcomm_disconnection_t));
207         disconn_info.device_role = RFCOMM_ROLE_SERVER;
208         g_strlcpy(disconn_info.uuid, info->uuid, BLUETOOTH_UUID_STRING_MAX);
209         disconn_info.device_addr = conn->addr;
210
211         BT_INFO("Disconnected FD [%d]", conn->fd);
212         disconn_info.socket_fd = conn->fd;
213
214         _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DISCONNECTED,
215                         BLUETOOTH_ERROR_NONE, &disconn_info,
216                         event_info->cb, event_info->user_data);
217
218         __rfcomm_remove_conn(info, conn->fd);
219 }
220
221 static gboolean __rfcomm_server_disconnect(rfcomm_info_t *info)
222 {
223         BT_INFO_C("### Disconnected [RFCOMM Server]");
224
225         if (g_slist_find(rfcomm_nodes, info) == NULL) {
226                 BT_INFO("rfcomm resource is already freed");
227                 return FALSE;
228         }
229
230         info->disconnect_idle_id = 0;
231
232         g_slist_foreach(info->rfcomm_conns,
233                         (GFunc)__rfcomm_server_disconnect_conn, info);
234
235         BT_DBG("-");
236         return FALSE;
237 }
238
239 static gboolean __is_error_by_disconnect(GError *err)
240 {
241         return !g_strcmp0(err->message, "Connection reset by peer") ||
242                         !g_strcmp0(err->message, "Connection timed out") ||
243                         !g_strcmp0(err->message, "Software caused connection abort");
244 }
245
246 static gboolean __data_received_cb(GIOChannel *chan, GIOCondition cond,
247                                                                 gpointer data)
248 {
249         char *buffer = NULL;
250         gsize len = 0;
251         int result = BLUETOOTH_ERROR_NONE;
252         rfcomm_info_t *info = data;
253         rfcomm_conn_t *conn;
254         bt_event_info_t *event_info;
255         bluetooth_rfcomm_received_data_t data_r;
256         GIOStatus status = G_IO_STATUS_NORMAL;
257         GError *err = NULL;
258         int fd;
259
260         retv_if(info == NULL, FALSE);
261
262         fd = g_io_channel_unix_get_fd(chan);
263         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
264                 BT_ERR_C("RFComm Server disconnected: %d", fd);
265
266                 if (info->disconnect_idle_id > 0) {
267                         BT_INFO("Disconnect idle still not process remove source");
268                         g_source_remove(info->disconnect_idle_id);
269                         info->disconnect_idle_id = 0;
270                 }
271
272                 conn = __find_rfcomm_conn_with_fd(info, fd);
273                 if (conn == NULL) {
274                         BT_ERR("No Connection info found with FD [%d]", fd);
275                         return FALSE;
276                 }
277
278                 if (conn->disconnected == FALSE) {
279                         close(conn->fd);
280                         conn->disconnected = TRUE;
281                 }
282                 __rfcomm_server_disconnect(info);
283                 return FALSE;
284         }
285
286         buffer = g_malloc0(BT_RFCOMM_BUFFER_LEN + 1);
287
288         status =  g_io_channel_read_chars(chan, buffer, BT_RFCOMM_BUFFER_LEN,
289                                                 &len, &err);
290         if (status != G_IO_STATUS_NORMAL) {
291                 BT_ERR("IO Channel read is failed with %d", status);
292
293                 g_free(buffer);
294                 if (!err)
295                         return TRUE;
296
297                 BT_ERR("IO Channel read error [%s]", err->message);
298                 if (status == G_IO_STATUS_ERROR &&
299                     __is_error_by_disconnect(err)) {
300                         BT_ERR("cond : %d", cond);
301                         g_error_free(err);
302
303                         if (info->disconnect_idle_id > 0) {
304                                 BT_INFO("Disconnect idle still not process remove source");
305                                 g_source_remove(info->disconnect_idle_id);
306                                 info->disconnect_idle_id = 0;
307                         }
308
309                         conn = __find_rfcomm_conn_with_fd(info, fd);
310                         if (conn == NULL) {
311                                 BT_ERR("No Connection info found with FD [%d]", fd);
312                                 return FALSE;
313                         }
314
315                         if (conn->disconnected == FALSE) {
316                                 close(conn->fd);
317                                 conn->disconnected = TRUE;
318                         }
319                         __rfcomm_server_disconnect(info);
320                         return FALSE;
321                 }
322                 g_error_free(err);
323                 return TRUE;
324         }
325
326         if (len == 0)
327                 BT_ERR("Length is zero");
328
329         event_info = _bt_event_get_cb_data(BT_RFCOMM_SERVER_EVENT);
330         if (event_info == NULL) {
331                 BT_ERR("event_info is NULL. Unable to invoke the callback");
332                 g_free(buffer);
333                 return TRUE;
334         }
335
336         data_r.socket_fd = fd;
337         data_r.buffer_size = len;
338         data_r.buffer = buffer;
339
340         _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED,
341                         result, &data_r,
342                         event_info->cb, event_info->user_data);
343
344         if (bluetooth_get_battery_monitor_state()) {
345                 int ret = _bt_common_send_rfcomm_rx_details(&data_r);
346                 if (ret != BLUETOOTH_ERROR_NONE)
347                         BT_ERR("RFCOMM received data details not sent to battery monitor frwk");
348         }
349
350         g_free(buffer);
351
352         return TRUE;
353 }
354
355 int new_server_connection(const char *path, int fd, bluetooth_device_address_t *addr)
356 {
357         rfcomm_info_t *info;
358         rfcomm_conn_t *conn;
359         GIOChannel *data_io;
360         bt_event_info_t *event_info;
361
362         BT_INFO("%s %d", path, fd);
363
364         info = __find_rfcomm_info_with_path(path);
365         if (info == NULL) {
366                 BT_ERR("rfcomm info is NULL");
367                 return -1;
368         }
369
370 #ifdef TIZEN_FEATURE_BT_DPM
371         if (_bt_check_dpm(BT_DPM_SPP, NULL) == BT_DPM_RESTRICTED) {
372                 char addr_str[20];
373
374                 BT_ERR("Not allow to use SPP profile");
375
376                 close(fd);
377                 _bt_convert_addr_type_to_string(addr_str, addr->addr);
378                 _bt_disconnect_ext_profile(addr_str, info->path);
379
380                 return -1;
381         }
382 #endif
383
384         conn = g_new0(rfcomm_conn_t, 1);
385         conn->fd = fd;
386         memcpy(&conn->addr, addr, sizeof(bluetooth_device_address_t));
387         info->rfcomm_conns = g_slist_append(info->rfcomm_conns, conn);
388
389         data_io = g_io_channel_unix_new(conn->fd);
390
391         g_io_channel_set_encoding(data_io, NULL, NULL);
392         g_io_channel_set_flags(data_io, G_IO_FLAG_NONBLOCK, NULL);
393
394         conn->watch_id = g_io_add_watch(data_io,
395                            G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
396                            __data_received_cb, info);
397
398         g_io_channel_unref(data_io);
399
400         event_info = _bt_event_get_cb_data(BT_RFCOMM_SERVER_EVENT);
401         if (event_info)
402                 __connected_cb(info, conn, event_info);
403
404         return 0;
405 }
406
407 static rfcomm_info_t *__register_method()
408 {
409         gchar *path;
410         rfcomm_info_t *info;
411         int object_id;
412         int id;
413
414         id = __rfcomm_assign_id();
415         if (id < 0)
416                 return NULL;
417
418         path = g_strdup_printf("/org/socket/server/%d/%d", getpid(), id);
419
420         object_id = _bt_register_new_conn(path, new_server_connection);
421         if (object_id < 0) {
422                 __rfcomm_delete_id(id);
423                 return NULL;
424         }
425         info = g_new0(rfcomm_info_t, 1);
426         info->object_id = (guint)object_id;
427         info->path = path;
428         info->id = id;
429
430         rfcomm_nodes = g_slist_append(rfcomm_nodes, info);
431
432         return info;
433 }
434
435 static rfcomm_info_t *__register_method_2(const char *path, const char *bus_name)
436 {
437         rfcomm_info_t *info;
438         int object_id;
439
440         object_id = _bt_register_new_conn_ex(path, bus_name, new_server_connection);
441         if (object_id < 0)
442                 return NULL;
443
444         info = g_new0(rfcomm_info_t, 1);
445         info->object_id = (guint)object_id;
446         info->path = g_strdup(path);
447         info->id = -1;
448
449         rfcomm_nodes = g_slist_append(rfcomm_nodes, info);
450
451         return info;
452 }
453
454 void free_rfcomm_conn(rfcomm_conn_t *conn, rfcomm_info_t *info)
455 {
456         if (conn->disconnected == FALSE) {
457                 close(conn->fd);
458                 conn->disconnected = TRUE;
459         }
460         __rfcomm_server_disconnect_conn(conn, info);
461 }
462
463 void free_rfcomm_info(rfcomm_info_t *info)
464 {
465         BT_DBG("");
466
467         if (info->disconnect_idle_id > 0) {
468                 BT_INFO("Disconnect idle still not process remove source");
469                 g_source_remove(info->disconnect_idle_id);
470                 info->disconnect_idle_id = 0;
471         }
472
473         __rfcomm_delete_id(info->id);
474         _bt_unregister_gdbus(info->object_id);
475
476         g_slist_foreach(info->rfcomm_conns, (GFunc)free_rfcomm_conn, info);
477
478         g_free(info->path);
479         g_free(info->uuid);
480         g_free(info);
481 }
482
483 void _bt_rfcomm_server_free_all(void)
484 {
485         BT_DBG("Free all the servers");
486
487         g_slist_free_full(rfcomm_nodes, (GDestroyNotify)free_rfcomm_info);
488         rfcomm_nodes = NULL;
489 }
490
491 void _bt_rfcomm_server_disconnect_all(void)
492 {
493         GSList *server;
494         GSList *conn;
495         char addr[20];
496
497         BT_INFO(" ### Disconnect all RFCOMM server connections");
498
499         for (server = rfcomm_nodes; server; ) {
500                 rfcomm_info_t *info = server->data;
501
502                 for (conn = info->rfcomm_conns; conn; conn = conn->next) {
503                         rfcomm_conn_t *conn_info = conn->data;
504
505                         if (conn_info == NULL)
506                                 continue;
507
508                         if (conn_info->watch_id == 0 || conn_info->disconnected)
509                                 continue;
510
511                         close(conn_info->fd);
512                         conn_info->disconnected = TRUE;
513
514                         _bt_convert_addr_type_to_string(addr,
515                                                         conn_info->addr.addr);
516                         _bt_disconnect_ext_profile(addr, info->path);
517                 }
518
519                 server = server->next;
520                 __rfcomm_server_disconnect(info);
521         }
522
523         return;
524 }
525 #else
526
527 #define BT_RFCOMM_SERVER_ID_MAX 254
528
529 typedef struct {
530         char addr[BT_ADDRESS_STRING_SIZE];
531         int sock_fd;
532         int watch_id;
533         int server_id;
534 } rfcomm_remote_client_info_t;
535
536 typedef struct {
537         char uuid[BLUETOOTH_UUID_STRING_MAX];
538         int server_id;
539         int server_fd;
540         int watch_id;
541         int max_pending_conn;
542         gboolean auto_accept;
543         char pending_addr[BT_ADDRESS_STRING_SIZE];
544         GSList *conn_list;
545 } rfcomm_server_info_t;
546
547 static GSList *rfcomm_servers;
548 static gboolean id_used[BT_RFCOMM_SERVER_ID_MAX];
549 int latest_id = 0;
550
551 int __rfcomm_assign_server_id(void)
552 {
553         int index;
554
555         BT_DBG("latest_id: %d", latest_id);
556
557         index = latest_id + 1;
558
559         if (index >= BT_RFCOMM_SERVER_ID_MAX)
560                 index = 0;
561
562         BT_DBG("index: %d", index);
563
564         while (id_used[index] == TRUE) {
565                 if (index == latest_id) {
566                         /* No available ID */
567                         BT_ERR("All request ID is used");
568                         return -1;
569                 }
570
571                 index++;
572
573                 if (index >= BT_RFCOMM_SERVER_ID_MAX)
574                         index = 0;
575         }
576
577         latest_id = index;
578         id_used[index] = TRUE;
579
580         BT_DBG("Assigned Id: %d", latest_id);
581
582         return latest_id;
583 }
584
585 void __rfcomm_delete_server_id(int id)
586 {
587         ret_if(id >= BT_RFCOMM_SERVER_ID_MAX);
588         ret_if(id < 0);
589
590         id_used[id] = FALSE;
591
592         /* Next server will use this ID */
593         latest_id = id - 1;
594 }
595
596 static rfcomm_server_info_t *__get_rfcomm_server_info_with_uuid(const char *uuid)
597 {
598         GSList *l;
599
600         if (!uuid)
601                 return NULL;
602
603         for (l = rfcomm_servers; l != NULL; l = l->next) {
604                 rfcomm_server_info_t *info = l->data;
605
606                 if (!strncasecmp(info->uuid, uuid, strlen(info->uuid)))
607                         return info;
608         }
609
610         return NULL;
611 }
612
613 int _get_rfcomm_server_id(char *uuid, gboolean *auto_accept)
614 {
615         rfcomm_server_info_t *server_info;
616
617         server_info = __get_rfcomm_server_info_with_uuid(uuid);
618         if (!server_info)
619                 return -1;
620
621         *auto_accept = server_info->auto_accept;
622         return server_info->server_id;
623 }
624
625 static rfcomm_server_info_t *__get_rfcomm_server_info_with_id(int server_id)
626 {
627         GSList *l;
628
629         for (l = rfcomm_servers; l != NULL; l = l->next) {
630                 rfcomm_server_info_t *info = l->data;
631                 if (!info)
632                         continue;
633
634                 BT_DBG("info->server_fd: %d, sock_fd:%d", info->server_id, server_id);
635                 if (info->server_id == server_id)
636                         return info;
637         }
638
639         return NULL;
640 }
641
642 void _bt_rfcomm_server_set_pending_conn(int server_id, char *address)
643 {
644         rfcomm_server_info_t *server_info;
645
646
647         if (!address)
648                 return;
649
650         server_info = __get_rfcomm_server_info_with_id(server_id);
651         if (!server_info)
652                 return;
653
654         g_strlcpy(server_info->pending_addr, address, BT_ADDRESS_STRING_SIZE);
655 }
656
657 static rfcomm_remote_client_info_t *__get_rfcomm_rem_client_info_with_fd(int sock_fd)
658 {
659         GSList *l;
660         GSList *l1;
661
662         for (l = rfcomm_servers; l != NULL; l = l->next) {
663                 rfcomm_server_info_t *info = l->data;
664
665                 if (!info)
666                         continue;
667
668                 for (l1 = info->conn_list; l1 != NULL; l1 = l1->next) {
669                         rfcomm_remote_client_info_t *client_info = l1->data;
670                         if (!client_info)
671                                 continue;
672
673                         if (client_info->sock_fd == sock_fd)
674                                 return client_info;
675                 }
676         }
677
678         return NULL;
679 }
680
681 static rfcomm_remote_client_info_t *__get_rfcomm_rem_client_info_with_addr(char *addr)
682 {
683         GSList *l;
684         GSList *l1;
685
686         retv_if(NULL == addr, NULL);
687
688         for (l = rfcomm_servers; l != NULL; l = l->next) {
689                 rfcomm_server_info_t *info = l->data;
690
691                 if (!info)
692                         continue;
693
694                 for (l1 = info->conn_list; l1 != NULL; l1 = l1->next) {
695                         rfcomm_remote_client_info_t *client_info = l1->data;
696                         if (!client_info)
697                                 continue;
698
699                         if (!strncasecmp(client_info->addr, addr, strlen(client_info->addr)))
700                                 return client_info;
701                 }
702         }
703
704         return NULL;
705 }
706
707 static void __remove_remote_client_info(rfcomm_remote_client_info_t *rem_client)
708 {
709         BT_DBG("+");
710
711         if (rem_client == NULL)
712                 return;
713
714         if (0 < rem_client->sock_fd) {
715                 shutdown(rem_client->sock_fd, SHUT_RDWR);
716                 close(rem_client->sock_fd);
717         }
718
719         if (rem_client->watch_id > 0)
720                 g_source_remove(rem_client->watch_id);
721
722         g_free(rem_client);
723
724         BT_DBG("-");
725 }
726
727 static void __handle_rfcomm_client_disconnected(rfcomm_server_info_t *server_info,
728                 rfcomm_remote_client_info_t *rem_client)
729 {
730         bluetooth_rfcomm_disconnection_t disconn_info;
731         bt_event_info_t *event_info;
732
733         BT_DBG("+");
734
735         if (rem_client == NULL || server_info == NULL)
736                 return;
737
738         event_info = _bt_event_get_cb_data(BT_RFCOMM_SERVER_EVENT);
739         if (event_info == NULL)
740                 return;
741
742         memset(&disconn_info, 0x00, sizeof(bluetooth_rfcomm_disconnection_t));
743         disconn_info.device_role = RFCOMM_ROLE_SERVER;
744         g_strlcpy(disconn_info.uuid, server_info->uuid, BLUETOOTH_UUID_STRING_MAX);
745         _bt_convert_addr_string_to_type(disconn_info.device_addr.addr, rem_client->addr);
746         BT_DBG("Disconnected FD [%d]", rem_client->sock_fd);
747         disconn_info.socket_fd = rem_client->sock_fd;
748
749         _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DISCONNECTED,
750                         BLUETOOTH_ERROR_NONE, &disconn_info,
751                         event_info->cb, event_info->user_data);
752 }
753
754 static void __remove_rfcomm_server(rfcomm_server_info_t *info)
755 {
756         rfcomm_remote_client_info_t *client_info;
757
758         BT_DBG("+");
759
760         if (!info)
761                 return;
762
763         rfcomm_servers = g_slist_remove(rfcomm_servers, info);
764         if (info->conn_list) {
765                 do {
766                         client_info = info->conn_list->data;
767                         if (!client_info)
768                                 break;
769
770                         info->conn_list = g_slist_remove(info->conn_list, client_info);
771                         __handle_rfcomm_client_disconnected(info, client_info);
772                         __remove_remote_client_info(client_info);
773                 } while (info->conn_list);
774         }
775
776         if (info->server_fd) {
777                 shutdown(info->server_fd, SHUT_RDWR);
778                 close(info->server_fd);
779         }
780
781         if (info->watch_id)
782                 g_source_remove(info->watch_id);
783
784         __rfcomm_delete_server_id(info->server_id);
785         g_free(info);
786
787         BT_DBG("-");
788 }
789
790 static void __connected_cb(rfcomm_remote_client_info_t *client_info, bt_event_info_t *event_info)
791 {
792         bluetooth_rfcomm_connection_t conn_info;
793         rfcomm_server_info_t *server_info;
794
795         server_info = __get_rfcomm_server_info_with_id(client_info->server_id);
796         ret_if(server_info == NULL);
797
798         memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t));
799         conn_info.device_role = RFCOMM_ROLE_SERVER;
800         g_strlcpy(conn_info.uuid, server_info->uuid, BLUETOOTH_UUID_STRING_MAX);
801         conn_info.socket_fd = client_info->sock_fd;
802         _bt_convert_addr_string_to_type(conn_info.device_addr.addr, client_info->addr);
803         conn_info.server_id = server_info->server_id;
804
805         BT_INFO_C("Connected [RFCOMM Server]");
806         _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_CONNECTED,
807                         BLUETOOTH_ERROR_NONE, &conn_info,
808                         event_info->cb, event_info->user_data);
809 }
810
811 static int __process_cmsg(struct msghdr *msg)
812 {
813         int sock_fd = -1;
814         struct cmsghdr *cmsg_ptr = NULL;
815
816         for (cmsg_ptr = CMSG_FIRSTHDR(msg); cmsg_ptr != NULL;
817                         cmsg_ptr = CMSG_NXTHDR(msg, cmsg_ptr)) {
818
819                 if (cmsg_ptr->cmsg_level != SOL_SOCKET)
820                         continue;
821
822                 if (cmsg_ptr->cmsg_type == SCM_RIGHTS) {
823                         //int *desc = (int *)CMSG_DATA(cmsg_ptr);
824                         int count
825                                 = ((cmsg_ptr->cmsg_len - CMSG_LEN(0)) / sizeof(int));
826
827                         if (count < 0) {
828                                 BT_ERR("ERROR Invalid count of descriptors");
829                                 continue;
830                         }
831
832                         //sock_fd = desc[0];
833                         memcpy(&sock_fd, CMSG_DATA(cmsg_ptr), sizeof(sock_fd));
834                         BT_DBG("Remote client fd: %d", sock_fd);
835                 }
836         }
837
838         return sock_fd;
839 }
840
841 static int __read_incomming_client_connection(
842                 int server_fd, char *buf, unsigned int len, int *client_fd)
843 {
844         int ret;
845         struct msghdr msg;
846         struct iovec iv;
847         struct cmsghdr cmsgbuf[2 * sizeof(struct cmsghdr) + 4];
848         int retryCount = 0;
849
850         retv_if(0 > server_fd, -1);
851         retv_if(NULL == client_fd, -1);
852
853         BT_INFO("server_fd = %d", server_fd);
854
855         memset(&msg, 0, sizeof(msg));
856         memset(&iv, 0, sizeof(iv));
857
858         iv.iov_base = buf;
859         iv.iov_len = len;
860         msg.msg_iov = &iv;
861         msg.msg_iovlen = 1;
862         msg.msg_control = cmsgbuf;
863         msg.msg_controllen = sizeof(cmsgbuf);
864
865         for (retryCount = 0; retryCount < 5; retryCount++) {
866                 ret = recvmsg(server_fd, &msg, 0);
867                 BT_DBG("recvmsg ret = %d", ret);
868                 if (ret < 0 && errno == EINTR)
869                         continue;
870                 else
871                         break;
872         }
873
874         if (ret < 0 && errno == EPIPE) {
875                 /* End of stream, server listining stopped */
876                 BT_ERR("EOS errno: %d", errno);
877                 return 0;
878         }
879
880         if (ret < 0) {
881                 BT_ERR("Ret errno: %d", errno);
882                 return -1;
883         }
884
885         if ((msg.msg_flags & (MSG_CTRUNC | MSG_OOB | MSG_ERRQUEUE)) != 0) {
886                 BT_ERR("MSG Flags errno: %d", errno);
887                 return -1;
888         }
889
890         BT_INFO("Connection received");
891         *client_fd = __process_cmsg(&msg);
892         if (*client_fd < 0)
893                 BT_ERR("Invalid client_fd received");
894
895         return ret;
896 }
897
898 static gboolean __data_received_cb(GIOChannel *chan, GIOCondition cond,
899                                                                 gpointer data)
900 {
901         char *buffer = NULL;
902         gsize len = 0;
903         int result = BLUETOOTH_ERROR_NONE;
904         bt_event_info_t *event_info;
905         bluetooth_rfcomm_received_data_t data_r;
906         GIOStatus status = G_IO_STATUS_NORMAL;
907         GError *err = NULL;
908         rfcomm_remote_client_info_t *client_info = data;
909         rfcomm_server_info_t *server_info;
910
911         retv_if(client_info == NULL, FALSE);
912
913         server_info = __get_rfcomm_server_info_with_id(client_info->server_id);
914
915         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
916                 BT_ERR_C("RFComm Server  disconnected: %d", client_info->sock_fd);
917                 goto fail;
918         }
919
920         buffer = g_malloc0(BT_RFCOMM_BUFFER_LEN + 1);
921         status =  g_io_channel_read_chars(chan, buffer,
922                         BT_RFCOMM_BUFFER_LEN, &len, &err);
923         if (status != G_IO_STATUS_NORMAL) {
924                 BT_ERR("IO Channel read is failed with %d", status);
925                 g_free(buffer);
926                 if (err) {
927                         BT_ERR("IO Channel read error [%s]", err->message);
928                         if (status == G_IO_STATUS_ERROR &&
929                                         !g_strcmp0(err->message, "Connection reset by peer")) {
930                                 BT_ERR("cond : %d", cond);
931                                 g_error_free(err);
932                                 goto fail;
933                         }
934                         g_error_free(err);
935                 }
936                 return TRUE;
937         }
938
939         if (len == 0) {
940                 BT_ERR("Length is zero, remote end hang up");
941                 goto fail;
942         }
943
944         event_info = _bt_event_get_cb_data(BT_RFCOMM_SERVER_EVENT);
945         if (event_info == NULL) {
946                 g_free(buffer);
947                 return TRUE;
948         }
949
950         data_r.socket_fd = client_info->sock_fd;
951         data_r.buffer_size = len;
952         data_r.buffer = buffer;
953
954         _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED,
955                         result, &data_r,
956                         event_info->cb, event_info->user_data);
957
958         g_free(buffer);
959
960         return TRUE;
961
962 fail:
963         BT_ERR("Failure occured, remove client connection");
964         server_info->conn_list = g_slist_remove(
965                         server_info->conn_list, client_info);
966         __handle_rfcomm_client_disconnected(server_info, client_info);
967         __remove_remote_client_info(client_info);
968         return FALSE;
969 }
970
971 static gboolean __new_connection_request_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
972 {
973         int len;
974         int size;
975         int channel;
976         int status;
977         int client_fd;
978         char buf[BLUETOOTH_SOCK_CONNECT_INFO_LEN];
979         unsigned char addr[BT_ADDRESS_LENGTH_MAX];
980
981         bt_event_info_t *event_info;
982         GIOChannel *io;
983         rfcomm_remote_client_info_t *rem_client;
984         rfcomm_server_info_t *server_info = data;
985
986         if (!server_info) {
987                 BT_ERR("Server info is invalid");
988                 return FALSE;
989         }
990
991         if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
992                 BT_INFO("RFCOMM Server with fd:%d is closed with cond:0x%X",
993                                 server_info->server_fd, cond);
994                 goto err;
995         }
996
997         BT_INFO("Server fd: %d", server_info->server_fd);
998         len = __read_incomming_client_connection(
999                         server_info->server_fd, buf, BLUETOOTH_SOCK_CONNECT_INFO_LEN, &client_fd);
1000         BT_DBG("Socket Read len: %d", len);
1001         if (len == 0) {
1002                 BT_ERR("Listen stopped");
1003                 goto err;
1004         } else if (len != BLUETOOTH_SOCK_CONNECT_INFO_LEN) {
1005                 BT_ERR("Read length is not same as socket info length");
1006                 goto err;
1007         }
1008
1009         len = 0;
1010         /* Read size of data */
1011         size = buf[len] | (buf[len + 1] << 8);
1012         len += 2;
1013
1014         /* Read bluetooth address */
1015         memcpy(addr, buf + len, BT_ADDRESS_LENGTH_MAX);
1016         len += BT_ADDRESS_LENGTH_MAX;
1017
1018         /* Read channel */
1019         channel = buf[len] | (buf[len + 1] << 8) |
1020                 (buf[len + 2] << 16) | (buf[len + 3] << 24);
1021         len += 4;
1022
1023         /* Read status */
1024         status = buf[len] | (buf[len + 1] << 8) |
1025                 (buf[len + 2] << 16) | (buf[len + 3] << 24);
1026         len += 4;
1027
1028         BT_DBG("size: %d, channel: %d, status: %d", size, channel, status);
1029
1030         rem_client = g_malloc0(sizeof(rfcomm_remote_client_info_t));
1031         rem_client->sock_fd = client_fd;
1032         rem_client->server_id = server_info->server_id;
1033         _bt_convert_addr_type_to_string(rem_client->addr, addr);
1034
1035         BT_INFO("New client [%s] connection with socket_fd: %d, server_id: %d",
1036                         rem_client->addr, rem_client->sock_fd, rem_client->server_id);
1037
1038         io = g_io_channel_unix_new(rem_client->sock_fd);
1039         g_io_channel_set_encoding(io, NULL, NULL);
1040         g_io_channel_set_flags(io, G_IO_FLAG_NONBLOCK, NULL);
1041         rem_client->watch_id = g_io_add_watch(io,
1042                         G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
1043                         __data_received_cb, rem_client);
1044         g_io_channel_unref(io);
1045
1046         server_info->conn_list = g_slist_append(server_info->conn_list, rem_client);
1047         event_info = _bt_event_get_cb_data(BT_RFCOMM_SERVER_EVENT);
1048         if (event_info)
1049                 __connected_cb(rem_client, event_info);
1050
1051         return TRUE;
1052
1053 err:
1054         /* Error occurred, Remove RFCOMM server*/
1055         __remove_rfcomm_server(server_info);
1056         return FALSE;
1057 }
1058
1059 static int __rfcomm_listen(rfcomm_server_info_t *server_info, bool accept)
1060 {
1061         int result;
1062         GUnixFDList *out_fd_list = NULL;
1063         GIOChannel *server_io;
1064
1065         retv_if(server_info == NULL, BLUETOOTH_ERROR_INTERNAL);
1066
1067         BT_INIT_PARAMS();
1068         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1069
1070         if (accept == false) {
1071                 g_array_append_vals(in_param1, server_info->uuid, BLUETOOTH_UUID_STRING_MAX);
1072                 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_RFCOMM_LISTEN,
1073                                 in_param1, in_param2, in_param3, in_param4, NULL, &out_param, &out_fd_list);
1074         } else {
1075                 g_array_append_vals(in_param1, server_info->uuid, BLUETOOTH_UUID_STRING_MAX);
1076                 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_RFCOMM_LISTEN_AND_ACCEPT,
1077                                 in_param1, in_param2, in_param3, in_param4, NULL, &out_param, &out_fd_list);
1078         }
1079
1080         BT_DBG("result: %x", result);
1081         if (result != BLUETOOTH_ERROR_NONE) {
1082                 BT_ERR("Fail to send request");
1083                 return result;
1084         } else if (NULL == out_fd_list) {
1085                 BT_ERR("out_fd_list is NULL");
1086                 return BLUETOOTH_ERROR_INTERNAL;
1087         } else {
1088                 int *fd_list_array;
1089                 int len = 0;
1090
1091                 if (!out_fd_list)
1092                         return BLUETOOTH_ERROR_INTERNAL;
1093
1094                 fd_list_array = g_unix_fd_list_steal_fds(out_fd_list, &len);
1095                 BT_INFO("Num fds in fd_list is : %d, fd_list[0]: %d", len, fd_list_array[0]);
1096                 server_info->server_fd = fd_list_array[0];
1097                 BT_INFO("Socket fd: %d", server_info->server_fd);
1098
1099                 g_free(fd_list_array);
1100                 g_object_unref(out_fd_list);
1101         }
1102
1103         server_io = g_io_channel_unix_new(server_info->server_fd);
1104         g_io_channel_set_encoding(server_io, NULL, NULL);
1105         g_io_channel_set_flags(server_io, G_IO_FLAG_NONBLOCK, NULL);
1106         server_info->watch_id = g_io_add_watch(server_io,
1107                         G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
1108                         __new_connection_request_cb, server_info);
1109         g_io_channel_unref(server_io);
1110
1111         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1112
1113         return BLUETOOTH_ERROR_NONE;
1114 }
1115 #endif
1116
1117 BT_EXPORT_API int bluetooth_rfcomm_create_socket(const char *uuid)
1118 {
1119 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1120         rfcomm_info_t *info;
1121 #else
1122         rfcomm_server_info_t *server_info;
1123 #endif
1124
1125         BT_CHECK_ENABLED(return);
1126         BT_CHECK_PARAMETER(uuid, return);
1127         BT_INFO("UUID Provided %s", uuid);
1128
1129         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_RFCOMM_CREATE_SOCKET)
1130                 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
1131                 BT_ERR("Don't have a privilege to use this API");
1132                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1133         }
1134
1135 #ifdef TIZEN_FEATURE_BT_DPM
1136         if (_bt_check_dpm(BT_DPM_SPP, NULL) == BT_DPM_RESTRICTED) {
1137                 BT_ERR("Not allow to use SPP profile");
1138                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
1139         }
1140 #endif
1141
1142 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1143         BT_INFO("<<<<<<<<< RFCOMM Create socket from app >>>>>>>>>");
1144         info = __register_method();
1145         if (info == NULL)
1146                 return -1;
1147
1148         info->uuid = g_strdup(uuid);
1149         info->disconnect_idle_id = 0;
1150         return info->id;
1151 #else
1152         BT_INFO("<<<<<<<<< RFCOMM Create socket from app >>>>>>>>>");
1153
1154         server_info = __get_rfcomm_server_info_with_uuid(uuid);
1155         if (!server_info) {
1156                 server_info = g_malloc0(sizeof(rfcomm_server_info_t));
1157                 g_strlcpy(server_info->uuid, uuid, BLUETOOTH_UUID_STRING_MAX);
1158                 server_info->server_id = __rfcomm_assign_server_id();
1159                 server_info->server_fd = -1;
1160                 server_info->watch_id = -1;
1161                 server_info->auto_accept = FALSE;
1162                 rfcomm_servers = g_slist_append(rfcomm_servers, server_info);
1163         }
1164         return server_info->server_id;
1165 #endif
1166 }
1167
1168 BT_EXPORT_API int bluetooth_rfcomm_create_socket_ex(const char *uuid, const char *bus_name, const char *path)
1169 {
1170 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1171         rfcomm_info_t *info;
1172
1173         BT_CHECK_ENABLED(return);
1174         BT_CHECK_PARAMETER(path, return);
1175         BT_INFO("PATH Provided %s", path);
1176
1177         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_RFCOMM_CREATE_SOCKET_EX)
1178                 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
1179                 BT_ERR("Don't have a privilege to use this API");
1180                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1181         }
1182
1183 #ifdef TIZEN_FEATURE_BT_DPM
1184         if (_bt_check_dpm(BT_DPM_SPP, NULL) == BT_DPM_RESTRICTED) {
1185                 BT_ERR("Not allow to use SPP profile");
1186                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
1187         }
1188 #endif
1189
1190         BT_INFO("<<<<<<<<< RFCOMM Create socket from app >>>>>>>>>");
1191         info = __register_method_2(path, bus_name);
1192         if (info == NULL)
1193                 return BLUETOOTH_ERROR_IN_PROGRESS;
1194         info->uuid = g_strdup(uuid);
1195         info->disconnect_idle_id = 0;
1196
1197         return BLUETOOTH_ERROR_NONE;
1198 #else
1199         return BLUETOOTH_ERROR_NOT_SUPPORT;
1200 #endif
1201 }
1202
1203
1204 BT_EXPORT_API int bluetooth_rfcomm_remove_socket(int id)
1205 {
1206 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1207         rfcomm_info_t *info;
1208 #else
1209         rfcomm_server_info_t *server_info;
1210 #endif
1211
1212         BT_CHECK_ENABLED(return);
1213
1214         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_RFCOMM_REMOVE_SOCKET)
1215                 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
1216                 BT_ERR("Don't have a privilege to use this API");
1217                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1218         }
1219
1220         if (id < 0) {
1221                 BT_ERR("Invalid ID");
1222                 return BLUETOOTH_ERROR_INVALID_PARAM;
1223         }
1224
1225 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1226         BT_INFO("RFCOMM Remove socket request from app, ID [%d]", id);
1227
1228         info = __find_rfcomm_info_with_id(id);
1229         if (info == NULL)
1230                 return BLUETOOTH_ERROR_INVALID_PARAM;
1231
1232         _bt_unregister_osp_server_in_agent(BT_RFCOMM_SERVER, info->uuid);
1233         _bt_unregister_profile(info->path);
1234
1235         rfcomm_nodes = g_slist_remove(rfcomm_nodes, info);
1236         free_rfcomm_info(info);
1237
1238         return BLUETOOTH_ERROR_NONE;
1239 #else
1240         BT_INFO("<<<<<<<<< RFCOMM Remove socket request from app, fd=[%d] >>>>>>>>>>>", socket_fd);
1241
1242         server_info = __get_rfcomm_server_info_with_id(id);
1243         if (!server_info) {
1244                 BT_ERR("server_info not found for socket_fd: %d", id);
1245                 return BLUETOOTH_ERROR_INVALID_PARAM;
1246         }
1247
1248         __remove_rfcomm_server(server_info);
1249
1250         return BLUETOOTH_ERROR_NONE;
1251 #endif
1252 }
1253
1254 BT_EXPORT_API int bluetooth_rfcomm_remove_socket_ex(const char *uuid)
1255 {
1256 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1257         rfcomm_info_t *info;
1258
1259         BT_CHECK_ENABLED(return);
1260
1261         if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_RFCOMM_REMOVE_SOCKET)
1262                 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
1263                 BT_ERR("Don't have a privilege to use this API");
1264                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1265         }
1266
1267         BT_INFO("RFCOMM Remove socket request from app, uuid=[%s]", uuid);
1268
1269         info = __find_rfcomm_info_with_uuid(uuid);
1270         if (info == NULL)
1271                 return BLUETOOTH_ERROR_INVALID_PARAM;
1272
1273         _bt_unregister_osp_server_in_agent(BT_RFCOMM_SERVER, info->uuid);
1274         _bt_unregister_profile(info->path);
1275
1276         rfcomm_nodes = g_slist_remove(rfcomm_nodes, info);
1277         free_rfcomm_info(info);
1278
1279         return BLUETOOTH_ERROR_NONE;
1280 #else
1281         return BLUETOOTH_ERROR_NOT_SUPPORT;
1282 #endif
1283 }
1284
1285 BT_EXPORT_API int bluetooth_rfcomm_server_disconnect(int socket_fd)
1286 {
1287 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1288         rfcomm_info_t *info;
1289         rfcomm_conn_t *conn;
1290
1291         char address[20];
1292
1293         BT_INFO(" ### Disconnect RFCOMM server");
1294         if (socket_fd < 0) {
1295                 BT_ERR("Invalid FD");
1296                 return BLUETOOTH_ERROR_INVALID_PARAM;
1297         }
1298
1299         info = __find_rfcomm_info_with_fd(socket_fd);
1300         if (info == NULL)
1301                 return BLUETOOTH_ERROR_INVALID_PARAM;
1302
1303         conn = __find_rfcomm_conn_with_fd(info, socket_fd);
1304         if (conn == NULL)
1305                 return BLUETOOTH_ERROR_INVALID_PARAM;
1306
1307         if (conn->watch_id == 0 || conn->disconnected)
1308                 return BLUETOOTH_ERROR_NOT_CONNECTED;
1309
1310         close(conn->fd);
1311         conn->disconnected = TRUE;
1312
1313         _bt_convert_addr_type_to_string(address, conn->addr.addr);
1314
1315         BT_DBG("Address %s", address);
1316         _bt_disconnect_ext_profile(address, info->path);
1317
1318         if (info->disconnect_idle_id == 0)
1319                 info->disconnect_idle_id = g_idle_add(
1320                                 (GSourceFunc)__rfcomm_server_disconnect, info);
1321         BT_DBG("-");
1322
1323         return BLUETOOTH_ERROR_NONE;
1324 #else
1325         rfcomm_remote_client_info_t *client_info;
1326
1327         BT_CHECK_ENABLED(return);
1328
1329         BT_INFO(">>>>>>>>RFCOMM server disconnect request from APP>>>>>>>>>");
1330         if (socket_fd < 0) {
1331                 BT_ERR("Invalid FD");
1332                 return BLUETOOTH_ERROR_INVALID_PARAM;
1333         }
1334
1335         client_info = __get_rfcomm_rem_client_info_with_fd(socket_fd);
1336         if (!client_info) {
1337                 BT_ERR("client_info not found for socket_fd: %d", socket_fd);
1338                 return BLUETOOTH_ERROR_NOT_CONNECTED;
1339         }
1340
1341         if (client_info->sock_fd) {
1342                 shutdown(client_info->sock_fd, SHUT_RDWR);
1343                 close(client_info->sock_fd);
1344                 client_info->sock_fd = -1;
1345         }
1346
1347         return BLUETOOTH_ERROR_NONE;
1348 #endif
1349 }
1350
1351 BT_EXPORT_API gboolean bluetooth_rfcomm_is_server_uuid_available(const char *uuid)
1352 {
1353         int result;
1354         gboolean available = TRUE;
1355         char uuid_str[BLUETOOTH_UUID_STRING_MAX];
1356
1357         retv_if(uuid == NULL, FALSE);
1358         retv_if(bluetooth_check_adapter() ==
1359                                 BLUETOOTH_ADAPTER_DISABLED, FALSE);
1360
1361         BT_INIT_PARAMS();
1362         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1363
1364         g_strlcpy(uuid_str, uuid, sizeof(uuid_str));
1365         g_array_append_vals(in_param1, uuid_str, BLUETOOTH_UUID_STRING_MAX);
1366
1367         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_IS_UUID_AVAILABLE,
1368                 in_param1, in_param2, in_param3, in_param4, &out_param);
1369
1370         BT_DBG("result: %x", result);
1371
1372         if (result == BLUETOOTH_ERROR_NONE)
1373                 available = g_array_index(out_param, gboolean, 0);
1374
1375         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1376
1377         BT_DBG("available: %d", available);
1378
1379         return available;
1380 }
1381
1382 BT_EXPORT_API int bluetooth_rfcomm_server_is_connected(const bluetooth_device_address_t *device_address, gboolean *connected)
1383 {
1384 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1385         GSList *l;
1386         GSList *ll;
1387         rfcomm_info_t *info;
1388         rfcomm_conn_t *conn;
1389 #else
1390         char input_addr[BT_ADDRESS_STRING_SIZE] = { 0 };
1391         rfcomm_remote_client_info_t *info;
1392 #endif
1393
1394         BT_CHECK_PARAMETER(device_address, return);
1395         BT_CHECK_PARAMETER(connected, return);
1396
1397         *connected = FALSE;
1398
1399 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1400         for (l = rfcomm_nodes; l; l = l->next) {
1401                 info = l->data;
1402
1403                 if (info == NULL || info->rfcomm_conns == NULL)
1404                         continue;
1405
1406                 for (ll = info->rfcomm_conns; ll; ll = ll->next) {
1407                         conn = ll->data;
1408
1409                         if (memcmp(device_address, &conn->addr,
1410                                         sizeof(bluetooth_device_address_t)))
1411                                 continue;
1412
1413                         *connected = TRUE;
1414                         return BLUETOOTH_ERROR_NONE;
1415                 }
1416         }
1417
1418         return BLUETOOTH_ERROR_NONE;
1419 #else
1420         _bt_convert_addr_type_to_string(input_addr, (unsigned char *)device_address->addr);
1421         info = __get_rfcomm_rem_client_info_with_addr(input_addr);
1422         if (info)
1423                 *connected = TRUE;
1424
1425         return BLUETOOTH_ERROR_NONE;
1426 #endif
1427 }
1428
1429 BT_EXPORT_API int bluetooth_rfcomm_listen_and_accept(int id, int max_pending_connection)
1430 {
1431 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1432         rfcomm_info_t *info;
1433 #else
1434         rfcomm_server_info_t *server_info;
1435 #endif
1436
1437         BT_CHECK_ENABLED(return);
1438         if (id < 0) {
1439                 BT_ERR("Invalid ID");
1440                 return BLUETOOTH_ERROR_INVALID_PARAM;
1441         }
1442
1443 #ifdef TIZEN_FEATURE_BT_DPM
1444         if (_bt_check_dpm(BT_DPM_SPP, NULL) == BT_DPM_RESTRICTED) {
1445                 BT_ERR("Not allow to use SPP profile");
1446                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
1447         }
1448 #endif
1449
1450 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1451         BT_INFO("RFCOMM Listen & accept from app");
1452
1453         info = __find_rfcomm_info_with_id(id);
1454         if (info == NULL)
1455                 return BLUETOOTH_ERROR_INVALID_PARAM;
1456
1457         bt_register_profile_info_t profile_info;
1458         int result;
1459
1460         profile_info.authentication = TRUE;
1461         profile_info.authorization = TRUE;
1462         profile_info.obj_path = info->path;
1463         profile_info.role = NULL;
1464         profile_info.service = info->uuid;
1465         profile_info.uuid = info->uuid;
1466
1467         BT_INFO("uuid %s", profile_info.uuid);
1468         result = _bt_register_profile(&profile_info, TRUE);
1469
1470         return result;
1471 #else
1472         BT_INFO("<<<<<<<<< RFCOMM Listen & accept from app >>>>>>>>>>>");
1473
1474         server_info = __get_rfcomm_server_info_with_id(id);
1475         if (!server_info) {
1476                 BT_ERR("server_info not found for id: %d", id);
1477                 return BLUETOOTH_ERROR_INVALID_PARAM;
1478         }
1479
1480         if (server_info->server_fd >= 0) {
1481                 BT_ERR("server already listining");
1482                 return BLUETOOTH_ERROR_DEVICE_BUSY;
1483         }
1484
1485         server_info->max_pending_conn = max_pending_connection;
1486         server_info->auto_accept = TRUE;
1487
1488         return __rfcomm_listen(server_info, true);
1489 #endif
1490 }
1491
1492 BT_EXPORT_API int bluetooth_rfcomm_listen_and_accept_ex(const char *uuid,
1493                                         int max_pending_connection,
1494                                         const char *bus_name, const char *path)
1495 {
1496 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1497         rfcomm_info_t *info;
1498
1499         BT_CHECK_ENABLED(return);
1500
1501 #ifdef TIZEN_FEATURE_BT_DPM
1502         if (_bt_check_dpm(BT_DPM_SPP, NULL) == BT_DPM_RESTRICTED) {
1503                 BT_ERR("Not allow to use SPP profile");
1504                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
1505         }
1506 #endif
1507
1508         BT_INFO("RFCOMM Listen & accept from app");
1509
1510         info = __find_rfcomm_info_with_uuid(uuid);
1511         if (info == NULL)
1512                 return BLUETOOTH_ERROR_INVALID_PARAM;
1513
1514         bt_register_profile_info_t profile_info;
1515         int result;
1516
1517         profile_info.authentication = TRUE;
1518         profile_info.authorization = TRUE;
1519         profile_info.obj_path = info->path;
1520         profile_info.role = NULL;
1521         profile_info.service = info->uuid;
1522         profile_info.uuid = info->uuid;
1523
1524         BT_INFO("uuid %s", profile_info.uuid);
1525         result = _bt_register_profile_ex(&profile_info, TRUE, bus_name, path);
1526
1527         return result;
1528 #else
1529         return BLUETOOTH_ERROR_NOT_SUPPORT;
1530 #endif
1531 }
1532
1533 BT_EXPORT_API int bluetooth_rfcomm_listen(int id, int max_pending_connection)
1534 {
1535 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1536         rfcomm_info_t *info;
1537 #else
1538         rfcomm_server_info_t *server_info;
1539 #endif
1540
1541         BT_CHECK_ENABLED(return);
1542         if (id < 0) {
1543                 BT_ERR("Invalid ID");
1544                 return BLUETOOTH_ERROR_INVALID_PARAM;
1545         }
1546
1547 #ifdef TIZEN_FEATURE_BT_DPM
1548         if (_bt_check_dpm(BT_DPM_SPP, NULL) == BT_DPM_RESTRICTED) {
1549                 BT_ERR("Not allow to use SPP profile");
1550                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
1551         }
1552 #endif
1553
1554 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1555         BT_INFO("RFCOMM Listen");
1556
1557         info = __find_rfcomm_info_with_id(id);
1558         if (info == NULL)
1559                 return BLUETOOTH_ERROR_INVALID_PARAM;
1560
1561         bt_register_profile_info_t profile_info;
1562         int result;
1563
1564         profile_info.authentication = TRUE;
1565         profile_info.authorization = TRUE;
1566         profile_info.obj_path = info->path;
1567         profile_info.role = NULL;
1568         profile_info.service = info->uuid;
1569         profile_info.uuid = info->uuid;
1570         BT_INFO("UUID %s", info->uuid);
1571         BT_INFO("PATH %s", info->path);
1572         result = _bt_register_profile_platform(&profile_info, TRUE);
1573         if (result != BLUETOOTH_ERROR_NONE)
1574                 return result;
1575
1576         return _bt_register_osp_server_in_agent(BT_RFCOMM_SERVER, info->uuid,
1577                                                 info->path, id);
1578
1579 #else
1580         BT_INFO("<<<<<<<<< RFCOMM Listen >>>>>>>>>>>");
1581
1582         server_info = __get_rfcomm_server_info_with_id(id);
1583         if (!server_info) {
1584                 BT_ERR("server_info not found for id: %d", id);
1585                 return BLUETOOTH_ERROR_INVALID_PARAM;
1586         }
1587
1588         if (server_info->server_fd >= 0) {
1589                 BT_ERR("server already listining");
1590                 return BLUETOOTH_ERROR_DEVICE_BUSY;
1591         }
1592
1593         server_info->max_pending_conn = max_pending_connection;
1594         server_info->auto_accept = FALSE;
1595         return __rfcomm_listen(server_info, false);
1596 #endif
1597 }
1598
1599 BT_EXPORT_API int bluetooth_rfcomm_accept_connection(int server_fd)
1600 {
1601         int result;
1602 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1603 #else
1604         rfcomm_server_info_t *server_info;
1605 #endif
1606
1607         BT_CHECK_ENABLED(return);
1608
1609 #ifdef TIZEN_FEATURE_BT_DPM
1610         if (_bt_check_dpm(BT_DPM_SPP, NULL) == BT_DPM_RESTRICTED) {
1611                 BT_ERR("Not allow to use SPP profile");
1612                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
1613         }
1614 #endif
1615
1616         if (server_fd < 0) {
1617                 BT_ERR("Invalid FD");
1618                 return BLUETOOTH_ERROR_INVALID_PARAM;
1619         }
1620
1621         BT_INIT_PARAMS();
1622         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1623
1624 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1625         g_array_append_vals(in_param1, &server_fd, sizeof(int));
1626 #else
1627         server_info = __get_rfcomm_server_info_with_id(server_fd);
1628         if (!server_info) {
1629                 BT_ERR("No server with fd: %d", server_fd);
1630                 return BLUETOOTH_ERROR_INVALID_PARAM;
1631         }
1632
1633         g_array_append_vals(in_param1, server_info->pending_addr, BT_ADDRESS_STRING_SIZE);
1634 #endif
1635
1636         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_ACCEPT_CONNECTION,
1637                 in_param1, in_param2, in_param3, in_param4, &out_param);
1638
1639         BT_DBG("result: %x", result);
1640
1641         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1642
1643         return result;
1644 }
1645
1646 BT_EXPORT_API int bluetooth_rfcomm_reject_connection(int server_fd)
1647 {
1648         int result;
1649 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1650 #else
1651         rfcomm_server_info_t *server_info;
1652 #endif
1653
1654         BT_CHECK_ENABLED(return);
1655
1656         if (server_fd < 0) {
1657                 BT_ERR("Invalid FD");
1658                 return BLUETOOTH_ERROR_INVALID_PARAM;
1659         }
1660
1661         BT_INFO("+");
1662
1663         BT_INIT_PARAMS();
1664         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1665
1666 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1667         g_array_append_vals(in_param1, &server_fd, sizeof(int));
1668 #else
1669         server_info = __get_rfcomm_server_info_with_id(server_fd);
1670         if (!server_info) {
1671                 BT_ERR("No server with fd: %d", server_fd);
1672                 return BLUETOOTH_ERROR_INVALID_PARAM;
1673         }
1674
1675         g_array_append_vals(in_param1, server_info->pending_addr, BT_ADDRESS_STRING_SIZE);
1676 #endif
1677         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_REJECT_CONNECTION,
1678                 in_param1, in_param2, in_param3, in_param4, &out_param);
1679
1680         BT_DBG("result: %x", result);
1681
1682         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1683
1684         return result;
1685 }
1686