2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
23 #include "bt-httpproxy.h"
24 #include "bluetooth-api.h"
26 #include <libsoup/soup.h>
28 #ifdef TIZEN_FEATURE_BT_HPS
31 #define LOG_TAG "BLUETOOTH_HPS"
33 #define BT_INFO(fmt, arg...) SLOGI(fmt, ##arg)
34 #define BT_ERR(fmt, arg...) SLOGE(fmt, ##arg)
35 #define BT_DBG(fmt, arg...) SLOGD(fmt, ##arg)
37 char *hps_obj_path = NULL;
38 char *http_uri_obj_path = NULL;
39 char *http_hdr_obj_path = NULL;
40 char *http_entity_obj_path = NULL;
41 char *http_cp_obj_path = NULL;
42 char *http_status_obj_path = NULL;
43 char *http_status_desc_obj_path = NULL;
44 char *http_security_obj_path = NULL;
46 static GMainLoop *main_loop;
47 static int property_sub_id = -1;
48 static int adapter_sub_id = -1;
49 static http_request_state req_state;
52 struct hps_notify_read_info {
59 struct hps_char_info {
65 static GSList *hps_notify_read_list = NULL;
66 static GSList *hps_char_list = NULL;
69 static GDBusConnection *conn;
70 static GDBusConnection *g_conn;
71 static guint g_owner_id = 0;
72 GDBusNodeInfo *hps_node_info = NULL;
75 char *g_header = NULL;
76 char *g_entity = NULL;
78 static SoupSession *hps_soup_session = NULL;
79 static SoupMessage *hps_soup_msg = NULL;
82 static const gchar hps_introspection_xml[] =
84 " <interface name='org.projectx.httpproxy_service'>"
85 " <method name='enable'>"
86 " <arg type='y' name='status' direction='out'/>"
88 " <method name='disable'>"
89 " <arg type='y' name='status' direction='out'/>"
95 static void _bt_hps_set_char_value(const char *obj_path, const char* value, int value_length, int offset);
97 static void _hps_convert_address_to_hex(bluetooth_device_address_t *addr_hex, const char *addr_str)
99 char *ptr1, *ptr2, *ptr3, *ptr4, *ptr5;
101 if (addr_str == NULL || addr_str[0] == '\0')
104 addr_hex->addr[0] = strtol(addr_str, &ptr5, 16);
105 addr_hex->addr[1] = strtol(ptr5 + 1, &ptr4, 16);
106 addr_hex->addr[2] = strtol(ptr4 + 1, &ptr3, 16);
107 addr_hex->addr[3] = strtol(ptr3 + 1, &ptr2, 16);
108 addr_hex->addr[4] = strtol(ptr2 + 1, &ptr1, 16);
109 addr_hex->addr[5] = strtol(ptr1 + 1, NULL, 16);
112 static char *__hps_convert_uuid_to_uuid128(const char *uuid)
122 uuid128 = g_strdup_printf("0000%s-0000-1000-8000-00805F9B34FB", uuid);
127 uuid128 = g_strdup_printf("%s-0000-1000-8000-00805F9B34FB", uuid);
132 uuid128 = strdup(uuid);
142 static void _bt_hps_send_status_notification(unsigned short http_status,
143 unsigned char data_status,
144 bluetooth_device_address_t *unicast_address)
146 char status[3] = {0x00};
147 int ret = BLUETOOTH_ERROR_NONE;
151 status[0] = http_status & 0xFF;
152 status[1] = (http_status >> 8) & 0xFF;
153 status[2] = data_status;
154 BT_DBG("Status %d %04x", http_status, http_status);
156 /* Store the status value */
157 _bt_hps_set_char_value(http_status_obj_path, status, 3, 0);
159 /* Send unicast notification */
160 ret = bluetooth_gatt_server_set_notification(http_status_obj_path, unicast_address);
161 if (ret != BLUETOOTH_ERROR_NONE) {
162 BT_ERR("_bt_hps_send_status_notification failed");
165 ret = bluetooth_gatt_update_characteristic(http_status_obj_path, status, 3);
166 if (ret != BLUETOOTH_ERROR_NONE) {
167 BT_ERR("_bt_hps_send_status_notification failed");
173 static void _bt_httpproxy_method(GDBusConnection *connection,
175 const gchar *object_path,
176 const gchar *interface_name,
177 const gchar *method_name,
178 GVariant *parameters,
179 GDBusMethodInvocation *invocation,
184 BT_DBG("Method[%s] Object Path[%s] Interface Name[%s]",
185 method_name, object_path, interface_name);
187 if (g_strcmp0(method_name, "enable") == 0) {
188 g_dbus_method_invocation_return_value(invocation, g_variant_new("(y)", status));
189 } else if (g_strcmp0(method_name, "disable") == 0) {
191 g_dbus_method_invocation_return_value(invocation, g_variant_new("(y)", status));
197 static const GDBusInterfaceVTable hps_method_table = {
198 _bt_httpproxy_method,
203 static void _bt_hps_on_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
206 GError *error = NULL;
212 object_id = g_dbus_connection_register_object(connection, BT_HPS_OBJECT_PATH,
213 hps_node_info->interfaces[0],
216 if (object_id == 0) {
217 BT_ERR("Failed to register method table: %s", error->message);
219 g_dbus_node_info_unref(hps_node_info);
225 static void _bt_hps_on_name_acquired(GDBusConnection *connection,
233 static void _bt_hps_on_name_lost(GDBusConnection *connection,
238 g_object_unref(g_conn);
240 g_dbus_node_info_unref(hps_node_info);
241 g_bus_unown_name(g_owner_id);
246 int _bt_hps_register_interface(void)
248 GError *error = NULL;
253 hps_node_info = g_dbus_node_info_new_for_xml(hps_introspection_xml, &error);
254 if (!hps_node_info) {
255 BT_ERR("Failed to install: %s", error->message);
256 return BLUETOOTH_ERROR_INTERNAL;
259 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
261 G_BUS_NAME_OWNER_FLAGS_NONE,
262 _bt_hps_on_bus_acquired, _bt_hps_on_name_acquired, _bt_hps_on_name_lost,
264 g_owner_id = owner_id;
265 BT_DBG("owner_id is [%d]\n", owner_id);
267 return BLUETOOTH_ERROR_NONE;
270 void _bt_hps_unregister_interface(void)
274 g_object_unref(g_conn);
276 g_dbus_node_info_unref(hps_node_info);
277 g_bus_unown_name(g_owner_id);
283 static struct hps_char_info *hps_get_char_value(const char *path)
287 for (tmp = hps_char_list; tmp != NULL; tmp = tmp->next) {
289 struct hps_char_info *char_info = tmp->data;
290 if (!g_strcmp0(char_info->char_path, path))
297 static int char_info_cmp(gconstpointer a1, gconstpointer a2)
299 const struct hps_char_info *attrib1 = a1;
300 const struct hps_char_info *attrib2 = a2;
302 return g_strcmp0(attrib1->char_path, attrib2->char_path);
305 static int notify_info_cmp(gconstpointer a1, gconstpointer a2)
307 const struct hps_notify_read_info *attrib1 = a1;
308 const struct hps_notify_read_info *attrib2 = a2;
310 return g_strcmp0(attrib1->char_path, attrib2->char_path);
313 static void _bt_hps_set_char_value(const char *obj_path, const char* value, int value_length, int offset)
319 for (tmp = hps_char_list; tmp != NULL; tmp = tmp->next) {
321 struct hps_char_info *char_info = tmp->data;
322 if (!g_strcmp0(char_info->char_path, obj_path)) {
325 str = g_strdup(char_info->char_value);
326 char_info->char_value = g_try_realloc(char_info->char_value, offset + value_length);
328 char_info->char_value = g_try_realloc(char_info->char_value, value_length);
330 if (char_info->char_value) {
332 memcpy(char_info->char_value, str, strlen(str));
335 memcpy(&char_info->char_value[offset], value, value_length);
336 char_info->value_length = offset + value_length;
338 memcpy(char_info->char_value, value, value_length);
339 char_info->value_length = value_length;
341 hps_char_list = g_slist_insert_sorted(hps_char_list,
342 char_info, char_info_cmp);
352 static void _bt_hps_set_notify_read_status(const char *obj_path,
353 guint offset_status, guint read_status, int https_status)
355 struct hps_notify_read_info *notify_read_info = NULL;
358 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
360 notify_read_info = tmp->data;
361 if (!g_strcmp0(notify_read_info->char_path, obj_path)) {
362 notify_read_info->read_status = read_status;
363 notify_read_info->offset_status = offset_status;
364 notify_read_info->https_status = https_status;
365 hps_notify_read_list = g_slist_insert_sorted(hps_notify_read_list,
366 notify_read_info, notify_info_cmp);
372 if (!hps_notify_read_list) {
373 /* Store Notification information */
374 notify_read_info = g_new0(struct hps_notify_read_info, 1);
375 if (notify_read_info) {
376 notify_read_info->char_path = g_strdup(obj_path);
377 notify_read_info->read_status = read_status;
378 notify_read_info->offset_status = offset_status;
379 notify_read_info->https_status = https_status;
380 hps_notify_read_list = g_slist_append(hps_notify_read_list, notify_read_info);
384 /* Store Notification information */
385 notify_read_info = g_new0(struct hps_notify_read_info, 1);
386 if (notify_read_info) {
387 notify_read_info->char_path = g_strdup(obj_path);
388 notify_read_info->read_status = read_status;
389 notify_read_info->offset_status = offset_status;
390 notify_read_info->https_status = https_status;
391 hps_notify_read_list = g_slist_append(hps_notify_read_list, notify_read_info);
397 static struct hps_notify_read_info *_bt_hps_get_notify_read_status(const char *obj_path)
401 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
403 struct hps_notify_read_info *notify_read_info = tmp->data;
404 if (!g_strcmp0(notify_read_info->char_path, obj_path))
405 return notify_read_info;
412 static void delete_all_characterisitc(void)
415 for (tmp = hps_char_list; tmp != NULL; tmp = tmp->next) {
417 struct hps_char_info *char_info = tmp->data;
418 if (char_info->char_path)
419 g_free(char_info->char_path);
420 if (char_info->char_value)
421 g_free(char_info->char_value);
422 hps_char_list = g_slist_delete_link(hps_char_list, tmp->data);
425 g_slist_free(hps_char_list);
426 hps_char_list = NULL;
429 static void delete_all_notify_read_status(void)
432 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
434 struct hps_notify_read_info *notify_read_info = tmp->data;
435 if (notify_read_info->char_path)
436 g_free(notify_read_info->char_path);
437 hps_notify_read_list = g_slist_delete_link(hps_notify_read_list, tmp->data);
440 g_slist_free(hps_notify_read_list);
441 hps_notify_read_list = NULL;
444 static void delete_notify_read_status(const char *obj_path)
447 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
449 struct hps_notify_read_info *notify_read_info = tmp->data;
450 if (!g_strcmp0(notify_read_info->char_path, obj_path)) {
451 if (notify_read_info->char_path)
452 g_free(notify_read_info->char_path);
453 hps_notify_read_list = g_slist_delete_link(hps_notify_read_list, tmp->data);
461 int _bt_hps_uri_write_cb(char *uri, int len, int offset)
463 if ((len < 1) || (len > MAX_URI_LENGTH)) {
464 BT_ERR("Wrong URI length %d", len);
465 return BLUETOOTH_ERROR_INTERNAL;
468 /* g_uri will be used commonly for all HTTP methods whereever applicable */
471 g_uri = g_strndup(uri, len);
473 _bt_hps_set_char_value(http_uri_obj_path, g_uri, len, offset);
475 return BLUETOOTH_ERROR_NONE;
478 int _bt_hps_http_header_write_cb(char *header, int len, int offset)
480 if ((len < 1) || (len > MAX_HEADER_LENGTH)) {
481 BT_ERR("Wrong Header length %d", len);
482 return BLUETOOTH_ERROR_INTERNAL;
485 /* g_header will be used commonly for all HTTP methods where ever applicable
486 general-header, request-header, entity-header
490 g_header = g_strndup(header, len);
492 _bt_hps_set_char_value(http_hdr_obj_path, g_header, len, offset);
495 return BLUETOOTH_ERROR_NONE;
498 int _bt_hps_entity_body_write_cb(char *entity, int len, int offset)
500 if ((len < 1) || (len > MAX_ENTITY_LENGTH)) {
501 BT_ERR("Wrong Entity length %d", len);
502 return BLUETOOTH_ERROR_INTERNAL;
505 /* g_entity will be used commonly for all HTTP methods whereever applicable */
508 g_entity = g_strndup(entity, len);
510 _bt_hps_set_char_value(http_entity_obj_path, g_entity, len, offset);
513 return BLUETOOTH_ERROR_NONE;
517 int _bt_hps_read_cb(const char *obj_path, char **value, int *len)
519 struct hps_char_info *info = NULL;
520 struct hps_notify_read_info *notify_read_info = NULL;
521 guint data_status = -1;
523 gboolean is_header = FALSE;
526 BT_ERR("Wrong Obj path");
530 if (!g_strcmp0(http_hdr_obj_path, obj_path))
533 info = hps_get_char_value(obj_path);
536 if (info->char_value == NULL || info->value_length == 0)
539 notify_read_info = _bt_hps_get_notify_read_status(obj_path);
540 if (notify_read_info && notify_read_info->read_status != DS_BODY_RECEIVED &&
541 notify_read_info->read_status != DS_HEADER_RECEIVED) {
542 offset = notify_read_info->offset_status;
543 if ((info->value_length - offset) > 0 &&
544 (info->value_length - offset) > MAX_ENTITY_LENGTH) {
546 data_status = DS_HEADER_TRUNCATED;
548 data_status = DS_BODY_TRUNCATED;
549 _bt_hps_set_notify_read_status(obj_path, offset + MAX_ENTITY_LENGTH,
550 data_status, notify_read_info->https_status);
551 *value = g_strdup(&info->char_value[offset]);
552 *len = MAX_ENTITY_LENGTH;
553 } else if ((info->value_length - offset) > 0 &&
554 (info->value_length - offset) <= MAX_ENTITY_LENGTH) {
556 data_status = DS_HEADER_RECEIVED;
558 data_status = DS_BODY_RECEIVED;
559 _bt_hps_set_notify_read_status(obj_path, offset, data_status, notify_read_info->https_status);
560 *value = g_strdup(&info->char_value[offset]);
561 *len = info->value_length - offset;
563 } else if (notify_read_info && (notify_read_info->read_status == DS_BODY_RECEIVED ||
564 notify_read_info->read_status == DS_HEADER_RECEIVED)) {
566 data_status = DS_HEADER_RECEIVED;
568 data_status = DS_BODY_RECEIVED;
569 delete_notify_read_status(obj_path);
570 *value = g_strdup(&info->char_value[offset]);
571 *len = info->value_length;
579 void _bt_hps_head_response_cb(SoupSession *session,
580 SoupMessage *msg, gpointer user_data)
582 unsigned short http_status = 0x00;
584 unsigned char status[3] = {0x00};
586 const char *device_address = user_data;
587 bluetooth_device_address_t addr_hex = { {0,} };
588 unsigned char data_status = DS_NONE;
589 _hps_convert_address_to_hex(&addr_hex, device_address);
592 if (hps_soup_session != session) {
593 BT_ERR("Wrong Session");
598 BT_ERR("Wrong Message");
603 req_state = HTTP_REQ_STATE_EXECUTED;
605 http_status = msg->status_code;
607 // Process Header in Response Body
608 if (msg->response_headers) {
610 const char *content = NULL;
611 const char *length = NULL;
614 length = soup_message_headers_get_one(msg->request_headers,
616 // Check "Content-MD5" is the right name to get header content
617 content = soup_message_headers_get_one(msg->response_headers,
619 if (content == NULL || length == NULL) {
620 BT_ERR("Wrong Response Header");
621 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
625 hdr_len = soup_message_headers_get_content_length(msg->response_headers);
627 // Write Data to Header Characteristic
629 _bt_hps_set_char_value(http_hdr_obj_path, content, hdr_len, 0);
631 bluetooth_gatt_set_characteristic_value(http_hdr_obj_path, content, hdr_len);
633 // TODO : Handle Truncated Header
635 // Write Data to Status Code Characteristic
637 data_status = (hdr_len > MAX_ENTITY_LENGTH) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
639 if (data_status == DS_BODY_TRUNCATED && SOUP_STATUS_IS_SUCCESSFUL(http_status))
640 _bt_hps_set_notify_read_status(http_hdr_obj_path, 0, data_status, http_status);
642 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
644 status[0] = http_status & 0x0F;
645 status[1] = (http_status >> 8) & 0x0F;
646 status[2] = (hdr_len > MAX_HEADER_LENGTH) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
648 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
651 BT_ERR("HEAD Response is NULL");
652 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
658 void _bt_hps_http_response_cb(SoupSession *session,
659 SoupMessage *msg, gpointer user_data)
661 unsigned short http_status = 0x00;
663 unsigned char status[3] = {0x00};
665 const char *device_address = user_data;
666 bluetooth_device_address_t addr_hex = { {0,} };
667 unsigned char data_status = DS_NONE;
668 _hps_convert_address_to_hex(&addr_hex, device_address);
671 if (hps_soup_session != session) {
672 BT_ERR("Wrong Session");
677 BT_ERR("Wrong Message");
683 req_state = HTTP_REQ_STATE_EXECUTED;
685 http_status = msg->status_code;
687 // Write Data to Status Code Characteristic
689 status[0] = http_status & 0x0F;
690 status[1] = (http_status >> 8) & 0x0F;
691 status[2] = DS_HEADER_RECEIVED;
692 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
694 data_status = DS_HEADER_RECEIVED;
695 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
701 void _bt_hps_get_response_cb(SoupSession *session,
702 SoupMessage *msg, gpointer user_data)
704 SoupBuffer *body = NULL;
705 unsigned short http_status = 0x00;
707 unsigned char status[3] = {0x00};
709 const char *device_address = user_data;
710 bluetooth_device_address_t addr_hex = { {0,} };
711 unsigned char data_status = DS_NONE;
712 _hps_convert_address_to_hex(&addr_hex, device_address);
715 if (hps_soup_session != session) {
716 BT_ERR("Wrong Session");
721 BT_ERR("Wrong Message");
727 req_state = HTTP_REQ_STATE_EXECUTED;
729 http_status = msg->status_code;
731 // Process Entity Body in Response Message
732 if (msg->response_body) {
734 body = soup_message_body_flatten(msg->response_body);
736 BT_ERR("Wrong Response Body");
738 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
742 if (body->data == NULL || body->length <= 0) {
743 BT_ERR("Wrong Response");
744 soup_buffer_free(body);
746 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
750 // Write Data to Entity Body Characteristic
752 _bt_hps_set_char_value(http_entity_obj_path, body->data, body->length, 0);
754 bluetooth_gatt_set_characteristic_value(http_entity_obj_path, body->data, body->length);
756 // TODO : Handle Truncated Entiry Body
758 // Write Data to Status Code Characteristic
760 data_status = (body->length > MAX_ENTITY_LENGTH) ? DS_BODY_TRUNCATED : DS_BODY_RECEIVED;
762 if (data_status == DS_BODY_TRUNCATED && SOUP_STATUS_IS_SUCCESSFUL(http_status))
763 _bt_hps_set_notify_read_status(http_entity_obj_path, 0, data_status, http_status);
765 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
768 status[0] = http_status & 0x0F;
769 status[1] = (http_status >> 8) & 0x0F;
770 status[2] = (body->length > MAX_HEADER_LENGTH) ? DS_BODY_TRUNCATED : DS_BODY_TRUNCATED;
772 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
774 soup_buffer_free(body);
776 BT_ERR("GET Response Body is NULL");
778 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
782 // Process Header in Response Body
783 if (msg->response_headers) {
785 const char *content = NULL;
786 const char *length = NULL;
789 length = soup_message_headers_get_one(msg->request_headers,
791 // Check "Content-MD5" is the right name to get header content
792 content = soup_message_headers_get_one(msg->response_headers,
794 if (content == NULL || length == NULL) {
795 BT_ERR("Wrong Response Header");
796 data_status = DS_NONE;
797 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
801 hdr_len = soup_message_headers_get_content_length(msg->response_headers);
802 // Write Data to Header Characteristic
804 _bt_hps_set_char_value(http_hdr_obj_path, content, hdr_len, 0);
806 bluetooth_gatt_set_characteristic_value(http_hdr_obj_path, content, hdr_len);
808 // TODO : Handle Truncated Header
810 // Write Data to Status Code Characteristic
812 data_status = (hdr_len > MAX_HEADER_LENGTH) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
814 if (data_status == DS_HEADER_TRUNCATED && SOUP_STATUS_IS_SUCCESSFUL(http_status))
815 _bt_hps_set_notify_read_status(http_hdr_obj_path, 0, data_status, http_status);
817 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
819 status[0] = http_status & 0x0F;
820 status[1] = (http_status >> 8) & 0x0F;
821 status[2] = (hdr_len > MAX_HEADER_LENGTH) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
823 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
826 BT_ERR("GET Response Header is NULL");
828 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
836 int _bt_hps_control_point_write_cb(const char *value, int len, char *addr)
838 int _bt_hps_control_point_write_cb(char *value, int len)
842 GTlsCertificate *cert = NULL;
843 GTlsCertificateFlags flags;
844 gboolean https_status = FALSE;
845 int result = BLUETOOTH_ERROR_NONE;
846 BT_INFO("Opcode %0x", opcode);
849 _bt_hps_set_char_value(http_cp_obj_path, value, len, 0);
853 case HTTP_GET_REQUEST:
854 if (req_state == HTTP_REQ_STATE_EXECUTED) {
855 req_state = HTTP_REQ_STATE_INPROGRESS;
856 hps_soup_msg = soup_message_new("GET", g_uri);
858 g_object_ref(hps_soup_msg);
859 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, addr);
861 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, NULL);
864 BT_ERR("HTTP GET request in progress, message dropped");
865 result = BLUETOOTH_ERROR_INTERNAL;
869 case HTTP_POST_REQUEST:
870 if (req_state == HTTP_REQ_STATE_EXECUTED) {
871 req_state = HTTP_REQ_STATE_INPROGRESS;
872 hps_soup_msg = soup_message_new("POST", g_uri);
873 if (hps_soup_msg == NULL || g_entity == NULL) {
874 BT_ERR("Soup Message NULL");
875 result = BLUETOOTH_ERROR_INTERNAL;
876 req_state = HTTP_REQ_STATE_EXECUTED;
879 soup_message_set_request(hps_soup_msg, "text/xml", SOUP_MEMORY_COPY,
880 g_entity, strlen(g_entity));
882 g_object_ref(hps_soup_msg);
883 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
885 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
888 BT_ERR("HTTP POST request in progress, message dropped");
889 result = BLUETOOTH_ERROR_INTERNAL;
893 case HTTP_HEAD_REQUEST:
894 if (req_state == HTTP_REQ_STATE_EXECUTED) {
895 req_state = HTTP_REQ_STATE_INPROGRESS;
896 hps_soup_msg = soup_message_new("HEAD", g_uri);
897 if (hps_soup_msg == NULL) {
898 BT_ERR("Soup Message NULL");
899 result = BLUETOOTH_ERROR_INTERNAL;
900 req_state = HTTP_REQ_STATE_EXECUTED;
904 g_object_ref(hps_soup_msg);
905 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, addr);
907 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, NULL);
910 BT_ERR("HTTP HEAD request in progress, message dropped");
911 result = BLUETOOTH_ERROR_INTERNAL;
915 case HTTP_PUT_REQUEST:
916 if (req_state == HTTP_REQ_STATE_EXECUTED) {
918 req_state = HTTP_REQ_STATE_INPROGRESS;
919 hps_soup_msg = soup_message_new("PUT", g_uri);
920 if (hps_soup_msg == NULL || g_entity == NULL) {
921 BT_ERR("Soup Message NULL");
922 result = BLUETOOTH_ERROR_INTERNAL;
923 req_state = HTTP_REQ_STATE_EXECUTED;
926 buf = soup_buffer_new(SOUP_MEMORY_TAKE, g_entity, strlen(g_entity));
927 soup_message_body_append_buffer(hps_soup_msg->request_body, buf);
928 soup_message_body_set_accumulate(hps_soup_msg->request_body, FALSE);
930 g_object_ref(hps_soup_msg);
931 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
933 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
937 BT_ERR("HTTP PUT request in progress, message dropped");
938 result = BLUETOOTH_ERROR_INTERNAL;
942 case HTTP_DELETE_REQUEST:
943 if (req_state == HTTP_REQ_STATE_EXECUTED) {
944 req_state = HTTP_REQ_STATE_INPROGRESS;
945 hps_soup_msg = soup_message_new("DELETE", g_uri);
946 if (hps_soup_msg == NULL) {
947 BT_ERR("Soup Message NULL");
948 result = BLUETOOTH_ERROR_INTERNAL;
949 req_state = HTTP_REQ_STATE_EXECUTED;
953 g_object_ref(hps_soup_msg);
954 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
956 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
959 BT_ERR("HTTP DELETE request in progress, message dropped");
960 result = BLUETOOTH_ERROR_INTERNAL;
964 case HTTPS_GET_REQUEST:
965 if (req_state == HTTP_REQ_STATE_EXECUTED) {
966 req_state = HTTP_REQ_STATE_INPROGRESS;
967 hps_soup_msg = soup_message_new("GET", g_uri);
968 if (hps_soup_msg == NULL) {
969 BT_ERR("Soup Message NULL");
970 result = BLUETOOTH_ERROR_INTERNAL;
971 req_state = HTTP_REQ_STATE_EXECUTED;
975 g_object_ref(hps_soup_msg);
976 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, addr);
978 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, NULL);
980 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
982 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1, 0);
984 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
987 BT_ERR("HTTPS GET request in progress, message dropped");
988 result = BLUETOOTH_ERROR_INTERNAL;
992 case HTTPS_HEAD_REQUEST:
993 if (req_state == HTTP_REQ_STATE_EXECUTED) {
994 req_state = HTTP_REQ_STATE_INPROGRESS;
995 hps_soup_msg = soup_message_new("HEAD", g_uri);
996 if (hps_soup_msg == NULL) {
997 BT_ERR("Soup Message NULL");
998 result = BLUETOOTH_ERROR_INTERNAL;
999 req_state = HTTP_REQ_STATE_EXECUTED;
1003 g_object_ref(hps_soup_msg);
1004 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, addr);
1006 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, NULL);
1008 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
1010 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1, 0);
1012 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
1015 BT_ERR("HTTPS HEAD request in progress, message dropped");
1016 result = BLUETOOTH_ERROR_INTERNAL;
1020 case HTTPS_POST_REQUEST:
1021 if (req_state == HTTP_REQ_STATE_EXECUTED) {
1022 req_state = HTTP_REQ_STATE_INPROGRESS;
1023 hps_soup_msg = soup_message_new("POST", g_uri);
1024 if (hps_soup_msg == NULL) {
1025 BT_ERR("Soup Message NULL");
1026 result = BLUETOOTH_ERROR_INTERNAL;
1027 req_state = HTTP_REQ_STATE_EXECUTED;
1030 soup_message_set_request(hps_soup_msg, "text/xml", SOUP_MEMORY_STATIC,
1031 g_entity, strlen(g_entity));
1033 g_object_ref(hps_soup_msg);
1034 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
1036 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
1039 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
1041 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1, 0);
1043 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
1046 BT_ERR("HTTPS POST request in progress, message dropped");
1047 result = BLUETOOTH_ERROR_INTERNAL;
1051 case HTTPS_PUT_REQUEST:
1052 if (req_state == HTTP_REQ_STATE_EXECUTED) {
1054 req_state = HTTP_REQ_STATE_INPROGRESS;
1055 hps_soup_msg = soup_message_new("PUT", g_uri);
1056 if (hps_soup_msg == NULL) {
1057 BT_ERR("Soup Message NULL");
1058 result = BLUETOOTH_ERROR_INTERNAL;
1059 req_state = HTTP_REQ_STATE_EXECUTED;
1062 buf = soup_buffer_new(SOUP_MEMORY_TAKE, g_entity, strlen(g_entity));
1063 soup_message_body_append_buffer(hps_soup_msg->request_body, buf);
1064 soup_message_body_set_accumulate(hps_soup_msg->request_body, FALSE);
1066 g_object_ref(hps_soup_msg);
1067 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
1069 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
1071 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
1073 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1, 0);
1075 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
1078 BT_ERR("HTTPS PUT request in progress, message dropped");
1079 result = BLUETOOTH_ERROR_INTERNAL;
1083 case HTTPS_DELETE_REQUEST:
1084 if (req_state == HTTP_REQ_STATE_EXECUTED) {
1085 req_state = HTTP_REQ_STATE_INPROGRESS;
1086 hps_soup_msg = soup_message_new("DELETE", g_uri);
1087 if (hps_soup_msg == NULL) {
1088 BT_ERR("Soup Message NULL");
1089 result = BLUETOOTH_ERROR_INTERNAL;
1090 req_state = HTTP_REQ_STATE_EXECUTED;
1094 g_object_ref(hps_soup_msg);
1095 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
1097 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
1100 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
1102 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1, 0);
1104 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
1107 BT_ERR("HTTPS DELETE request in progress, message dropped");
1108 result = BLUETOOTH_ERROR_INTERNAL;
1112 case HTTP_REQUEST_CANCEL:
1113 /* Cancel the outstanding request */
1114 if (req_state == HTTP_REQ_STATE_INPROGRESS) {
1115 req_state = HTTP_REQ_STATE_IDLE;
1116 if (hps_soup_msg == NULL) {
1117 BT_ERR("Soup Message NULL");
1118 result = BLUETOOTH_ERROR_INTERNAL;
1119 req_state = HTTP_REQ_STATE_EXECUTED;
1122 soup_session_cancel_message(hps_soup_session, hps_soup_msg, SOUP_STATUS_CANCELLED);
1123 hps_soup_msg = NULL;
1128 BT_ERR("Unknown opcode %0x", opcode);
1129 result = BLUETOOTH_ERROR_INTERNAL;
1136 void _bt_hps_security_read_cb(char *value, int len)
1138 BT_INFO("HPS Client Read the value");
1143 void _bt_hps_gatt_char_property_changed_event(GVariant *msg,
1146 int result = BLUETOOTH_ERROR_NONE;
1147 GVariantIter value_iter;
1148 const char *property = NULL;
1149 const char * char_path = NULL;
1150 const char * svc_handle = NULL;
1151 GVariant *var = NULL;
1152 GVariant *val = NULL;
1153 g_variant_iter_init(&value_iter, msg);
1155 while ((g_variant_iter_loop(&value_iter, "{sv}", &property, &var))) {
1157 if (property == NULL) {
1158 BT_ERR("Property NULL");
1162 if (!g_strcmp0(property, "WriteValue")) {
1164 BT_INFO("WriteValue");
1165 BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
1172 g_variant_get(var, "(&s&s&syq@ay)", &char_path,
1173 &svc_handle, &addr, &req_id, &offset, &val);
1175 len = g_variant_get_size(val);
1177 BT_DBG("Len = %d, Offset = %d", len, offset);
1179 value = (char *) g_variant_get_data(val);
1182 if (!g_strcmp0(char_path, http_uri_obj_path)) {
1184 result = _bt_hps_uri_write_cb(value, len, offset);;
1185 } else if (!g_strcmp0(char_path, http_hdr_obj_path)) {
1186 /* Retrive HEADER */
1187 result = _bt_hps_http_header_write_cb(value, len, offset);
1188 } else if (!g_strcmp0(char_path, http_entity_obj_path)) {
1189 /* Retrive ENTITY BODY */
1190 result = _bt_hps_entity_body_write_cb(value, len, offset);
1191 } else if (!g_strcmp0(char_path, http_cp_obj_path)) {
1192 result = _bt_hps_control_point_write_cb(value, len, addr);
1194 BT_ERR("Wrong Object Path %s", char_path);
1195 result = BLUETOOTH_ERROR_INTERNAL;
1197 bluetooth_gatt_send_response(req_id, BLUETOOTH_GATT_ATT_REQUEST_TYPE_WRITE, result, 0, NULL, 0);
1199 BT_ERR("Array Len 0");
1202 BT_ERR("var==NULL");
1204 } else if (!g_strcmp0(property, "ReadValue")) {
1210 int data_status = -1;
1211 BT_INFO("ReadValue");
1212 BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
1214 g_variant_get(var, "(&s&s&syq)", &char_path, &svc_handle,
1215 &addr, &req_id, &offset);
1217 data_status = _bt_hps_read_cb(char_path, &value, &len);
1218 if (data_status >= DS_NONE) {
1219 struct hps_notify_read_info *notify_read_info = NULL;
1220 bluetooth_device_address_t addr_hex = { {0,} };
1221 _hps_convert_address_to_hex(&addr_hex, addr);
1222 bluetooth_gatt_send_response(req_id, BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ,
1223 BLUETOOTH_ERROR_NONE, offset, value, len);
1224 notify_read_info = _bt_hps_get_notify_read_status(char_path);
1225 if (notify_read_info) {
1226 _bt_hps_send_status_notification(notify_read_info->https_status,
1227 data_status, &addr_hex);
1229 if (data_status == DS_BODY_RECEIVED ||
1230 data_status == DS_HEADER_RECEIVED) {
1231 _bt_hps_set_char_value(char_path, NULL, 0, 0);
1237 BT_ERR("ReadValue failed %s", char_path);
1238 bluetooth_gatt_send_response(req_id, BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ,
1239 BLUETOOTH_ERROR_INTERNAL, offset, NULL, 0);
1246 void _bt_hps_gatt_char_property_changed_event(GVariant *msg,
1249 GVariantIter value_iter;
1250 char *property = NULL;
1251 char * char_handle = NULL;
1252 GVariant *val = NULL;
1253 int result = BLUETOOTH_ERROR_NONE;
1254 GVariant *param = NULL;
1255 g_variant_iter_init(&value_iter, msg);
1256 char_handle = g_strdup(path);
1258 while ((g_variant_iter_loop(&value_iter, "{sv}", &property, &val))) {
1260 if (property == NULL) {
1261 BT_ERR("Property NULL");
1265 if (strcasecmp(property, "ChangedValue") == 0) {
1268 GByteArray *gp_byte_array = NULL;
1269 BT_INFO("Type '%s'\n", g_variant_get_type_string(val));
1272 gp_byte_array = g_byte_array_new();
1273 len = g_variant_get_size(val);
1274 BT_DBG("Len = %d", len);
1275 g_byte_array_append(gp_byte_array,
1276 (const guint8 *)g_variant_get_data(val), len);
1277 if (gp_byte_array->len != 0) {
1278 GVariant *byte_array = NULL;
1279 byte_array = g_variant_new_from_data(
1280 G_VARIANT_TYPE_BYTESTRING,
1281 gp_byte_array->data,
1284 param = g_variant_new("(is@ay)", result, char_handle,
1287 if (strcmp(path, http_uri_obj_path)) {
1289 _bt_hps_uri_write_cb(NULL, len);
1290 } else if (strcmp(path, http_hdr_obj_path)) {
1292 _bt_hps_http_header_write_cb(NULL, len);
1293 } else if (strcmp(path, http_entity_obj_path)) {
1294 //Retrive ENTITY BODY
1295 _bt_hps_entity_body_write_cb(NULL, len);
1296 } else if (strcmp(path, http_cp_obj_path)) {
1297 _bt_hps_control_point_write_cb(NULL, len);
1298 } else if (strcmp(path, http_security_obj_path)) {
1299 _bt_hps_security_read_cb(NULL, len);
1301 BT_ERR("Wrong Object Path %s", path);
1304 BT_ERR("Array Len 0");
1306 g_byte_array_free(gp_byte_array, TRUE);
1308 BT_ERR("val==NULL");
1312 g_free(char_handle);
1318 void _bt_hps_property_event_filter(GDBusConnection *connection,
1319 const gchar *sender_name,
1320 const gchar *object_path,
1321 const gchar *interface_name,
1322 const gchar *signal_name,
1323 GVariant *parameters,
1328 if (signal_name == NULL) {
1329 BT_ERR("Wrong Signal");
1334 if (g_strcmp0(signal_name, PROPERTIES_CHANGED) == 0) {
1336 g_variant_get(parameters, "(@a{sv}@as)", &value, NULL);
1338 _bt_hps_gatt_char_property_changed_event(value, object_path);
1340 if (g_strcmp0(interface_name, BT_HPS_PROPERTIES_INTERFACE) == 0) {
1342 g_variant_get(parameters, "(&s@a{sv}@as)", &interface_name, &value, NULL);
1344 _bt_hps_gatt_char_property_changed_event(value, object_path);
1347 //BT_ERR("Wrong Interface %s", interface_name);
1354 void _bt_hps_adapter_event_filter(GDBusConnection *connection,
1355 const gchar *sender_name,
1356 const gchar *object_path,
1357 const gchar *interface_name,
1358 const gchar *signal_name,
1359 GVariant *parameters,
1362 int result = BLUETOOTH_ERROR_NONE;
1365 if (signal_name == NULL) {
1366 BT_ERR("Wrong Signal");
1370 BT_INFO("Interface %s, Signal %s", interface_name, signal_name);
1372 if (g_strcmp0(interface_name, BT_HPS_INTERFACE_NAME) == 0) {
1374 g_variant_get(parameters, "(&s@a{sv}@as)", &interface_name, &value, NULL);
1376 if (strcasecmp(signal_name, BLE_ENABLED) == 0) {
1377 g_variant_get(parameters, "(i)", &result);
1379 if (_bt_hps_prepare_httpproxy() != BLUETOOTH_ERROR_NONE) {
1380 BT_ERR("Fail to prepare HTTP Proxy");
1384 if (_bt_hps_set_advertising_data() != BLUETOOTH_ERROR_NONE) {
1385 BT_ERR("Fail to set advertising data");
1390 BT_ERR("Wrong Signal %s", signal_name);
1397 int _bt_hps_init_event_receiver()
1399 GError *error = NULL;
1404 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
1405 if (error != NULL) {
1406 BT_ERR("ERROR: Can't get on system bus [%s]", error->message);
1407 g_clear_error(&error);
1411 property_sub_id = g_dbus_connection_signal_subscribe(conn,
1412 NULL, BT_HPS_INTERFACE_NAME,
1413 PROPERTIES_CHANGED, BT_HPS_OBJECT_PATH, NULL, 0,
1414 _bt_hps_property_event_filter,
1417 adapter_sub_id = g_dbus_connection_signal_subscribe(conn,
1418 NULL, BT_HPS_INTERFACE_NAME,
1419 BLE_ENABLED, BT_HPS_OBJECT_PATH, NULL, 0,
1420 _bt_hps_adapter_event_filter,
1426 void _bt_hps_deinit_event_receiver(void)
1429 g_dbus_connection_signal_unsubscribe(conn, property_sub_id);
1430 g_dbus_connection_signal_unsubscribe(conn, adapter_sub_id);
1435 int _bt_hps_set_advertising_data(void)
1440 guint8 data[4] = {0x03, 0x02, 0x23, 0x18};
1441 bluetooth_advertising_data_t adv;
1443 BT_DBG("%x %x %x %x", data[0], data[1], data[2], data[3]);
1444 memcpy(adv.data, data, sizeof(data));
1445 ret = bluetooth_set_advertising_data(0, &adv, sizeof(data));
1446 if (ret != BLUETOOTH_ERROR_NONE) {
1447 BT_ERR("Failed to set ADV data %d", ret);
1451 ret = bluetooth_set_advertising(0, TRUE);
1452 if (ret != BLUETOOTH_ERROR_NONE) {
1453 BT_ERR("Failed to set ADV %d", ret);
1460 int _bt_hps_prepare_httpproxy(void)
1462 int ret = BLUETOOTH_ERROR_NONE;
1466 bt_gatt_characteristic_property_t props;
1468 char value[MAX_URI_LENGTH] = { 0 };
1469 struct hps_char_info *char_info = NULL;
1471 char status[3] = { 0 };
1476 ret = bluetooth_gatt_init();
1477 if (ret != BLUETOOTH_ERROR_NONE) {
1478 BT_ERR("Failed to Init GATT %d", ret);
1482 service_uuid = __hps_convert_uuid_to_uuid128(HPS_UUID);
1483 ret = bluetooth_gatt_add_service(service_uuid, &hps_obj_path);
1484 if (ret != BLUETOOTH_ERROR_NONE) {
1485 BT_ERR("Failed to add service %d", ret);
1489 /* Characteristic URI */
1490 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1491 char_uuid = __hps_convert_uuid_to_uuid128(HTTP_URI_UUID);
1492 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_uri_obj_path);
1493 if (ret != BLUETOOTH_ERROR_NONE) {
1494 BT_ERR("Failed to add new char %d", ret);
1499 ret = bluetooth_gatt_set_characteristic_value(http_uri_obj_path, value, MAX_URI_LENGTH);
1500 if (ret != BLUETOOTH_ERROR_NONE) {
1501 BT_ERR("Failed to add new char %d", ret);
1505 /* Store requets information */
1506 char_info = g_new0(struct hps_char_info, 1);
1507 char_info->char_path = g_strdup(http_uri_obj_path);
1508 hps_char_list = g_slist_append(hps_char_list, char_info);
1509 _bt_hps_set_char_value(http_uri_obj_path, value, MAX_URI_LENGTH, 0);
1512 /* Characteristic HTTP Headers */
1513 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1514 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1515 char_uuid = __hps_convert_uuid_to_uuid128(HTTP_HDR_UUID);
1516 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_hdr_obj_path);
1517 if (ret != BLUETOOTH_ERROR_NONE) {
1518 BT_ERR("Failed to add new char %d", ret);
1522 ret = bluetooth_gatt_set_characteristic_value(http_hdr_obj_path, value, MAX_HEADER_LENGTH);
1523 if (ret != BLUETOOTH_ERROR_NONE) {
1524 BT_ERR("Failed to add new char %d", ret);
1528 /* Store Characterisitc information */
1529 char_info = g_new0(struct hps_char_info, 1);
1530 char_info->char_path = g_strdup(http_hdr_obj_path);
1531 hps_char_list = g_slist_append(hps_char_list, char_info);
1532 _bt_hps_set_char_value(http_hdr_obj_path, value, MAX_HEADER_LENGTH, 0);
1535 /* Characteristic HTTP Entity Body */
1536 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1537 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1538 char_uuid = __hps_convert_uuid_to_uuid128(HTTP_ENTITY_UUID);
1539 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_entity_obj_path);
1540 if (ret != BLUETOOTH_ERROR_NONE) {
1541 BT_ERR("Failed to add new char %d", ret);
1545 ret = bluetooth_gatt_set_characteristic_value(http_entity_obj_path, value, MAX_ENTITY_LENGTH);
1546 if (ret != BLUETOOTH_ERROR_NONE) {
1547 BT_ERR("Failed to add new char %d", ret);
1551 /* Store Characterisitc information */
1552 char_info = g_new0(struct hps_char_info, 1);
1553 char_info->char_path = g_strdup(http_entity_obj_path);
1554 hps_char_list = g_slist_append(hps_char_list, char_info);
1555 _bt_hps_set_char_value(http_entity_obj_path, value, MAX_ENTITY_LENGTH, 0);
1558 /* Characteristic HTTP Control Point */
1559 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1560 char_uuid = __hps_convert_uuid_to_uuid128(HTTP_CP_UUID);
1561 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_cp_obj_path);
1562 if (ret != BLUETOOTH_ERROR_NONE) {
1563 BT_ERR("Failed to add new char %d", ret);
1567 ret = bluetooth_gatt_set_characteristic_value(http_cp_obj_path, &cp, 1);
1568 if (ret != BLUETOOTH_ERROR_NONE) {
1569 BT_ERR("Failed to add new char %d", ret);
1573 /* Store Characterisitc information */
1574 char_info = g_new0(struct hps_char_info, 1);
1575 char_info->char_path = g_strdup(http_cp_obj_path);
1576 hps_char_list = g_slist_append(hps_char_list, char_info);
1577 _bt_hps_set_char_value(http_cp_obj_path, &cp, 1, 0);
1580 /* Characteristic HTTP Status Code */
1581 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1582 char_uuid = __hps_convert_uuid_to_uuid128(HTTP_STATUS_UUID);
1583 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_status_obj_path);
1584 if (ret != BLUETOOTH_ERROR_NONE) {
1585 BT_ERR("Failed to add new char %d", ret);
1589 ret = bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
1590 if (ret != BLUETOOTH_ERROR_NONE) {
1591 BT_ERR("Failed to add new char %d", ret);
1595 desc_uuid = __hps_convert_uuid_to_uuid128(HTTP_STATUS_CCC_DESC_UUID);
1596 ret = bluetooth_gatt_add_descriptor(http_status_obj_path, desc_uuid,
1597 (BLUETOOTH_GATT_PERMISSION_READ | BLUETOOTH_GATT_PERMISSION_WRITE),
1598 &http_status_desc_obj_path);
1599 if (ret != BLUETOOTH_ERROR_NONE) {
1600 BT_ERR("Failed to add new char descriptor %d", ret);
1604 /* Store Characterisitc information */
1605 char_info = g_new0(struct hps_char_info, 1);
1606 char_info->char_path = g_strdup(http_status_obj_path);
1607 hps_char_list = g_slist_append(hps_char_list, char_info);
1608 _bt_hps_set_char_value(http_status_obj_path, status, 3, 0);
1611 /* Characteristic HTTPS Security */
1612 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
1613 char_uuid = __hps_convert_uuid_to_uuid128(HTTP_SECURITY_UUID);
1614 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_security_obj_path);
1615 if (ret != BLUETOOTH_ERROR_NONE) {
1616 BT_ERR("Failed to add new char %d", ret);
1620 ret = bluetooth_gatt_set_characteristic_value(http_security_obj_path, &cp, 1);
1621 if (ret != BLUETOOTH_ERROR_NONE) {
1622 BT_ERR("Failed to add new char %d", ret);
1626 /* Store Characterisitc information */
1627 char_info = g_new0(struct hps_char_info, 1);
1628 char_info->char_path = g_strdup(http_security_obj_path);
1629 hps_char_list = g_slist_append(hps_char_list, char_info);
1630 _bt_hps_set_char_value(http_security_obj_path, &cp, 1, 0);
1633 ret = bluetooth_gatt_register_service(hps_obj_path);
1634 if (ret != BLUETOOTH_ERROR_NONE) {
1635 BT_ERR("Failed to register service %d", ret);
1639 ret = bluetooth_gatt_register_application();
1640 if (ret != BLUETOOTH_ERROR_NONE) {
1641 BT_ERR("Failed to register application %d", ret);
1649 delete_all_characterisitc();
1650 delete_all_notify_read_status();
1656 static void _bt_hps_sig_handler(int sig)
1662 BT_DBG("caught signal - sigterm\n");
1665 BT_DBG("caught signal - sigint\n");
1668 BT_DBG("caught signal - sigkill\n");
1671 BT_DBG("caught signal %d and ignored\n", sig);
1676 void _bt_hps_exit(void)
1681 if (g_uri != NULL) {
1686 if (g_header != NULL) {
1691 if (g_entity != NULL) {
1696 soup_session_abort(hps_soup_session);
1697 g_assert_cmpint(G_OBJECT(hps_soup_session)->ref_count, ==, 1);
1698 g_object_unref(hps_soup_session);
1701 delete_all_characterisitc();
1704 ret = bluetooth_gatt_deinit();
1705 if (ret != BLUETOOTH_ERROR_NONE)
1706 BT_ERR("Failed to Deinit GATT %d", ret);
1708 ret = bluetooth_unregister_callback();
1709 if (ret != BLUETOOTH_ERROR_NONE)
1710 BT_ERR("Failed to Unregister callback %d", ret);
1712 _bt_hps_deinit_event_receiver();
1714 _bt_hps_unregister_interface();
1716 if (main_loop != NULL)
1717 g_main_loop_quit(main_loop);
1720 void bt_hps_event_callback(int event, bluetooth_event_param_t* param,
1723 BT_DBG("HPS event %d", event);
1727 /* HTTP Proxy Service Main loop */
1730 struct sigaction sa;
1732 BT_ERR("Starting the bt-httpproxy daemon");
1734 /* Values taken from http://www.browserscope.org/ following
1735 * the rule "Do What Every Other Modern Browser Is Doing". They seem
1736 * to significantly improve page loading time compared to soup's
1738 * Change MAX_CONNECTIONS_PER_HOST value 6 -> 12, and maxConnections is changed from 35 to 60.
1739 * Enhanced network loading speed apply tunning value. */
1740 static const int maxConnections = 60;
1741 static const int maxConnectionsPerHost = 12;
1743 memset(&sa, 0, sizeof(sa));
1744 sa.sa_handler = _bt_hps_sig_handler;
1745 sa.sa_flags = SA_SIGINFO;
1746 sigaction(SIGINT, &sa, NULL);
1747 sigaction(SIGTERM, &sa, NULL);
1748 sigaction(SIGKILL, &sa, NULL);
1751 if (bluetooth_register_callback(bt_hps_event_callback, NULL) != BLUETOOTH_ERROR_NONE) {
1752 BT_ERR("bluetooth_register_callback returned failiure");
1757 if (_bt_hps_register_interface() != BLUETOOTH_ERROR_NONE) {
1758 BT_ERR("Fail to register http proxy service");
1762 if (_bt_hps_init_event_receiver() != BLUETOOTH_ERROR_NONE) {
1763 BT_ERR("Fail to init event reciever");
1767 hps_soup_session = soup_session_async_new();
1768 if (hps_soup_session == NULL) {
1769 BT_ERR("Failed to soup_session_async_new");
1772 /* Set Soup Session Fetures */
1773 g_object_set(hps_soup_session,
1774 SOUP_SESSION_MAX_CONNS, maxConnections,
1775 SOUP_SESSION_MAX_CONNS_PER_HOST, maxConnectionsPerHost,
1776 SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER,
1777 SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_SNIFFER,
1778 SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_RESOLVER_DEFAULT,
1779 SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
1782 main_loop = g_main_loop_new(NULL, FALSE);
1784 g_main_loop_run(main_loop);
1786 BT_DBG("g_main_loop_quit called!");
1788 if (main_loop != NULL)
1789 g_main_loop_unref(main_loop);