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