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