Merge "Fix the coding style errors (bt-httpproxy)" into tizen
[platform/core/connectivity/bluetooth-frwk.git] / bt-httpproxy / bt-httpproxy.c
1 /*
2  * Copyright (c) 2015 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 <dlog.h>
19 #include <gio/gio.h>
20
21 #include <stdio.h>
22
23 #include "bt-httpproxy.h"
24 #include "bluetooth-api.h"
25
26 #include <libsoup/soup.h>
27
28 #ifdef HPS_FEATURE
29
30 #undef LOG_TAG
31 #define LOG_TAG "BLUETOOTH_HPS"
32
33 #define BT_INFO(fmt, arg...) SLOGI(fmt, ##arg)
34 #define BT_ERR(fmt, arg...) SLOGE(fmt, ##arg)
35 #define BT_DBG(fmt, arg...) SLOGD(fmt, ##arg)
36
37 char *hps_obj_path = NULL;
38 char *http_uri_obj_path = NULL;
39 char *http_hdr_obj_path = NULL;
40 char *http_entity_obj_path = NULL;
41 char *http_cp_obj_path = NULL;
42 char *http_status_obj_path = NULL;
43 char *http_status_desc_obj_path = NULL;
44 char *http_security_obj_path = NULL;
45
46 static GMainLoop *main_loop;
47 static int property_sub_id = -1;
48 static int adapter_sub_id = -1;
49 static http_request_state req_state;
50
51 #ifdef  HPS_GATT_DB
52 struct hps_notify_read_info {
53         gchar *char_path;
54         guint  read_status;
55         guint  offset_status;
56         int  https_status;
57 };
58
59 struct hps_char_info {
60         gchar *char_path;
61         gchar *char_value;
62         int value_length;
63 };
64
65 static GSList *hps_notify_read_list = NULL;
66 static GSList *hps_char_list = NULL;
67 #endif
68
69 static GDBusConnection *conn;
70 static GDBusConnection *g_conn;
71 static guint g_owner_id = 0;
72 GDBusNodeInfo *hps_node_info = NULL;
73
74 char *g_uri = NULL;
75 char *g_header = NULL;
76 char *g_entity = NULL;
77
78 static SoupSession *hps_soup_session = NULL;
79 static SoupMessage *hps_soup_msg = NULL;
80
81
82 static const gchar hps_introspection_xml[] =
83 "<node name='/'>"
84 "       <interface name='org.projectx.httpproxy_service'>"
85 "               <method name='enable'>"
86 "                       <arg type='y' name='status' direction='out'/>"
87 "               </method>"
88 "               <method name='disable'>"
89 "                       <arg type='y' name='status' direction='out'/>"
90 "               </method>"
91 "       </interface>"
92 "</node>";
93
94 #ifdef  HPS_GATT_DB
95 static void _bt_hps_set_char_value(const char *obj_path, const char* value, int value_length);
96
97 static void _hps_convert_address_to_hex(bluetooth_device_address_t *addr_hex, const char *addr_str)
98 {
99         int i = 0;
100         unsigned int addr[BLUETOOTH_ADDRESS_LENGTH] = { 0, };
101
102         if (addr_str == NULL || addr_str[0] == '\0')
103                 return;
104
105         i = sscanf(addr_str, "%X:%X:%X:%X:%X:%X", &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]);
106         if (i != BLUETOOTH_ADDRESS_LENGTH) {
107                 BT_ERR("Invalid format string - [%s]", addr_str);
108         }
109
110         for (i = 0; i < BLUETOOTH_ADDRESS_LENGTH; i++) {
111                 addr_hex->addr[i] = (unsigned char)addr[i];
112         }
113 }
114
115 static void _bt_hps_send_status_notification(unsigned short http_status,
116                         unsigned char data_status,
117                         bluetooth_device_address_t *unicast_address)
118 {
119         char status[3] = {0x00};
120         int ret = BLUETOOTH_ERROR_NONE;
121
122         BT_DBG("");
123
124         status[0] = http_status & 0xFF;
125         status[1] = (http_status >> 8) & 0xFF;
126         status[2] = data_status;
127         BT_DBG("Status %d %04x", http_status, http_status);
128
129         /* Store the status value */
130         _bt_hps_set_char_value(http_status_obj_path, status, 3);
131
132         /* Send unicast notification */
133         ret = bluetooth_gatt_server_set_notification(http_status_obj_path, unicast_address);
134         if (ret != BLUETOOTH_ERROR_NONE) {
135                 BT_ERR("_bt_hps_send_status_notification failed");
136                 return;
137         }
138         ret = bluetooth_gatt_update_characteristic(http_status_obj_path, status, 3);
139         if (ret != BLUETOOTH_ERROR_NONE) {
140                 BT_ERR("_bt_hps_send_status_notification failed");
141                 return;
142         }
143 }
144 #endif
145
146 static void _bt_httpproxy_method(GDBusConnection *connection,
147                 const gchar *sender,
148                 const gchar *object_path,
149                 const gchar *interface_name,
150                 const gchar *method_name,
151                 GVariant *parameters,
152                 GDBusMethodInvocation *invocation,
153                 gpointer user_data)
154 {
155         int status = 0;
156
157         BT_DBG("Method[%s] Object Path[%s] Interface Name[%s]",
158                         method_name, object_path, interface_name);
159
160         if (g_strcmp0(method_name, "enable") == 0) {
161                 g_dbus_method_invocation_return_value(invocation, g_variant_new("(y)", status));
162         } else if (g_strcmp0(method_name, "disable") == 0) {
163                 _bt_hps_exit();
164                 g_dbus_method_invocation_return_value(invocation, g_variant_new("(y)", status));
165         }
166
167         return;
168 }
169
170 static const GDBusInterfaceVTable hps_method_table = {
171         _bt_httpproxy_method,
172         NULL,
173         NULL,
174 };
175
176 static void _bt_hps_on_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
177 {
178         guint object_id;
179         GError *error = NULL;
180
181         BT_DBG("");
182
183         g_conn = connection;
184
185         object_id = g_dbus_connection_register_object(connection, BT_HPS_OBJECT_PATH,
186                                                 hps_node_info->interfaces[0],
187                                                 &hps_method_table,
188                                                 NULL, NULL, &error);
189         if (object_id == 0) {
190                 BT_ERR("Failed to register method table: %s", error->message);
191                 g_error_free(error);
192                 g_dbus_node_info_unref(hps_node_info);
193         }
194
195         return;
196 }
197
198 static void _bt_hps_on_name_acquired(GDBusConnection *connection,
199                                         const gchar     *name,
200                                         gpointer user_data)
201 {
202         BT_DBG("");
203         return;
204 }
205
206 static void _bt_hps_on_name_lost(GDBusConnection *connection,
207                                 const gchar     *name,
208                                 gpointer user_data)
209 {
210         BT_DBG("");
211         g_object_unref(g_conn);
212         g_conn = NULL;
213         g_dbus_node_info_unref(hps_node_info);
214         g_bus_unown_name(g_owner_id);
215
216         return;
217 }
218
219 int _bt_hps_register_interface(void)
220 {
221         GError *error = NULL;
222         guint owner_id;
223
224         BT_DBG("");
225
226         hps_node_info = g_dbus_node_info_new_for_xml(hps_introspection_xml, &error);
227         if (!hps_node_info) {
228                 BT_ERR("Failed to install: %s", error->message);
229                 return BLUETOOTH_ERROR_INTERNAL;
230         }
231
232         owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
233                                 BT_HPS_SERVICE_NAME,
234                                 G_BUS_NAME_OWNER_FLAGS_NONE,
235                                 _bt_hps_on_bus_acquired, _bt_hps_on_name_acquired, _bt_hps_on_name_lost,
236                                 NULL, NULL);
237         g_owner_id = owner_id;
238         BT_DBG("owner_id is [%d]\n", owner_id);
239
240         return BLUETOOTH_ERROR_NONE;
241 }
242
243 void _bt_hps_unregister_interface(void)
244 {
245         BT_DBG("");
246
247         g_object_unref(g_conn);
248         g_conn = NULL;
249         g_dbus_node_info_unref(hps_node_info);
250         g_bus_unown_name(g_owner_id);
251
252         return;
253 }
254
255 #ifdef  HPS_GATT_DB
256 static struct hps_char_info *hps_get_char_value(const char *path)
257 {
258         GSList *tmp = NULL;
259
260         for (tmp = hps_char_list; tmp != NULL; tmp = tmp->next) {
261                 if (tmp->data) {
262                         struct hps_char_info *char_info = tmp->data;
263                         if (!g_strcmp0(char_info->char_path, path))
264                                 return char_info;
265                 }
266         }
267         return NULL;
268 }
269
270 static int char_info_cmp(gconstpointer a1, gconstpointer a2)
271 {
272         const struct hps_char_info *attrib1 = a1;
273         const struct hps_char_info *attrib2 = a2;
274
275         return g_strcmp0(attrib1->char_path, attrib2->char_path);
276 }
277
278 static int notify_info_cmp(gconstpointer a1, gconstpointer a2)
279 {
280         const struct hps_notify_read_info *attrib1 = a1;
281         const struct hps_notify_read_info *attrib2 = a2;
282
283         return g_strcmp0(attrib1->char_path, attrib2->char_path);
284 }
285
286 static void _bt_hps_set_char_value(const char *obj_path, const char* value, int value_length)
287 {
288         GSList *tmp = NULL;
289         if (!value)
290                 return;
291
292         for (tmp = hps_char_list; tmp != NULL; tmp = tmp->next) {
293                 if (tmp->data) {
294                         struct hps_char_info *char_info = tmp->data;
295                         if (!g_strcmp0(char_info->char_path, obj_path)) {
296                                 char_info->char_value = g_try_realloc(char_info->char_value, value_length);
297                                 if (char_info->char_value) {
298                                         memcpy(char_info->char_value, value, value_length);
299                                         char_info->value_length = value_length;
300                                         hps_char_list = g_slist_insert_sorted(hps_char_list,
301                                                                         char_info, char_info_cmp);
302                                 }
303                                 return;
304                         }
305                 }
306         }
307         return;
308 }
309
310 static void _bt_hps_set_notify_read_status(const char *obj_path,
311                         guint offset_status, guint read_status, int https_status)
312 {
313         struct hps_notify_read_info *notify_read_info = NULL;
314         GSList *tmp = NULL;
315
316         for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
317                 if (tmp->data) {
318                         notify_read_info = tmp->data;
319                         if (!g_strcmp0(notify_read_info->char_path, obj_path)) {
320                                 notify_read_info->read_status = read_status;
321                                 notify_read_info->offset_status = offset_status;
322                                 notify_read_info->https_status = https_status;
323                                 hps_notify_read_list = g_slist_insert_sorted(hps_notify_read_list,
324                                                                 notify_read_info, notify_info_cmp);
325                                 return;
326                         }
327                 }
328         }
329
330         if (!hps_notify_read_list) {
331                 /* Store Notification information */
332                 notify_read_info = g_new0(struct hps_notify_read_info, 1);
333                 if (notify_read_info) {
334                         notify_read_info->char_path = g_strdup(obj_path);
335                         notify_read_info->read_status = read_status;
336                         notify_read_info->offset_status = offset_status;
337                         notify_read_info->https_status = https_status;
338                         hps_notify_read_list = g_slist_append(hps_notify_read_list, notify_read_info);
339                 }
340                 return;
341         } else {
342                 /* Store Notification information */
343                 notify_read_info = g_new0(struct hps_notify_read_info, 1);
344                 if (notify_read_info) {
345                         notify_read_info->char_path = g_strdup(obj_path);
346                         notify_read_info->read_status = read_status;
347                         notify_read_info->offset_status = offset_status;
348                         notify_read_info->https_status = https_status;
349                         hps_notify_read_list = g_slist_append(hps_notify_read_list, notify_read_info);
350                 }
351                 return;
352         }
353 }
354
355 static struct hps_notify_read_info *_bt_hps_get_notify_read_status(const char *obj_path)
356 {
357         GSList *tmp = NULL;
358
359         for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
360                 if (tmp->data) {
361                         struct hps_notify_read_info *notify_read_info = tmp->data;
362                         if (!g_strcmp0(notify_read_info->char_path, obj_path))
363                                 return notify_read_info;
364                 }
365         }
366
367         return NULL;
368 }
369
370 static void delete_all_characterisitc(void)
371 {
372         GSList *tmp = NULL;
373         for (tmp = hps_char_list; tmp != NULL; tmp = tmp->next) {
374                 if (tmp->data) {
375                         struct hps_char_info *char_info = tmp->data;
376                         if (char_info->char_path)
377                                 g_free(char_info->char_path);
378                         if (char_info->char_value)
379                                 g_free(char_info->char_value);
380                         hps_char_list = g_slist_delete_link(hps_char_list, tmp->data);
381                 }
382         }
383         g_slist_free(hps_char_list);
384         hps_char_list = NULL;
385 }
386
387 static void delete_all_notify_read_status(void)
388 {
389         GSList *tmp = NULL;
390         for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
391                 if (tmp->data) {
392                         struct hps_notify_read_info *notify_read_info = tmp->data;
393                         if (notify_read_info->char_path)
394                                 g_free(notify_read_info->char_path);
395                         hps_notify_read_list = g_slist_delete_link(hps_notify_read_list, tmp->data);
396                 }
397         }
398         g_slist_free(hps_notify_read_list);
399         hps_notify_read_list = NULL;
400 }
401
402 static void delete_notify_read_status(const char *obj_path)
403 {
404         GSList *tmp = NULL;
405         for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
406                 if (tmp->data) {
407                         struct hps_notify_read_info *notify_read_info = tmp->data;
408                         if (!g_strcmp0(notify_read_info->char_path, obj_path)) {
409                                 if (notify_read_info->char_path)
410                                         g_free(notify_read_info->char_path);
411                                 hps_notify_read_list = g_slist_delete_link(hps_notify_read_list, tmp->data);
412                                 return;
413                         }
414                 }
415         }
416 }
417 #endif
418
419 int _bt_hps_uri_write_cb(char *uri, int len)
420 {
421         if ((len < 1) || (len > MAX_URI_LENGTH)) {
422                 BT_ERR("Wrong URI length %d", len);
423                 return BLUETOOTH_ERROR_INTERNAL;
424         }
425
426         /* g_uri will be used commonly for all HTTP methods whereever applicable */
427         if (g_uri)
428                 g_free(g_uri);
429         g_uri = g_strndup(uri, len);
430 #ifdef  HPS_GATT_DB
431         _bt_hps_set_char_value(http_uri_obj_path, g_uri, len);
432 #endif
433         return BLUETOOTH_ERROR_NONE;
434 }
435
436 int _bt_hps_http_header_write_cb(char *header, int len)
437 {
438         if ((len < 1) || (len > MAX_HEADER_LENGTH)) {
439                 BT_ERR("Wrong Header length %d", len);
440                 return BLUETOOTH_ERROR_INTERNAL;
441         }
442
443         /* g_header will be used commonly for all HTTP methods where ever applicable
444            general-header, request-header, entity-header
445         */
446         if (g_header)
447                 g_free(g_header);
448         g_header = g_strndup(header, len);
449 #ifdef  HPS_GATT_DB
450         _bt_hps_set_char_value(http_hdr_obj_path, g_header, len);
451 #endif
452
453         return BLUETOOTH_ERROR_NONE;
454 }
455
456 int _bt_hps_entity_body_write_cb(char *entity, int len)
457 {
458         if ((len < 1) || (len > MAX_ENTITY_LENGTH)) {
459                 BT_ERR("Wrong Entity length %d", len);
460                 return BLUETOOTH_ERROR_INTERNAL;
461         }
462
463         /* g_entity will be used commonly for all HTTP methods whereever applicable */
464         if (g_entity)
465                 g_free(g_entity);
466         g_entity = g_strndup(entity, len);
467 #ifdef  HPS_GATT_DB
468         _bt_hps_set_char_value(http_entity_obj_path, g_entity, len);
469 #endif
470
471         return BLUETOOTH_ERROR_NONE;
472 }
473
474 #ifdef  HPS_GATT_DB
475 int _bt_hps_read_cb(const char *obj_path, char **value, int *len)
476 {
477         struct hps_char_info *info = NULL;
478         struct hps_notify_read_info *notify_read_info = NULL;
479         guint data_status = -1;
480         guint offset = 0;
481         gboolean is_header = FALSE;
482
483         if (!obj_path) {
484                 BT_ERR("Wrong Obj path");
485                 return FALSE;
486         }
487
488         if (!g_strcmp0(http_hdr_obj_path, obj_path))
489                 is_header = TRUE;
490
491         info = hps_get_char_value(obj_path);
492         if (info) {
493
494                 if (info->char_value == NULL || info->value_length == 0)
495                         return data_status;
496
497                 notify_read_info = _bt_hps_get_notify_read_status(obj_path);
498                 if (notify_read_info && notify_read_info->read_status != DS_BODY_RECEIVED &&
499                                 notify_read_info->read_status != DS_HEADER_RECEIVED) {
500                         offset = notify_read_info->offset_status;
501                         if ((info->value_length - offset) > 0 &&
502                                 (info->value_length - offset) > MAX_ENTITY_LENGTH)  {
503                                 if (is_header)
504                                         data_status = DS_HEADER_TRUNCATED;
505                                 else
506                                         data_status = DS_BODY_TRUNCATED;
507                                 _bt_hps_set_notify_read_status(obj_path, offset + MAX_ENTITY_LENGTH,
508                                                                 data_status, notify_read_info->https_status);
509                                 *value = g_strdup(&info->char_value[offset]);
510                                 *len = info->value_length;
511                         } else if ((info->value_length - offset) > 0 &&
512                                 (info->value_length - offset) <= MAX_ENTITY_LENGTH) {
513                                 if (is_header)
514                                         data_status = DS_HEADER_RECEIVED;
515                                 else
516                                         data_status = DS_BODY_RECEIVED;
517                                 _bt_hps_set_notify_read_status(obj_path, offset, data_status, notify_read_info->https_status);
518                                 *value = g_strdup(&info->char_value[offset]);
519                                 *len = info->value_length;
520                         }
521                 } else if (notify_read_info && (notify_read_info->read_status == DS_BODY_RECEIVED ||
522                                                 notify_read_info->read_status == DS_HEADER_RECEIVED)) {
523                                 if (is_header)
524                                         data_status = DS_HEADER_RECEIVED;
525                                 else
526                                         data_status = DS_BODY_RECEIVED;
527                                 delete_notify_read_status(obj_path);
528                                 *value = g_strdup(&info->char_value[offset]);
529                                 *len = info->value_length;
530                 }
531         }
532
533         return data_status;
534 }
535 #endif
536
537 void _bt_hps_head_response_cb(SoupSession *session,
538                         SoupMessage *msg, gpointer user_data)
539 {
540         unsigned short http_status = 0x00;
541 #ifndef HPS_GATT_DB
542         unsigned char status[3] = {0x00};
543 #else
544         const char *device_address = user_data;
545         bluetooth_device_address_t addr_hex = { {0,} };
546         unsigned char data_status = DS_NONE;
547         _hps_convert_address_to_hex(&addr_hex, device_address);
548 #endif
549
550         if (hps_soup_session != session) {
551                 BT_ERR("Wrong Session");
552                 return;
553         }
554
555         if (msg == NULL) {
556                 BT_ERR("Wrong Message");
557                 return;
558         }
559         hps_soup_msg = NULL;
560
561         req_state = HTTP_REQ_STATE_EXECUTED;
562
563         http_status = msg->status_code;
564
565         // Process Header in Response Body
566         if (msg->response_headers) {
567
568                 const char *content = NULL;
569                 const char *length = NULL;
570                 guint hdr_len = 0;
571
572                 length = soup_message_headers_get_one(msg->request_headers,
573                                                                 "Content-Length");
574                 // Check "Content-MD5" is the right name to get header content
575                 content = soup_message_headers_get_one(msg->response_headers,
576                                                                 "Content-MD5");
577                 if (content == NULL || length == NULL) {
578                         BT_ERR("Wrong Response Header");
579                         _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
580                         return;
581                 }
582
583                 hdr_len = soup_message_headers_get_content_length(msg->response_headers);
584
585                 // Write Data to Header Characteristic
586 #ifdef  HPS_GATT_DB
587                 _bt_hps_set_char_value(http_hdr_obj_path, content, hdr_len);
588 #else
589                 bluetooth_gatt_set_characteristic_value(http_hdr_obj_path, content, hdr_len);
590 #endif
591                 // TODO : Handle Truncated Header
592
593                 // Write Data to Status Code Characteristic
594 #ifdef  HPS_GATT_DB
595                 data_status = (hdr_len > MAX_ENTITY_LENGTH) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
596                 if (data_status == DS_BODY_TRUNCATED && SOUP_STATUS_IS_SUCCESSFUL(http_status)) {
597                         _bt_hps_set_notify_read_status(http_hdr_obj_path, data_status, 0, http_status);
598                 }
599                 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
600 #else
601                 status[0] = http_status & 0x0F;
602                 status[1] = (http_status >> 8) & 0x0F;
603                 status[2] = (hdr_len > MAX_HEADER_LENGTH) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
604
605                 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
606 #endif
607         } else {
608                 BT_ERR("HEAD Response is NULL");
609                 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
610         }
611
612         return;
613 }
614
615 void _bt_hps_http_response_cb(SoupSession *session,
616                         SoupMessage *msg, gpointer user_data)
617 {
618         unsigned short http_status = 0x00;
619 #ifndef HPS_GATT_DB
620         unsigned char status[3] = {0x00};
621 #else
622         const char *device_address = user_data;
623         bluetooth_device_address_t addr_hex = { {0,} };
624         unsigned char data_status = DS_NONE;
625         _hps_convert_address_to_hex(&addr_hex, device_address);
626 #endif
627
628         if (hps_soup_session != session) {
629                 BT_ERR("Wrong Session");
630                 return;
631         }
632
633         if (msg == NULL) {
634                 BT_ERR("Wrong Message");
635                 return;
636         }
637
638         hps_soup_msg = NULL;
639
640         req_state = HTTP_REQ_STATE_EXECUTED;
641
642         http_status = msg->status_code;
643
644         // Write Data to Status Code Characteristic
645 #ifndef HPS_GATT_DB
646         status[0] = http_status & 0x0F;
647         status[1] = (http_status >> 8) & 0x0F;
648         status[2] = DS_HEADER_RECEIVED;
649         bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
650 #else
651         data_status = DS_HEADER_RECEIVED;
652         _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
653 #endif
654
655         return;
656 }
657
658 void _bt_hps_get_response_cb(SoupSession *session,
659                         SoupMessage *msg, gpointer user_data)
660 {
661         SoupBuffer *body = NULL;
662         unsigned short http_status = 0x00;
663 #ifndef HPS_GATT_DB
664         unsigned char status[3] = {0x00};
665 #else
666         const char *device_address = user_data;
667         bluetooth_device_address_t addr_hex = { {0,} };
668         unsigned char data_status = DS_NONE;
669         _hps_convert_address_to_hex(&addr_hex, device_address);
670 #endif
671
672         if (hps_soup_session != session) {
673                 BT_ERR("Wrong Session");
674                 return;
675         }
676
677         if (msg == NULL) {
678                 BT_ERR("Wrong Message");
679                 return;
680         }
681
682         hps_soup_msg = NULL;
683
684         req_state = HTTP_REQ_STATE_EXECUTED;
685
686         http_status = msg->status_code;
687
688         // Process Entity Body in Response Message
689         if (msg->response_body) {
690
691                 body = soup_message_body_flatten(msg->response_body);
692                 if (body == NULL) {
693                         BT_ERR("Wrong Response Body");
694 #ifdef HPS_GATT_DB
695                         _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
696 #endif
697                         return;
698                 }
699                 if (body->data == NULL || body->length <= 0) {
700                         BT_ERR("Wrong Response");
701                         soup_buffer_free(body);
702 #ifdef HPS_GATT_DB
703                         _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
704 #endif
705                         return;
706                 }
707                 // Write Data to Entity Body Characteristic
708 #ifdef  HPS_GATT_DB
709                 _bt_hps_set_char_value(http_entity_obj_path, body->data, body->length);
710 #else
711                 bluetooth_gatt_set_characteristic_value(http_entity_obj_path, body->data, body->length);
712 #endif
713                 // TODO : Handle Truncated Entiry Body
714
715                 // Write Data to Status Code Characteristic
716 #ifdef  HPS_GATT_DB
717                 data_status = (body->length > MAX_ENTITY_LENGTH) ? DS_BODY_TRUNCATED : DS_BODY_RECEIVED;
718                 if (data_status == DS_BODY_TRUNCATED && SOUP_STATUS_IS_SUCCESSFUL(http_status)) {
719                         _bt_hps_set_notify_read_status(http_entity_obj_path, data_status, 0, http_status);
720                 }
721                 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
722
723 #else
724                 status[0] = http_status & 0x0F;
725                 status[1] = (http_status >> 8) & 0x0F;
726                 status[2] = (body->length > MAX_HEADER_LENGTH) ? DS_BODY_TRUNCATED : DS_BODY_TRUNCATED;
727
728                 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
729 #endif
730                 soup_buffer_free(body);
731         } else {
732                 BT_ERR("GET Response Body is NULL");
733 #ifdef HPS_GATT_DB
734                 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
735 #endif
736         }
737
738         // Process Header in Response Body
739         if (msg->response_headers) {
740
741                 const char *content = NULL;
742                 const char *length = NULL;
743                 guint hdr_len = 0;
744
745                 length = soup_message_headers_get_one(msg->request_headers,
746                                                                 "Content-Length");
747                 // Check "Content-MD5" is the right name to get header content
748                 content = soup_message_headers_get_one(msg->response_headers,
749                                                                 "Content-MD5");
750                 if (content == NULL || length == NULL) {
751                         BT_ERR("Wrong Response Header");
752                         data_status = DS_NONE;
753                         _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
754                         return;
755                 }
756
757                 hdr_len = soup_message_headers_get_content_length(msg->response_headers);
758                 // Write Data to Header Characteristic
759 #ifdef  HPS_GATT_DB
760                 _bt_hps_set_char_value(http_hdr_obj_path, content, hdr_len);
761 #else
762                 bluetooth_gatt_set_characteristic_value(http_hdr_obj_path, content, hdr_len);
763 #endif
764                 // TODO : Handle Truncated Header
765
766                 // Write Data to Status Code Characteristic
767 #ifdef  HPS_GATT_DB
768                 data_status = (hdr_len > MAX_HEADER_LENGTH) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
769                 if (data_status == DS_HEADER_TRUNCATED && SOUP_STATUS_IS_SUCCESSFUL(http_status)) {
770                         _bt_hps_set_notify_read_status(http_hdr_obj_path, data_status, 0, http_status);
771                 }
772                 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
773 #else
774                 status[0] = http_status & 0x0F;
775                 status[1] = (http_status >> 8) & 0x0F;
776                 status[2] = (hdr_len > MAX_HEADER_LENGTH) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
777
778                 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
779 #endif
780         } else {
781                 BT_ERR("GET Response Header is NULL");
782 #ifdef HPS_GATT_DB
783                 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
784 #endif
785         }
786
787         return;
788 }
789
790 #ifdef  HPS_GATT_DB
791 int _bt_hps_control_point_write_cb(const char *value, int len, char *addr)
792 #else
793 int _bt_hps_control_point_write_cb(char *value, int len)
794 #endif
795 {
796         int opcode = *value;
797         GTlsCertificate *cert = NULL;
798         GTlsCertificateFlags flags;
799         gboolean https_status = FALSE;
800         int result = BLUETOOTH_ERROR_NONE;
801         BT_INFO("Opcode %0x", opcode);
802
803 #ifdef  HPS_GATT_DB
804         _bt_hps_set_char_value(http_cp_obj_path, value, len);
805 #endif
806
807         switch (opcode) {
808                 case HTTP_GET_REQUEST:
809                         if (req_state == HTTP_REQ_STATE_EXECUTED) {
810                                 req_state = HTTP_REQ_STATE_INPROGRESS;
811                                 hps_soup_msg = soup_message_new("GET", g_uri);
812 #ifdef  HPS_GATT_DB
813                                 g_object_ref(hps_soup_msg);
814                                 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, addr);
815 #else
816                                 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, NULL);
817 #endif
818                         } else {
819                                 BT_ERR("HTTP GET request in progress, message dropped");
820                                 result = BLUETOOTH_ERROR_INTERNAL;
821                         }
822                         break;
823
824                 case HTTP_POST_REQUEST:
825                         if (req_state == HTTP_REQ_STATE_EXECUTED) {
826                                 req_state = HTTP_REQ_STATE_INPROGRESS;
827                                 hps_soup_msg = soup_message_new("POST", g_uri);
828                                 if (hps_soup_msg == NULL || g_entity == NULL) {
829                                         BT_ERR("Soup Message NULL");
830                                         result = BLUETOOTH_ERROR_INTERNAL;
831                                         req_state = HTTP_REQ_STATE_EXECUTED;
832                                         break;
833                                 }
834                                 soup_message_set_request(hps_soup_msg, "text/xml", SOUP_MEMORY_COPY,
835                                                           g_entity, strlen(g_entity));
836 #ifdef  HPS_GATT_DB
837                                 g_object_ref(hps_soup_msg);
838                                 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
839 #else
840                                 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
841 #endif
842                         } else {
843                                 BT_ERR("HTTP POST request in progress, message dropped");
844                                 result = BLUETOOTH_ERROR_INTERNAL;
845                         }
846                         break;
847
848                 case HTTP_HEAD_REQUEST:
849                         if (req_state == HTTP_REQ_STATE_EXECUTED) {
850                                 req_state = HTTP_REQ_STATE_INPROGRESS;
851                                 hps_soup_msg = soup_message_new("HEAD", g_uri);
852                                 if (hps_soup_msg == NULL) {
853                                         BT_ERR("Soup Message NULL");
854                                         result = BLUETOOTH_ERROR_INTERNAL;
855                                         req_state = HTTP_REQ_STATE_EXECUTED;
856                                         break;
857                                 }
858 #ifdef  HPS_GATT_DB
859                                 g_object_ref(hps_soup_msg);
860                                 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, addr);
861 #else
862                                 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, NULL);
863 #endif
864                         } else {
865                                 BT_ERR("HTTP HEAD request in progress, message dropped");
866                                 result = BLUETOOTH_ERROR_INTERNAL;
867                         }
868                         break;
869
870                 case HTTP_PUT_REQUEST:
871                         if (req_state == HTTP_REQ_STATE_EXECUTED) {
872                                 SoupBuffer *buf;
873                                 req_state = HTTP_REQ_STATE_INPROGRESS;
874                                 hps_soup_msg = soup_message_new("PUT", g_uri);
875                                 if (hps_soup_msg == NULL  || g_entity == NULL) {
876                                         BT_ERR("Soup Message NULL");
877                                         result = BLUETOOTH_ERROR_INTERNAL;
878                                         req_state = HTTP_REQ_STATE_EXECUTED;
879                                         break;
880                                 }
881                                 buf = soup_buffer_new(SOUP_MEMORY_TAKE, g_entity, strlen(g_entity));
882                                 soup_message_body_append_buffer(hps_soup_msg->request_body, buf);
883                                 soup_message_body_set_accumulate(hps_soup_msg->request_body, FALSE);
884 #ifdef  HPS_GATT_DB
885                                 g_object_ref(hps_soup_msg);
886                                 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
887 #else
888                                 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
889 #endif
890
891                         } else {
892                                 BT_ERR("HTTP PUT request in progress, message dropped");
893                                 result = BLUETOOTH_ERROR_INTERNAL;
894                         }
895                         break;
896
897                 case HTTP_DELETE_REQUEST:
898                         if (req_state == HTTP_REQ_STATE_EXECUTED) {
899                                 req_state = HTTP_REQ_STATE_INPROGRESS;
900                                 hps_soup_msg = soup_message_new("DELETE", g_uri);
901                                 if (hps_soup_msg == NULL) {
902                                         BT_ERR("Soup Message NULL");
903                                         result = BLUETOOTH_ERROR_INTERNAL;
904                                         req_state = HTTP_REQ_STATE_EXECUTED;
905                                         break;
906                                 }
907 #ifdef  HPS_GATT_DB
908                                 g_object_ref(hps_soup_msg);
909                                 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
910 #else
911                                 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
912 #endif
913                         } else {
914                                 BT_ERR("HTTP DELETE request in progress, message dropped");
915                                 result = BLUETOOTH_ERROR_INTERNAL;
916                         }
917                         break;
918
919                 case HTTPS_GET_REQUEST:
920                         if (req_state == HTTP_REQ_STATE_EXECUTED) {
921                                 req_state = HTTP_REQ_STATE_INPROGRESS;
922                                 hps_soup_msg = soup_message_new("GET", g_uri);
923                                 if (hps_soup_msg == NULL) {
924                                         BT_ERR("Soup Message NULL");
925                                         result = BLUETOOTH_ERROR_INTERNAL;
926                                         req_state = HTTP_REQ_STATE_EXECUTED;
927                                         break;
928                                 }
929 #ifdef  HPS_GATT_DB
930                                 g_object_ref(hps_soup_msg);
931                                 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, addr);
932 #else
933                                 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, NULL);
934 #endif
935                                 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
936 #ifdef  HPS_GATT_DB
937                                 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1);
938 #else
939                                 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
940 #endif
941                         } else {
942                                 BT_ERR("HTTPS GET request in progress, message dropped");
943                                 result = BLUETOOTH_ERROR_INTERNAL;
944                         }
945                         break;
946
947                 case HTTPS_HEAD_REQUEST:
948                         if (req_state == HTTP_REQ_STATE_EXECUTED) {
949                                 req_state = HTTP_REQ_STATE_INPROGRESS;
950                                 hps_soup_msg = soup_message_new("HEAD", g_uri);
951                                 if (hps_soup_msg == NULL) {
952                                         BT_ERR("Soup Message NULL");
953                                         result = BLUETOOTH_ERROR_INTERNAL;
954                                         req_state = HTTP_REQ_STATE_EXECUTED;
955                                         break;
956                                 }
957 #ifdef  HPS_GATT_DB
958                                 g_object_ref(hps_soup_msg);
959                                 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, addr);
960 #else
961                                 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, NULL);
962 #endif
963                                 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
964 #ifdef  HPS_GATT_DB
965                                 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1);
966 #else
967                                 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
968 #endif
969                         } else {
970                                 BT_ERR("HTTPS HEAD request in progress, message dropped");
971                                 result = BLUETOOTH_ERROR_INTERNAL;
972                         }
973                         break;
974
975                 case HTTPS_POST_REQUEST:
976                         if (req_state == HTTP_REQ_STATE_EXECUTED) {
977                                 req_state = HTTP_REQ_STATE_INPROGRESS;
978                                 hps_soup_msg = soup_message_new("POST", g_uri);
979                                 if (hps_soup_msg == NULL) {
980                                         BT_ERR("Soup Message NULL");
981                                         result = BLUETOOTH_ERROR_INTERNAL;
982                                         req_state = HTTP_REQ_STATE_EXECUTED;
983                                         break;
984                                 }
985                                 soup_message_set_request(hps_soup_msg, "text/xml", SOUP_MEMORY_STATIC,
986                                                           g_entity, strlen(g_entity));
987 #ifdef  HPS_GATT_DB
988                                 g_object_ref(hps_soup_msg);
989                                 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
990 #else
991                                 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
992
993 #endif
994                                 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
995 #ifdef  HPS_GATT_DB
996                                 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1);
997 #else
998                                 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
999 #endif
1000                         } else {
1001                                 BT_ERR("HTTPS POST request in progress, message dropped");
1002                                 result = BLUETOOTH_ERROR_INTERNAL;
1003                         }
1004                         break;
1005
1006                 case HTTPS_PUT_REQUEST:
1007                         if (req_state == HTTP_REQ_STATE_EXECUTED) {
1008                                 SoupBuffer *buf;
1009                                 req_state = HTTP_REQ_STATE_INPROGRESS;
1010                                 hps_soup_msg = soup_message_new("PUT", g_uri);
1011                                 if (hps_soup_msg == NULL) {
1012                                         BT_ERR("Soup Message NULL");
1013                                         result = BLUETOOTH_ERROR_INTERNAL;
1014                                         req_state = HTTP_REQ_STATE_EXECUTED;
1015                                         break;
1016                                 }
1017                                 buf = soup_buffer_new(SOUP_MEMORY_TAKE, g_entity, strlen(g_entity));
1018                                 soup_message_body_append_buffer(hps_soup_msg->request_body, buf);
1019                                 soup_message_body_set_accumulate(hps_soup_msg->request_body, FALSE);
1020 #ifdef  HPS_GATT_DB
1021                                 g_object_ref(hps_soup_msg);
1022                                 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
1023 #else
1024                                 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
1025 #endif
1026                                 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
1027 #ifdef  HPS_GATT_DB
1028                                 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1);
1029 #else
1030                                 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
1031 #endif
1032                         } else {
1033                                 BT_ERR("HTTPS PUT request in progress, message dropped");
1034                                 result = BLUETOOTH_ERROR_INTERNAL;
1035                         }
1036                         break;
1037
1038                 case HTTPS_DELETE_REQUEST:
1039                         if (req_state == HTTP_REQ_STATE_EXECUTED) {
1040                                 req_state = HTTP_REQ_STATE_INPROGRESS;
1041                                 hps_soup_msg = soup_message_new("DELETE", g_uri);
1042                                 if (hps_soup_msg == NULL) {
1043                                         BT_ERR("Soup Message NULL");
1044                                         result = BLUETOOTH_ERROR_INTERNAL;
1045                                         req_state = HTTP_REQ_STATE_EXECUTED;
1046                                         break;
1047                                 }
1048 #ifdef  HPS_GATT_DB
1049                                 g_object_ref(hps_soup_msg);
1050                                 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
1051 #else
1052                                 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
1053 #endif
1054
1055                                 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
1056 #ifdef  HPS_GATT_DB
1057                                 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1);
1058 #else
1059                                 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
1060 #endif
1061                         } else {
1062                                 BT_ERR("HTTPS DELETE request in progress, message dropped");
1063                                 result = BLUETOOTH_ERROR_INTERNAL;
1064                         }
1065                         break;
1066
1067                 case HTTP_REQUEST_CANCEL:
1068                         /* Cancel the outstanding request */
1069                         if (req_state == HTTP_REQ_STATE_INPROGRESS) {
1070                                 req_state = HTTP_REQ_STATE_IDLE;
1071                                 if (hps_soup_msg == NULL) {
1072                                         BT_ERR("Soup Message NULL");
1073                                         result = BLUETOOTH_ERROR_INTERNAL;
1074                                         req_state = HTTP_REQ_STATE_EXECUTED;
1075                                         break;
1076                                 }
1077                                 soup_session_cancel_message(hps_soup_session, hps_soup_msg, SOUP_STATUS_CANCELLED);
1078                                 hps_soup_msg = NULL;
1079                         }
1080                         break;
1081
1082                 default:
1083                         BT_ERR("Unknown opcode %0x", opcode);
1084                         result = BLUETOOTH_ERROR_INTERNAL;
1085                         break;
1086         }
1087
1088         return result;
1089 }
1090
1091 void _bt_hps_security_read_cb(char *value, int len)
1092 {
1093         BT_INFO("HPS Client Read the value");
1094         return;
1095 }
1096
1097 #ifdef  HPS_GATT_DB
1098 void _bt_hps_gatt_char_property_changed_event(GVariant *msg,
1099                                 const char *path)
1100 {
1101         int result = BLUETOOTH_ERROR_NONE;
1102         GVariantIter value_iter;
1103         const char *property = NULL;
1104         const char * char_path = NULL;
1105         const char * svc_handle = NULL;
1106         GVariant *var = NULL;
1107         GVariant *val = NULL;
1108         g_variant_iter_init(&value_iter, msg);
1109
1110         while ((g_variant_iter_loop(&value_iter, "{sv}", &property, &var))) {
1111
1112                 if (property == NULL) {
1113                         BT_ERR("Property NULL");
1114                         return;
1115                 }
1116
1117                 if (!g_strcmp0(property, "WriteValue")) {
1118                         int len = 0;
1119                         BT_INFO("WriteValue");
1120                         BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
1121
1122                         if (var) {
1123                                 gchar *addr = NULL;
1124                                 guint8 req_id = 1;
1125                                 guint16 offset = 0;
1126                                 char *value = NULL;
1127                                 g_variant_get(var, "(&s&s&syq@ay)", &char_path,
1128                                                 &svc_handle, &addr, &req_id, &offset, &val);
1129
1130                                 len = g_variant_get_size(val);
1131
1132                                 BT_DBG("Len = %d", len);
1133
1134                                 value = (char *) g_variant_get_data(val);
1135
1136                                 if (len != 0) {
1137                                         if (!g_strcmp0(char_path, http_uri_obj_path)) {
1138                                                 /* Retrive URI */
1139                                                 result = _bt_hps_uri_write_cb(value, len);
1140                                         } else if (!g_strcmp0(char_path, http_hdr_obj_path)) {
1141                                                 /* Retrive HEADER */
1142                                                 result = _bt_hps_http_header_write_cb(value, len);
1143                                         } else if (!g_strcmp0(char_path, http_entity_obj_path)) {
1144                                                 /* Retrive ENTITY BODY */
1145                                                 result = _bt_hps_entity_body_write_cb(value, len);
1146                                         } else if (!g_strcmp0(char_path, http_cp_obj_path)) {
1147                                                 result = _bt_hps_control_point_write_cb(value, len, addr);
1148                                         } else {
1149                                                 BT_ERR("Wrong Object Path %s", char_path);
1150                                                 result = BLUETOOTH_ERROR_INTERNAL;
1151                                         }
1152                                 bluetooth_gatt_send_response(req_id, BLUETOOTH_GATT_ATT_REQUEST_TYPE_WRITE, result, 0, NULL, 0);
1153                                 } else {
1154                                         BT_ERR("Array Len 0");
1155                                 }
1156                         } else {
1157                                 BT_ERR("var==NULL");
1158                         }
1159                 } else if (!g_strcmp0(property, "ReadValue")) {
1160                         gchar *addr = NULL;
1161                         guint8 req_id = 1;
1162                         guint16 offset = 0;
1163                         char *value = NULL;
1164                         int len = 0;
1165                         int data_status = -1;
1166                         BT_INFO("ReadValue");
1167                         BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
1168
1169                         g_variant_get(var, "(&s&s&syq)", &char_path, &svc_handle,
1170                                                                 &addr, &req_id, &offset);
1171
1172                         data_status = _bt_hps_read_cb(char_path, &value, &len);
1173                         if (data_status >= DS_NONE) {
1174                                 struct hps_notify_read_info *notify_read_info = NULL;
1175                                 bluetooth_device_address_t addr_hex = { {0,} };
1176                                 _hps_convert_address_to_hex(&addr_hex, addr);
1177                                 bluetooth_gatt_send_response(req_id, BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ,
1178                                                                 BLUETOOTH_ERROR_NONE, offset, value, len);
1179                                 notify_read_info = _bt_hps_get_notify_read_status(char_path);
1180                                 if (notify_read_info) {
1181                                         _bt_hps_send_status_notification(notify_read_info->https_status,
1182                                                                         data_status, &addr_hex);
1183                                 } else {
1184                                         if (data_status == DS_BODY_RECEIVED ||
1185                                                 data_status == DS_HEADER_RECEIVED) {
1186                                                 _bt_hps_set_char_value(char_path, NULL, 0);
1187                                         }
1188                                 }
1189                                 if (value)
1190                                         g_free(value);
1191                         } else {
1192                                 BT_ERR("ReadValue failed %s", char_path);
1193                                 bluetooth_gatt_send_response(req_id, BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ,
1194                                                                 BLUETOOTH_ERROR_INTERNAL, offset, NULL, 0);
1195                         }
1196                 }
1197         }
1198         return;
1199 }
1200 #else
1201 void _bt_hps_gatt_char_property_changed_event(GVariant *msg,
1202                                 const char *path)
1203 {
1204         GVariantIter value_iter;
1205         char *property = NULL;
1206         char * char_handle = NULL;
1207         GVariant *val = NULL;
1208         int result = BLUETOOTH_ERROR_NONE;
1209         GVariant *param = NULL;
1210         g_variant_iter_init(&value_iter, msg);
1211         char_handle = g_strdup(path);
1212
1213         while ((g_variant_iter_loop(&value_iter, "{sv}", &property, &val))) {
1214
1215                 if (property == NULL) {
1216                         BT_ERR("Property NULL");
1217                         return;
1218                 }
1219
1220                 if (strcasecmp(property, "ChangedValue") == 0) {
1221
1222                         int len = 0;
1223                         GByteArray *gp_byte_array = NULL;
1224                         BT_INFO("Type '%s'\n", g_variant_get_type_string(val));
1225
1226                         if (val) {
1227                                 gp_byte_array = g_byte_array_new();
1228                                 len = g_variant_get_size(val);
1229                                 BT_DBG("Len = %d", len);
1230                                 g_byte_array_append(gp_byte_array,
1231                                         (const guint8 *)g_variant_get_data(val), len);
1232                                 if (gp_byte_array->len != 0) {
1233                                         GVariant *byte_array = NULL;
1234                                         byte_array = g_variant_new_from_data(
1235                                                                 G_VARIANT_TYPE_BYTESTRING,
1236                                                                 gp_byte_array->data,
1237                                                                 gp_byte_array->len,
1238                                                                 TRUE, NULL, NULL);
1239                                         param = g_variant_new("(is@ay)", result, char_handle,
1240                                                                 byte_array);
1241
1242                                         if (strcmp(path, http_uri_obj_path)) {
1243                                                 //Retrive URI
1244                                                 _bt_hps_uri_write_cb(NULL, len);
1245                                         } else if (strcmp(path, http_hdr_obj_path)) {
1246                                                 //Retrive HEADER
1247                                                 _bt_hps_http_header_write_cb(NULL, len);
1248                                         } else if (strcmp(path, http_entity_obj_path)) {
1249                                                 //Retrive ENTITY BODY
1250                                                 _bt_hps_entity_body_write_cb(NULL, len);
1251                                         } else if (strcmp(path, http_cp_obj_path)) {
1252                                                 _bt_hps_control_point_write_cb(NULL, len);
1253                                         } else if (strcmp(path, http_security_obj_path)) {
1254                                                 _bt_hps_security_read_cb(NULL, len);
1255                                         } else {
1256                                                 BT_ERR("Wrong Object Path %s", path);
1257                                         }
1258                                 } else {
1259                                         BT_ERR("Array Len 0");
1260                                 }
1261                                 g_byte_array_free(gp_byte_array, TRUE);
1262                         } else {
1263                                 BT_ERR("val==NULL");
1264                         }
1265                 }
1266         }
1267         g_free(char_handle);
1268
1269         return;
1270 }
1271 #endif
1272
1273 void _bt_hps_property_event_filter(GDBusConnection *connection,
1274                                         const gchar *sender_name,
1275                                         const gchar *object_path,
1276                                         const gchar *interface_name,
1277                                         const gchar *signal_name,
1278                                         GVariant *parameters,
1279                                         gpointer user_data)
1280 {
1281         GVariant *value;
1282
1283         if (signal_name == NULL) {
1284                 BT_ERR("Wrong Signal");
1285                 return;
1286         }
1287
1288 #ifdef  HPS_GATT_DB
1289         if (g_strcmp0(signal_name, PROPERTIES_CHANGED) == 0) {
1290
1291                 g_variant_get(parameters, "(@a{sv}@as)", &value, NULL);
1292
1293                 _bt_hps_gatt_char_property_changed_event(value, object_path);
1294 #else
1295         if (g_strcmp0(interface_name, BT_HPS_PROPERTIES_INTERFACE) == 0) {
1296
1297                 g_variant_get(parameters, "(&s@a{sv}@as)", &interface_name, &value, NULL);
1298
1299                 _bt_hps_gatt_char_property_changed_event(value, object_path);
1300 #endif
1301         } else {
1302                 //BT_ERR("Wrong Interface %s", interface_name);
1303         }
1304
1305         return;
1306 }
1307
1308
1309 void _bt_hps_adapter_event_filter(GDBusConnection *connection,
1310                                         const gchar *sender_name,
1311                                         const gchar *object_path,
1312                                         const gchar *interface_name,
1313                                         const gchar *signal_name,
1314                                         GVariant *parameters,
1315                                         gpointer user_data)
1316 {
1317         int result = BLUETOOTH_ERROR_NONE;
1318         GVariant *value;
1319
1320         if (signal_name == NULL) {
1321                 BT_ERR("Wrong Signal");
1322                 return;
1323         }
1324
1325         BT_INFO("Interface %s, Signal %s", interface_name, signal_name);
1326
1327         if (g_strcmp0(interface_name, BT_HPS_INTERFACE_NAME) == 0) {
1328
1329                 g_variant_get(parameters, "(&s@a{sv}@as)", &interface_name, &value, NULL);
1330
1331                 if (strcasecmp(signal_name, BLE_ENABLED) == 0) {
1332                         g_variant_get(parameters, "(i)", &result);
1333
1334                         if (_bt_hps_prepare_httpproxy() != BLUETOOTH_ERROR_NONE) {
1335                                 BT_ERR("Fail to prepare HTTP Proxy");
1336                                 return;
1337                         }
1338
1339                         if (_bt_hps_set_advertising_data() != BLUETOOTH_ERROR_NONE) {
1340                                 BT_ERR("Fail to set advertising data");
1341                                 return;
1342                         }
1343
1344                 } else {
1345                         BT_ERR("Wrong Signal %s", signal_name);
1346                 }
1347         }
1348
1349         return;
1350 }
1351
1352 int _bt_hps_init_event_receiver()
1353 {
1354         GError *error = NULL;
1355
1356         BT_DBG("");
1357
1358         if (conn == NULL) {
1359                 conn =  g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
1360                 if (error != NULL) {
1361                         BT_ERR("ERROR: Can't get on system bus [%s]", error->message);
1362                         g_clear_error(&error);
1363                 }
1364         }
1365
1366         property_sub_id = g_dbus_connection_signal_subscribe(conn,
1367                 NULL, BT_HPS_INTERFACE_NAME,
1368                 PROPERTIES_CHANGED, BT_HPS_OBJECT_PATH, NULL, 0,
1369                 _bt_hps_property_event_filter,
1370                 NULL, NULL);
1371
1372         adapter_sub_id = g_dbus_connection_signal_subscribe(conn,
1373                 NULL, BT_HPS_INTERFACE_NAME,
1374                 BLE_ENABLED, BT_HPS_OBJECT_PATH, NULL, 0,
1375                 _bt_hps_adapter_event_filter,
1376                 NULL, NULL);
1377
1378         return 0;
1379 }
1380
1381 void _bt_hps_deinit_event_receiver(void)
1382 {
1383         BT_DBG("");
1384         g_dbus_connection_signal_unsubscribe(conn, property_sub_id);
1385         g_dbus_connection_signal_unsubscribe(conn, adapter_sub_id);
1386         conn = NULL;
1387         return;
1388 }
1389
1390 int _bt_hps_set_advertising_data(void)
1391 {
1392         int ret;
1393         BT_DBG("");
1394
1395     // Temporary UUID is used. SIG have not yet defined the UUID yet
1396         guint8 data[4]  = {0x03, 0x02, 0x00, 0x19};
1397         bluetooth_advertising_data_t adv;
1398
1399         BT_DBG("%x %x %x %x", data[0], data[1], data[2], data[3]);
1400         memcpy(adv.data, data, sizeof(data));
1401         ret = bluetooth_set_advertising_data(0, &adv, sizeof(data));
1402         if (ret != BLUETOOTH_ERROR_NONE) {
1403                 BT_ERR("Failed to set ADV data %d", ret);
1404                 return ret;
1405         }
1406
1407         ret = bluetooth_set_advertising(0, TRUE);
1408         if (ret != BLUETOOTH_ERROR_NONE) {
1409                 BT_ERR("Failed to set ADV %d", ret);
1410                 return ret;
1411         }
1412
1413         return 0;
1414 }
1415
1416 int _bt_hps_prepare_httpproxy(void)
1417 {
1418         int ret = BLUETOOTH_ERROR_NONE;
1419         char *char_uuid;
1420         char *service_uuid;
1421         char *desc_uuid;
1422         bt_gatt_characteristic_property_t props;
1423 #ifdef  HPS_GATT_DB
1424         char value[MAX_URI_LENGTH] = { 0 };
1425         struct hps_char_info *char_info = NULL;
1426         char cp = 0x00;
1427         char status[3] = { 0 };
1428 #endif
1429
1430         BT_DBG("");
1431
1432         ret = bluetooth_gatt_init();
1433         if (ret != BLUETOOTH_ERROR_NONE) {
1434                 BT_ERR("Failed to Init GATT %d", ret);
1435                 goto fail;
1436         }
1437
1438         service_uuid = g_strdup(HPS_UUID);
1439         ret = bluetooth_gatt_add_service(service_uuid, &hps_obj_path);
1440         if (ret != BLUETOOTH_ERROR_NONE) {
1441                 BT_ERR("Failed to add service %d", ret);
1442                 goto fail;
1443         }
1444
1445         /* Characteristic URI */
1446         props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1447                         BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1448         char_uuid = g_strdup(HTTP_URI_UUID);
1449         ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_uri_obj_path);
1450         if (ret != BLUETOOTH_ERROR_NONE) {
1451                 BT_ERR("Failed to add new char %d", ret);
1452                 goto fail;
1453         }
1454
1455 #ifdef  HPS_GATT_DB
1456         ret = bluetooth_gatt_set_characteristic_value(http_uri_obj_path, value, MAX_URI_LENGTH);
1457         if (ret != BLUETOOTH_ERROR_NONE) {
1458                 BT_ERR("Failed to add new char %d", ret);
1459                 goto fail;
1460         }
1461
1462         /* Store requets information */
1463         char_info = g_new0(struct hps_char_info, 1);
1464         char_info->char_path = g_strdup(http_uri_obj_path);
1465         _bt_hps_set_char_value(http_uri_obj_path, value, MAX_URI_LENGTH);
1466         hps_char_list = g_slist_append(hps_char_list, char_info);
1467 #endif
1468
1469         /* Characteristic HTTP Headers */
1470         props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1471                         BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1472         char_uuid = g_strdup(HTTP_HDR_UUID);
1473         ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_hdr_obj_path);
1474         if (ret != BLUETOOTH_ERROR_NONE) {
1475                 BT_ERR("Failed to add new char %d", ret);
1476                 goto fail;
1477         }
1478 #ifdef  HPS_GATT_DB
1479         ret = bluetooth_gatt_set_characteristic_value(http_hdr_obj_path, value, MAX_HEADER_LENGTH);
1480         if (ret != BLUETOOTH_ERROR_NONE) {
1481                 BT_ERR("Failed to add new char %d", ret);
1482                 goto fail;
1483         }
1484
1485         /* Store Characterisitc information */
1486         char_info = g_new0(struct hps_char_info, 1);
1487         char_info->char_path = g_strdup(http_hdr_obj_path);
1488         _bt_hps_set_char_value(http_hdr_obj_path, value, MAX_HEADER_LENGTH);
1489         hps_char_list = g_slist_append(hps_char_list, char_info);
1490 #endif
1491
1492         /* Characteristic HTTP Entity Body */
1493         props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1494                         BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1495         char_uuid = g_strdup(HTTP_ENTITY_UUID);
1496         ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_entity_obj_path);
1497         if (ret != BLUETOOTH_ERROR_NONE) {
1498                 BT_ERR("Failed to add new char %d", ret);
1499                 goto fail;
1500         }
1501 #ifdef  HPS_GATT_DB
1502         ret = bluetooth_gatt_set_characteristic_value(http_entity_obj_path, value, MAX_ENTITY_LENGTH);
1503         if (ret != BLUETOOTH_ERROR_NONE) {
1504                 BT_ERR("Failed to add new char %d", ret);
1505                 goto fail;
1506         }
1507
1508         /* Store Characterisitc information */
1509         char_info = g_new0(struct hps_char_info, 1);
1510         char_info->char_path = g_strdup(http_entity_obj_path);
1511         _bt_hps_set_char_value(http_entity_obj_path, value, MAX_ENTITY_LENGTH);
1512         hps_char_list = g_slist_append(hps_char_list, char_info);
1513 #endif
1514
1515         /* Characteristic HTTP Control Point */
1516         props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1517                         BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1518         char_uuid = g_strdup(HTTP_CP_UUID);
1519         ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_cp_obj_path);
1520         if (ret != BLUETOOTH_ERROR_NONE) {
1521                 BT_ERR("Failed to add new char %d", ret);
1522                 goto fail;
1523         }
1524 #ifdef  HPS_GATT_DB
1525         ret = bluetooth_gatt_set_characteristic_value(http_cp_obj_path, &cp, 1);
1526         if (ret != BLUETOOTH_ERROR_NONE) {
1527                 BT_ERR("Failed to add new char %d", ret);
1528                 goto fail;
1529         }
1530
1531         /* Store Characterisitc information */
1532         char_info = g_new0(struct hps_char_info, 1);
1533         char_info->char_path = g_strdup(http_cp_obj_path);
1534         _bt_hps_set_char_value(http_cp_obj_path, &cp, 1);
1535         hps_char_list = g_slist_append(hps_char_list, char_info);
1536 #endif
1537
1538         /* Characteristic HTTP Status Code */
1539         props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1540                         BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE |
1541                         BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1542         char_uuid = g_strdup(HTTP_STATUS_UUID);
1543         ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_status_obj_path);
1544         if (ret != BLUETOOTH_ERROR_NONE) {
1545                 BT_ERR("Failed to add new char %d", ret);
1546                 goto fail;
1547         }
1548 #ifdef  HPS_GATT_DB
1549         ret = bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
1550         if (ret != BLUETOOTH_ERROR_NONE) {
1551                 BT_ERR("Failed to add new char %d", ret);
1552                 goto fail;
1553         }
1554 #endif
1555         desc_uuid = g_strdup(HTTP_STATUS_CCC_DESC_UUID);
1556         ret = bluetooth_gatt_add_descriptor(http_status_obj_path, desc_uuid,
1557                                         (BLUETOOTH_GATT_PERMISSION_READ | BLUETOOTH_GATT_PERMISSION_WRITE),
1558                                         &http_status_desc_obj_path);
1559         if (ret != BLUETOOTH_ERROR_NONE) {
1560                 BT_ERR("Failed to add new char descriptor %d", ret);
1561                 goto fail;
1562         }
1563 #ifdef  HPS_GATT_DB
1564         /* Store Characterisitc information */
1565         char_info = g_new0(struct hps_char_info, 1);
1566         char_info->char_path = g_strdup(http_status_obj_path);
1567         _bt_hps_set_char_value(http_status_obj_path, status, 3);
1568         hps_char_list = g_slist_append(hps_char_list, char_info);
1569 #endif
1570
1571         /* Characteristic HTTPS Security */
1572         props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1573                         BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1574         char_uuid = g_strdup(HTTP_SECURITY_UUID);
1575         ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_security_obj_path);
1576         if (ret != BLUETOOTH_ERROR_NONE) {
1577                 BT_ERR("Failed to add new char %d", ret);
1578                 goto fail;
1579         }
1580 #ifdef  HPS_GATT_DB
1581         ret = bluetooth_gatt_set_characteristic_value(http_security_obj_path, &cp, 1);
1582         if (ret != BLUETOOTH_ERROR_NONE) {
1583                 BT_ERR("Failed to add new char %d", ret);
1584                 goto fail;
1585         }
1586
1587         /* Store Characterisitc information */
1588         char_info = g_new0(struct hps_char_info, 1);
1589         char_info->char_path = g_strdup(http_security_obj_path);
1590         _bt_hps_set_char_value(http_security_obj_path, &cp, 1);
1591         hps_char_list = g_slist_append(hps_char_list, char_info);
1592 #endif
1593
1594         ret = bluetooth_gatt_register_service(hps_obj_path);
1595         if (ret != BLUETOOTH_ERROR_NONE) {
1596                 BT_ERR("Failed to register service %d", ret);
1597                 goto fail;
1598         }
1599
1600         ret = bluetooth_gatt_register_application();
1601         if (ret != BLUETOOTH_ERROR_NONE) {
1602                 BT_ERR("Failed to register application %d", ret);
1603                 goto fail;
1604         }
1605
1606         return ret;
1607
1608 fail:
1609 #ifdef  HPS_GATT_DB
1610         delete_all_characterisitc();
1611         delete_all_notify_read_status();
1612 #endif
1613         return ret;
1614 }
1615
1616
1617 static void _bt_hps_sig_handler(int sig)
1618 {
1619         BT_DBG("");
1620
1621         switch (sig) {
1622                 case SIGTERM:
1623                         BT_DBG("caught signal - sigterm\n");
1624                         break;
1625                 case SIGINT:
1626                         BT_DBG("caught signal - sigint\n");
1627                         break;
1628                 case SIGKILL:
1629                         BT_DBG("caught signal - sigkill\n");
1630                         break;
1631                 default:
1632                         BT_DBG("caught signal %d and ignored\n", sig);
1633                         break;
1634         }
1635 }
1636
1637 void _bt_hps_exit(void)
1638 {
1639         int ret;
1640         BT_DBG("");
1641
1642         if (g_uri != NULL) {
1643                 g_free(g_uri);
1644                 g_uri = NULL;
1645         }
1646
1647         if (g_header != NULL) {
1648                 g_free(g_header);
1649                 g_header = NULL;
1650         }
1651
1652         if (g_entity != NULL) {
1653                 g_free(g_entity);
1654                 g_entity = NULL;
1655         }
1656
1657         soup_session_abort(hps_soup_session);
1658         g_assert_cmpint(G_OBJECT(hps_soup_session)->ref_count, ==, 1);
1659         g_object_unref(hps_soup_session);
1660
1661 #ifdef  HPS_GATT_DB
1662         delete_all_characterisitc();
1663 #endif
1664
1665         ret = bluetooth_gatt_deinit();
1666         if (ret != BLUETOOTH_ERROR_NONE)
1667                 BT_ERR("Failed to Deinit GATT %d", ret);
1668
1669         ret = bluetooth_unregister_callback();
1670         if (ret != BLUETOOTH_ERROR_NONE)
1671                 BT_ERR("Failed to Unregister callback %d", ret);
1672
1673         _bt_hps_deinit_event_receiver();
1674
1675         _bt_hps_unregister_interface();
1676
1677         if (main_loop != NULL) {
1678                 g_main_loop_quit(main_loop);
1679         }
1680 }
1681
1682 void bt_hps_event_callback(int event, bluetooth_event_param_t* param,
1683                                                         void *user_data)
1684 {
1685         BT_DBG("HPS event %d", event);
1686         return;
1687 }
1688
1689 /* HTTP Proxy Service Main loop */
1690 int main(void)
1691 {
1692         struct sigaction sa;
1693
1694         BT_ERR("Starting the bt-httpproxy daemon");
1695
1696         /* Values taken from http://www.browserscope.org/  following
1697           * the rule "Do What Every Other Modern Browser Is Doing". They seem
1698           * to significantly improve page loading time compared to soup's
1699           * default values.
1700           * Change MAX_CONNECTIONS_PER_HOST value 6 -> 12, and maxConnections is changed from 35 to 60.
1701           * Enhanced network loading speed apply tunning value. */
1702         static const int maxConnections = 60;
1703         static const int maxConnectionsPerHost = 12;
1704
1705         memset(&sa, 0, sizeof(sa));
1706         sa.sa_handler = _bt_hps_sig_handler;
1707         sa.sa_flags = SA_SIGINFO;
1708         sigaction(SIGINT, &sa, NULL);
1709         sigaction(SIGTERM, &sa, NULL);
1710         sigaction(SIGKILL, &sa, NULL);
1711
1712 #ifndef HPS_GATT_DB
1713         if (bluetooth_register_callback(bt_hps_event_callback, NULL) != BLUETOOTH_ERROR_NONE) {
1714                 BT_ERR("bluetooth_register_callback returned failiure");
1715                 return -3;
1716         }
1717 #endif
1718
1719         if (_bt_hps_register_interface() != BLUETOOTH_ERROR_NONE) {
1720                 BT_ERR("Fail to register http proxy service");
1721                 return -4;
1722         }
1723
1724         if (_bt_hps_init_event_receiver() != BLUETOOTH_ERROR_NONE) {
1725                 BT_ERR("Fail to init event reciever");
1726                 return -5;
1727         }
1728
1729         hps_soup_session = soup_session_async_new();
1730         if (hps_soup_session == NULL) {
1731                 BT_ERR("Failed to soup_session_async_new");
1732                 return -6;
1733         }
1734         /* Set Soup Session Fetures */
1735         g_object_set(hps_soup_session,
1736                         SOUP_SESSION_MAX_CONNS, maxConnections,
1737                         SOUP_SESSION_MAX_CONNS_PER_HOST, maxConnectionsPerHost,
1738                         SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER,
1739                         SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_SNIFFER,
1740                         SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_RESOLVER_DEFAULT,
1741                         SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
1742                         NULL);
1743
1744         main_loop = g_main_loop_new(NULL, FALSE);
1745
1746         g_main_loop_run(main_loop);
1747
1748         BT_DBG("g_main_loop_quit called!");
1749
1750         if (main_loop != NULL) {
1751                 g_main_loop_unref(main_loop);
1752         }
1753
1754         return 0;
1755 }
1756
1757 #endif