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