2 * Bluetooth-httpproxy-service
4 * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: C S Bhargava <cs.bhargava@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
27 #include "bt-httpproxy.h"
28 #include "bluetooth-api.h"
30 #include <libsoup/soup.h>
35 #define LOG_TAG "BLUETOOTH_HPS"
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)
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;
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;
56 struct hps_notify_read_info {
63 struct hps_char_info {
69 static GSList *hps_notify_read_list = NULL;
70 static GSList *hps_char_list = NULL;
73 static GDBusConnection *conn;
74 static GDBusConnection *g_conn;
75 static guint g_owner_id = 0;
76 GDBusNodeInfo *hps_node_info = NULL;
79 char *g_header = NULL;
80 char *g_entity = NULL;
82 static SoupSession *hps_soup_session = NULL;
83 static SoupMessage *hps_soup_msg = NULL;
86 static const gchar hps_introspection_xml[] =
88 " <interface name='org.projectx.httpproxy_service'>"
89 " <method name='enable'>"
90 " <arg type='y' name='status' direction='out'/>"
92 " <method name='disable'>"
93 " <arg type='y' name='status' direction='out'/>"
99 static void _bt_hps_set_char_value(const char *obj_path, const char* value, int value_length);
101 static void _hps_convert_address_to_hex(bluetooth_device_address_t *addr_hex, const char *addr_str)
104 unsigned int addr[BLUETOOTH_ADDRESS_LENGTH] = { 0, };
106 if (addr_str == NULL || addr_str[0] == '\0')
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);
114 for (i = 0; i < BLUETOOTH_ADDRESS_LENGTH; i++) {
115 addr_hex->addr[i] = (unsigned char)addr[i];
119 static void _bt_hps_send_status_notification(unsigned short http_status,
120 unsigned char data_status,
121 bluetooth_device_address_t *unicast_address)
123 char status[3] = {0x00};
124 int ret = BLUETOOTH_ERROR_NONE;
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);
133 /* Store the status value */
134 _bt_hps_set_char_value(http_status_obj_path, status, 3);
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");
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");
150 static void _bt_httpproxy_method(GDBusConnection *connection,
152 const gchar *object_path,
153 const gchar *interface_name,
154 const gchar *method_name,
155 GVariant *parameters,
156 GDBusMethodInvocation *invocation,
161 BT_DBG("Method[%s] Object Path[%s] Interface Name[%s]",
162 method_name, object_path, interface_name);
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) {
168 g_dbus_method_invocation_return_value(invocation, g_variant_new("(y)", status));
174 static const GDBusInterfaceVTable hps_method_table = {
175 _bt_httpproxy_method,
180 static void _bt_hps_on_bus_acquired (GDBusConnection *connection, const gchar *name, gpointer user_data)
183 GError *error = NULL;
189 object_id = g_dbus_connection_register_object(connection, BT_HPS_OBJECT_PATH,
190 hps_node_info->interfaces[0],
193 if (object_id == 0) {
194 BT_ERR("Failed to register method table: %s", error->message);
196 g_dbus_node_info_unref(hps_node_info);
202 static void _bt_hps_on_name_acquired (GDBusConnection *connection,
210 static void _bt_hps_on_name_lost (GDBusConnection *connection,
215 g_object_unref(g_conn);
217 g_dbus_node_info_unref(hps_node_info);
218 g_bus_unown_name(g_owner_id);
223 int _bt_hps_register_interface(void)
225 GError *error = NULL;
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;
236 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
238 G_BUS_NAME_OWNER_FLAGS_NONE,
239 _bt_hps_on_bus_acquired, _bt_hps_on_name_acquired, _bt_hps_on_name_lost,
241 g_owner_id = owner_id;
242 BT_DBG("owner_id is [%d]\n", owner_id);
244 return BLUETOOTH_ERROR_NONE;
247 void _bt_hps_unregister_interface(void)
251 g_object_unref(g_conn);
253 g_dbus_node_info_unref(hps_node_info);
254 g_bus_unown_name(g_owner_id);
260 static struct hps_char_info *hps_get_char_value(const char *path)
264 for (tmp = hps_char_list; tmp != NULL; tmp = tmp->next) {
266 struct hps_char_info *char_info = tmp->data;
267 if(!g_strcmp0(char_info->char_path, path))
274 static int char_info_cmp(gconstpointer a1, gconstpointer a2)
276 const struct hps_char_info *attrib1 = a1;
277 const struct hps_char_info *attrib2 = a2;
279 return g_strcmp0(attrib1->char_path, attrib2->char_path);
282 static int notify_info_cmp(gconstpointer a1, gconstpointer a2)
284 const struct hps_notify_read_info *attrib1 = a1;
285 const struct hps_notify_read_info *attrib2 = a2;
287 return g_strcmp0(attrib1->char_path, attrib2->char_path);
290 static void _bt_hps_set_char_value(const char *obj_path, const char* value, int value_length)
296 for (tmp = hps_char_list; tmp != NULL; tmp = tmp->next) {
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);
314 static void _bt_hps_set_notify_read_status(const char *obj_path,
315 guint offset_status, guint read_status, int https_status)
317 struct hps_notify_read_info *notify_read_info = NULL;
320 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
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);
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);
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);
359 static struct hps_notify_read_info *_bt_hps_get_notify_read_status(const char *obj_path)
363 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
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;
375 static void delete_all_characterisitc(void)
378 for (tmp = hps_char_list; tmp != NULL; tmp = tmp->next) {
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);
388 g_slist_free(hps_char_list);
389 hps_char_list = NULL;
392 static void delete_all_notify_read_status(void)
395 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
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);
403 g_slist_free(hps_notify_read_list);
404 hps_notify_read_list = NULL;
407 static void delete_notify_read_status(const char *obj_path)
410 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
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);
424 int _bt_hps_uri_write_cb(char *uri, int len)
426 if((len < 1) || (len > MAX_URI_LENGTH)) {
427 BT_ERR("Wrong URI length %d", len);
428 return BLUETOOTH_ERROR_INTERNAL;
431 /* g_uri will be used commonly for all HTTP methods whereever applicable */
434 g_uri = g_strndup(uri, len);
436 _bt_hps_set_char_value(http_uri_obj_path, g_uri, len);
438 return BLUETOOTH_ERROR_NONE;
441 int _bt_hps_http_header_write_cb(char *header, int len)
443 if((len < 1) || (len > MAX_HEADER_LENGTH)) {
444 BT_ERR("Wrong Header length %d", len);
445 return BLUETOOTH_ERROR_INTERNAL;
448 /* g_header will be used commonly for all HTTP methods where ever applicable
449 general-header, request-header, entity-header
453 g_header = g_strndup(header, len);
455 _bt_hps_set_char_value(http_hdr_obj_path, g_header, len);
458 return BLUETOOTH_ERROR_NONE;
461 int _bt_hps_entity_body_write_cb(char *entity, int len)
463 if((len < 1) || (len > MAX_ENTITY_LENGTH)) {
464 BT_ERR("Wrong Entity length %d", len);
465 return BLUETOOTH_ERROR_INTERNAL;
468 /* g_entity will be used commonly for all HTTP methods whereever applicable */
471 g_entity = g_strndup(entity, len);
473 _bt_hps_set_char_value(http_entity_obj_path, g_entity, len);
476 return BLUETOOTH_ERROR_NONE;
480 int _bt_hps_read_cb(const char *obj_path, char **value, int *len)
482 struct hps_char_info *info = NULL;
483 struct hps_notify_read_info *notify_read_info = NULL;
484 guint data_status = -1;
486 gboolean is_header = FALSE;
489 BT_ERR("Wrong Obj path");
493 if (!g_strcmp0(http_hdr_obj_path, obj_path))
496 info = hps_get_char_value(obj_path);
499 if (info->char_value == NULL || info->value_length == 0)
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) {
509 data_status = DS_HEADER_TRUNCATED;
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) {
519 data_status = DS_HEADER_RECEIVED;
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;
526 } else if (notify_read_info && (notify_read_info->read_status == DS_BODY_RECEIVED ||
527 notify_read_info->read_status == DS_HEADER_RECEIVED)) {
529 data_status = DS_HEADER_RECEIVED;
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;
542 void _bt_hps_head_response_cb(SoupSession *session,
543 SoupMessage *msg, gpointer user_data)
545 unsigned short http_status = 0x00;
547 unsigned char status[3] = {0x00};
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);
555 if(hps_soup_session != session) {
556 BT_ERR("Wrong Session");
561 BT_ERR("Wrong Message");
566 req_state = HTTP_REQ_STATE_EXECUTED;
568 http_status = msg->status_code;
570 // Process Header in Response Body
571 if(msg->response_headers) {
573 const char *content = NULL;
574 const char *length = NULL;
577 length = soup_message_headers_get_one (msg->request_headers,
579 // Check "Content-MD5" is the right name to get header content
580 content = soup_message_headers_get_one (msg->response_headers,
582 if (content == NULL || length == NULL) {
583 BT_ERR("Wrong Response Header");
584 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
588 hdr_len = soup_message_headers_get_content_length(msg->response_headers);
590 // Write Data to Header Characteristic
592 _bt_hps_set_char_value(http_hdr_obj_path, content, hdr_len);
594 bluetooth_gatt_set_characteristic_value(http_hdr_obj_path, content, hdr_len);
596 // TODO : Handle Truncated Header
598 // Write Data to Status Code Characteristic
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);
604 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
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;
610 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
613 BT_ERR("HEAD Response is NULL");
614 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
620 void _bt_hps_http_response_cb(SoupSession *session,
621 SoupMessage *msg, gpointer user_data)
623 unsigned short http_status = 0x00;
625 unsigned char status[3] = {0x00};
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);
633 if(hps_soup_session != session) {
634 BT_ERR("Wrong Session");
639 BT_ERR("Wrong Message");
645 req_state = HTTP_REQ_STATE_EXECUTED;
647 http_status = msg->status_code;
649 // Write Data to Status Code Characteristic
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);
656 data_status = DS_HEADER_RECEIVED;
657 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
663 void _bt_hps_get_response_cb(SoupSession *session,
664 SoupMessage *msg, gpointer user_data)
666 SoupBuffer *body = NULL;
667 unsigned short http_status = 0x00;
669 unsigned char status[3] = {0x00};
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);
677 if(hps_soup_session != session) {
678 BT_ERR("Wrong Session");
683 BT_ERR("Wrong Message");
689 req_state = HTTP_REQ_STATE_EXECUTED;
691 http_status = msg->status_code;
693 // Process Entity Body in Response Message
694 if(msg->response_body) {
696 body = soup_message_body_flatten (msg->response_body);
698 BT_ERR("Wrong Response Body");
700 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
704 if (body->data == NULL || body->length <= 0) {
705 BT_ERR("Wrong Response");
706 soup_buffer_free(body);
708 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
712 // Write Data to Entity Body Characteristic
714 _bt_hps_set_char_value(http_entity_obj_path, body->data, body->length);
716 bluetooth_gatt_set_characteristic_value(http_entity_obj_path, body->data, body->length);
718 // TODO : Handle Truncated Entiry Body
720 // Write Data to Status Code Characteristic
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);
726 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
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;
733 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
735 soup_buffer_free(body);
737 BT_ERR("GET Response Body is NULL");
739 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
743 // Process Header in Response Body
744 if(msg->response_headers) {
746 const char *content = NULL;
747 const char *length = NULL;
750 length = soup_message_headers_get_one (msg->request_headers,
752 // Check "Content-MD5" is the right name to get header content
753 content = soup_message_headers_get_one (msg->response_headers,
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);
762 hdr_len = soup_message_headers_get_content_length(msg->response_headers);
763 // Write Data to Header Characteristic
765 _bt_hps_set_char_value(http_hdr_obj_path, content, hdr_len);
767 bluetooth_gatt_set_characteristic_value(http_hdr_obj_path, content, hdr_len);
769 // TODO : Handle Truncated Header
771 // Write Data to Status Code Characteristic
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);
777 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
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;
783 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
786 BT_ERR("GET Response Header is NULL");
788 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
796 int _bt_hps_control_point_write_cb(const char *value, int len, char *addr)
798 int _bt_hps_control_point_write_cb(char *value, int len)
802 GTlsCertificate *cert = NULL;
803 GTlsCertificateFlags flags;
804 gboolean https_status = FALSE;
805 int result = BLUETOOTH_ERROR_NONE;
806 BT_INFO("Opcode %0x", opcode);
809 _bt_hps_set_char_value(http_cp_obj_path, value, len);
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);
818 g_object_ref (hps_soup_msg);
819 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, addr);
821 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, NULL);
824 BT_ERR("HTTP GET request in progress, message dropped");
825 result = BLUETOOTH_ERROR_INTERNAL;
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;
839 soup_message_set_request (hps_soup_msg, "text/xml", SOUP_MEMORY_COPY,
840 g_entity, strlen (g_entity));
842 g_object_ref (hps_soup_msg);
843 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
845 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
848 BT_ERR("HTTP POST request in progress, message dropped");
849 result = BLUETOOTH_ERROR_INTERNAL;
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;
864 g_object_ref (hps_soup_msg);
865 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, addr);
867 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, NULL);
870 BT_ERR("HTTP HEAD request in progress, message dropped");
871 result = BLUETOOTH_ERROR_INTERNAL;
875 case HTTP_PUT_REQUEST:
876 if(req_state == HTTP_REQ_STATE_EXECUTED) {
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;
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);
890 g_object_ref (hps_soup_msg);
891 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
893 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
897 BT_ERR("HTTP PUT request in progress, message dropped");
898 result = BLUETOOTH_ERROR_INTERNAL;
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;
913 g_object_ref (hps_soup_msg);
914 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
916 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
919 BT_ERR("HTTP DELETE request in progress, message dropped");
920 result = BLUETOOTH_ERROR_INTERNAL;
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;
935 g_object_ref (hps_soup_msg);
936 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, addr);
938 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, NULL);
940 https_status = soup_message_get_https_status (hps_soup_msg, &cert, &flags);
942 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1);
944 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
947 BT_ERR("HTTPS GET request in progress, message dropped");
948 result = BLUETOOTH_ERROR_INTERNAL;
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;
963 g_object_ref (hps_soup_msg);
964 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, addr);
966 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, NULL);
968 https_status = soup_message_get_https_status (hps_soup_msg, &cert, &flags);
970 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1);
972 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
975 BT_ERR("HTTPS HEAD request in progress, message dropped");
976 result = BLUETOOTH_ERROR_INTERNAL;
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;
990 soup_message_set_request (hps_soup_msg, "text/xml", SOUP_MEMORY_STATIC,
991 g_entity, strlen (g_entity));
993 g_object_ref (hps_soup_msg);
994 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
996 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
999 https_status = soup_message_get_https_status (hps_soup_msg, &cert, &flags);
1001 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1);
1003 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
1006 BT_ERR("HTTPS POST request in progress, message dropped");
1007 result = BLUETOOTH_ERROR_INTERNAL;
1011 case HTTPS_PUT_REQUEST:
1012 if(req_state == HTTP_REQ_STATE_EXECUTED) {
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;
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);
1026 g_object_ref (hps_soup_msg);
1027 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
1029 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
1031 https_status = soup_message_get_https_status (hps_soup_msg, &cert, &flags);
1033 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1);
1035 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
1038 BT_ERR("HTTPS PUT request in progress, message dropped");
1039 result = BLUETOOTH_ERROR_INTERNAL;
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;
1054 g_object_ref (hps_soup_msg);
1055 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
1057 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
1060 https_status = soup_message_get_https_status (hps_soup_msg, &cert, &flags);
1062 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1);
1064 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
1067 BT_ERR("HTTPS DELETE request in progress, message dropped");
1068 result = BLUETOOTH_ERROR_INTERNAL;
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;
1082 soup_session_cancel_message (hps_soup_session, hps_soup_msg, SOUP_STATUS_CANCELLED);
1083 hps_soup_msg = NULL;
1088 BT_ERR("Unknown opcode %0x", opcode);
1089 result = BLUETOOTH_ERROR_INTERNAL;
1096 void _bt_hps_security_read_cb (char *value, int len)
1098 BT_INFO("HPS Client Read the value");
1103 void _bt_hps_gatt_char_property_changed_event(GVariant *msg,
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);
1115 while ((g_variant_iter_loop(&value_iter, "{sv}", &property, &var))) {
1117 if(property == NULL) {
1118 BT_ERR("Property NULL");
1122 if (!g_strcmp0(property, "WriteValue")) {
1124 BT_INFO("WriteValue");
1125 BT_INFO("Type '%s'\n", g_variant_get_type_string (var));
1132 g_variant_get(var, "(&s&s&syq@ay)", &char_path,
1133 &svc_handle, &addr, &req_id, &offset, &val);
1135 len = g_variant_get_size(val);
1137 BT_DBG("Len = %d", len);
1139 value = (char *) g_variant_get_data(val);
1142 if(!g_strcmp0(char_path, http_uri_obj_path)) {
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);
1154 BT_ERR("Wrong Object Path %s", char_path);
1155 result = BLUETOOTH_ERROR_INTERNAL;
1157 bluetooth_gatt_send_response(req_id, BLUETOOTH_GATT_ATT_REQUEST_TYPE_WRITE, result, 0, NULL, 0);
1159 BT_ERR("Array Len 0");
1162 BT_ERR("var==NULL");
1164 } else if (!g_strcmp0(property, "ReadValue")) {
1170 int data_status = -1;
1171 BT_INFO("ReadValue");
1172 BT_INFO("Type '%s'\n", g_variant_get_type_string (var));
1174 g_variant_get(var, "(&s&s&syq)", &char_path, &svc_handle,
1175 &addr, &req_id, &offset);
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);
1189 if (data_status == DS_BODY_RECEIVED ||
1190 data_status == DS_HEADER_RECEIVED) {
1191 _bt_hps_set_char_value(char_path, NULL, 0);
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);
1206 void _bt_hps_gatt_char_property_changed_event(GVariant *msg,
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);
1218 while ((g_variant_iter_loop(&value_iter, "{sv}", &property, &val))) {
1220 if(property == NULL) {
1221 BT_ERR("Property NULL");
1225 if (strcasecmp(property, "ChangedValue") == 0) {
1228 GByteArray *gp_byte_array = NULL;
1229 BT_INFO("Type '%s'\n", g_variant_get_type_string (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,
1244 param = g_variant_new("(is@ay)", result, char_handle,
1247 if(strcmp(path, http_uri_obj_path)) {
1249 _bt_hps_uri_write_cb(NULL, len);
1250 } else if(strcmp(path, http_hdr_obj_path)) {
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);
1261 BT_ERR("Wrong Object Path %s", path);
1264 BT_ERR("Array Len 0");
1266 g_byte_array_free(gp_byte_array, TRUE);
1268 BT_ERR("val==NULL");
1272 g_free(char_handle);
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,
1288 if (signal_name == NULL) {
1289 BT_ERR("Wrong Signal");
1294 if (g_strcmp0(signal_name, PROPERTIES_CHANGED) == 0) {
1296 g_variant_get(parameters, "(@a{sv}@as)", &value, NULL);
1298 _bt_hps_gatt_char_property_changed_event(value, object_path);
1300 if (g_strcmp0(interface_name, BT_HPS_PROPERTIES_INTERFACE) == 0) {
1302 g_variant_get(parameters, "(&s@a{sv}@as)", &interface_name, &value, NULL);
1304 _bt_hps_gatt_char_property_changed_event(value, object_path);
1307 //BT_ERR("Wrong Interface %s", interface_name);
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,
1322 int result = BLUETOOTH_ERROR_NONE;
1325 if (signal_name == NULL) {
1326 BT_ERR("Wrong Signal");
1330 BT_INFO("Interface %s, Signal %s", interface_name, signal_name);
1332 if (g_strcmp0(interface_name, BT_HPS_INTERFACE_NAME) == 0) {
1334 g_variant_get(parameters, "(&s@a{sv}@as)", &interface_name, &value, NULL);
1336 if (strcasecmp(signal_name, BLE_ENABLED) == 0) {
1337 g_variant_get(parameters, "(i)", &result);
1339 if (_bt_hps_prepare_httpproxy() != BLUETOOTH_ERROR_NONE) {
1340 BT_ERR("Fail to prepare HTTP Proxy");
1344 if (_bt_hps_set_advertising_data() != BLUETOOTH_ERROR_NONE) {
1345 BT_ERR("Fail to set advertising data");
1350 BT_ERR("Wrong Signal %s", signal_name);
1357 int _bt_hps_init_event_receiver()
1359 GError *error = 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);
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,
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,
1386 void _bt_hps_deinit_event_receiver(void)
1389 g_dbus_connection_signal_unsubscribe(conn, property_sub_id);
1390 g_dbus_connection_signal_unsubscribe(conn, adapter_sub_id);
1395 int _bt_hps_set_advertising_data(void)
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;
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);
1412 ret = bluetooth_set_advertising(0, TRUE);
1413 if(ret != BLUETOOTH_ERROR_NONE) {
1414 BT_ERR("Failed to set ADV %d", ret);
1421 int _bt_hps_prepare_httpproxy(void)
1423 int ret = BLUETOOTH_ERROR_NONE;
1427 bt_gatt_characteristic_property_t props;
1429 char value[MAX_URI_LENGTH] = { 0 };
1430 struct hps_char_info *char_info = NULL;
1432 char status[3] = { 0 };
1437 ret = bluetooth_gatt_init();
1438 if(ret != BLUETOOTH_ERROR_NONE) {
1439 BT_ERR("Failed to Init GATT %d", ret);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
1597 ret = bluetooth_gatt_register_service(hps_obj_path);
1598 if(ret != BLUETOOTH_ERROR_NONE) {
1599 BT_ERR("Failed to register service %d", ret);
1607 delete_all_characterisitc();
1608 delete_all_notify_read_status();
1614 static void _bt_hps_sig_handler(int sig)
1620 BT_DBG("caught signal - sigterm\n");
1623 BT_DBG("caught signal - sigint\n");
1626 BT_DBG("caught signal - sigkill\n");
1629 BT_DBG("caught signal %d and ignored\n",sig);
1634 void _bt_hps_exit(void)
1644 if(g_header != NULL) {
1649 if(g_entity != NULL) {
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);
1659 delete_all_characterisitc();
1662 ret = bluetooth_gatt_deinit();
1663 if(ret != BLUETOOTH_ERROR_NONE) {
1664 BT_ERR("Failed to Deinit GATT %d", ret);
1667 ret = bluetooth_unregister_callback();
1668 if(ret != BLUETOOTH_ERROR_NONE) {
1669 BT_ERR("Failed to Unregister callback %d", ret);
1672 _bt_hps_deinit_event_receiver();
1674 _bt_hps_unregister_interface();
1676 if (main_loop != NULL) {
1677 g_main_loop_quit(main_loop);
1681 void bt_hps_event_callback(int event, bluetooth_event_param_t* param,
1684 BT_DBG("HPS event %d", event);
1688 /* HTTP Proxy Service Main loop */
1691 struct sigaction sa;
1693 BT_ERR("Starting the bt-httpproxy daemon");
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
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;
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);
1711 // g_type_init is deprecated glib 2.36 onwards, current version id 2.15
1715 if(bluetooth_register_callback(bt_hps_event_callback, NULL) != BLUETOOTH_ERROR_NONE) {
1716 BT_ERR("bluetooth_register_callback returned failiure");
1721 if (_bt_hps_register_interface() != BLUETOOTH_ERROR_NONE) {
1722 BT_ERR("Fail to register http proxy service");
1726 if (_bt_hps_init_event_receiver() != BLUETOOTH_ERROR_NONE) {
1727 BT_ERR("Fail to init event reciever");
1731 hps_soup_session = soup_session_async_new();
1732 if (hps_soup_session == NULL) {
1733 BT_ERR("Failed to soup_session_async_new");
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,
1746 main_loop = g_main_loop_new(NULL, FALSE);
1748 g_main_loop_run(main_loop);
1750 BT_DBG("g_main_loop_quit called!");
1752 if (main_loop != NULL) {
1753 g_main_loop_unref(main_loop);