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