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