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