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)
100 unsigned int addr[BLUETOOTH_ADDRESS_LENGTH] = { 0, };
102 if (addr_str == NULL || addr_str[0] == '\0')
105 i = sscanf(addr_str, "%X:%X:%X:%X:%X:%X", &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]);
106 if (i != BLUETOOTH_ADDRESS_LENGTH)
107 BT_ERR("Invalid format string - [%s]", addr_str);
109 for (i = 0; i < BLUETOOTH_ADDRESS_LENGTH; i++)
110 addr_hex->addr[i] = (unsigned char)addr[i];
113 static char *__hps_convert_uuid_to_uuid128(const char *uuid)
123 uuid128 = g_strdup_printf("0000%s-0000-1000-8000-00805F9B34FB", uuid);
128 uuid128 = g_strdup_printf("%s-0000-1000-8000-00805F9B34FB", uuid);
133 uuid128 = strdup(uuid);
143 static void _bt_hps_send_status_notification(unsigned short http_status,
144 unsigned char data_status,
145 bluetooth_device_address_t *unicast_address)
147 char status[3] = {0x00};
148 int ret = BLUETOOTH_ERROR_NONE;
152 status[0] = http_status & 0xFF;
153 status[1] = (http_status >> 8) & 0xFF;
154 status[2] = data_status;
155 BT_DBG("Status %d %04x", http_status, http_status);
157 /* Store the status value */
158 _bt_hps_set_char_value(http_status_obj_path, status, 3, 0);
160 /* Send unicast notification */
161 ret = bluetooth_gatt_server_set_notification(http_status_obj_path, unicast_address);
162 if (ret != BLUETOOTH_ERROR_NONE) {
163 BT_ERR("_bt_hps_send_status_notification failed");
166 ret = bluetooth_gatt_update_characteristic(http_status_obj_path, status, 3);
167 if (ret != BLUETOOTH_ERROR_NONE) {
168 BT_ERR("_bt_hps_send_status_notification failed");
174 static void _bt_httpproxy_method(GDBusConnection *connection,
176 const gchar *object_path,
177 const gchar *interface_name,
178 const gchar *method_name,
179 GVariant *parameters,
180 GDBusMethodInvocation *invocation,
185 BT_DBG("Method[%s] Object Path[%s] Interface Name[%s]",
186 method_name, object_path, interface_name);
188 if (g_strcmp0(method_name, "enable") == 0) {
189 g_dbus_method_invocation_return_value(invocation, g_variant_new("(y)", status));
190 } else if (g_strcmp0(method_name, "disable") == 0) {
192 g_dbus_method_invocation_return_value(invocation, g_variant_new("(y)", status));
198 static const GDBusInterfaceVTable hps_method_table = {
199 _bt_httpproxy_method,
204 static void _bt_hps_on_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
207 GError *error = NULL;
213 object_id = g_dbus_connection_register_object(connection, BT_HPS_OBJECT_PATH,
214 hps_node_info->interfaces[0],
217 if (object_id == 0) {
218 BT_ERR("Failed to register method table: %s", error->message);
220 g_dbus_node_info_unref(hps_node_info);
226 static void _bt_hps_on_name_acquired(GDBusConnection *connection,
234 static void _bt_hps_on_name_lost(GDBusConnection *connection,
239 g_object_unref(g_conn);
241 g_dbus_node_info_unref(hps_node_info);
242 g_bus_unown_name(g_owner_id);
247 int _bt_hps_register_interface(void)
249 GError *error = NULL;
254 hps_node_info = g_dbus_node_info_new_for_xml(hps_introspection_xml, &error);
255 if (!hps_node_info) {
256 BT_ERR("Failed to install: %s", error->message);
257 return BLUETOOTH_ERROR_INTERNAL;
260 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
262 G_BUS_NAME_OWNER_FLAGS_NONE,
263 _bt_hps_on_bus_acquired, _bt_hps_on_name_acquired, _bt_hps_on_name_lost,
265 g_owner_id = owner_id;
266 BT_DBG("owner_id is [%d]\n", owner_id);
268 return BLUETOOTH_ERROR_NONE;
271 void _bt_hps_unregister_interface(void)
275 g_object_unref(g_conn);
277 g_dbus_node_info_unref(hps_node_info);
278 g_bus_unown_name(g_owner_id);
284 static struct hps_char_info *hps_get_char_value(const char *path)
288 for (tmp = hps_char_list; tmp != NULL; tmp = tmp->next) {
290 struct hps_char_info *char_info = tmp->data;
291 if (!g_strcmp0(char_info->char_path, path))
298 static int char_info_cmp(gconstpointer a1, gconstpointer a2)
300 const struct hps_char_info *attrib1 = a1;
301 const struct hps_char_info *attrib2 = a2;
303 return g_strcmp0(attrib1->char_path, attrib2->char_path);
306 static int notify_info_cmp(gconstpointer a1, gconstpointer a2)
308 const struct hps_notify_read_info *attrib1 = a1;
309 const struct hps_notify_read_info *attrib2 = a2;
311 return g_strcmp0(attrib1->char_path, attrib2->char_path);
314 static void _bt_hps_set_char_value(const char *obj_path, const char* value, int value_length, int offset)
320 for (tmp = hps_char_list; tmp != NULL; tmp = tmp->next) {
322 struct hps_char_info *char_info = tmp->data;
323 if (!g_strcmp0(char_info->char_path, obj_path)) {
326 str = g_strdup(char_info->char_value);
327 char_info->char_value = g_try_realloc(char_info->char_value, offset + value_length);
329 char_info->char_value = g_try_realloc(char_info->char_value, value_length);
331 if (char_info->char_value) {
333 memcpy(char_info->char_value, str, strlen(str));
336 memcpy(&char_info->char_value[offset], value, value_length);
337 char_info->value_length = offset + value_length;
339 memcpy(char_info->char_value, value, value_length);
340 char_info->value_length = value_length;
342 hps_char_list = g_slist_insert_sorted(hps_char_list,
343 char_info, char_info_cmp);
353 static void _bt_hps_set_notify_read_status(const char *obj_path,
354 guint offset_status, guint read_status, int https_status)
356 struct hps_notify_read_info *notify_read_info = NULL;
359 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
361 notify_read_info = tmp->data;
362 if (!g_strcmp0(notify_read_info->char_path, obj_path)) {
363 notify_read_info->read_status = read_status;
364 notify_read_info->offset_status = offset_status;
365 notify_read_info->https_status = https_status;
366 hps_notify_read_list = g_slist_insert_sorted(hps_notify_read_list,
367 notify_read_info, notify_info_cmp);
373 if (!hps_notify_read_list) {
374 /* Store Notification information */
375 notify_read_info = g_new0(struct hps_notify_read_info, 1);
376 if (notify_read_info) {
377 notify_read_info->char_path = g_strdup(obj_path);
378 notify_read_info->read_status = read_status;
379 notify_read_info->offset_status = offset_status;
380 notify_read_info->https_status = https_status;
381 hps_notify_read_list = g_slist_append(hps_notify_read_list, notify_read_info);
385 /* Store Notification information */
386 notify_read_info = g_new0(struct hps_notify_read_info, 1);
387 if (notify_read_info) {
388 notify_read_info->char_path = g_strdup(obj_path);
389 notify_read_info->read_status = read_status;
390 notify_read_info->offset_status = offset_status;
391 notify_read_info->https_status = https_status;
392 hps_notify_read_list = g_slist_append(hps_notify_read_list, notify_read_info);
398 static struct hps_notify_read_info *_bt_hps_get_notify_read_status(const char *obj_path)
402 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
404 struct hps_notify_read_info *notify_read_info = tmp->data;
405 if (!g_strcmp0(notify_read_info->char_path, obj_path))
406 return notify_read_info;
413 static void delete_all_characterisitc(void)
416 for (tmp = hps_char_list; tmp != NULL; tmp = tmp->next) {
418 struct hps_char_info *char_info = tmp->data;
419 if (char_info->char_path)
420 g_free(char_info->char_path);
421 if (char_info->char_value)
422 g_free(char_info->char_value);
423 hps_char_list = g_slist_delete_link(hps_char_list, tmp->data);
426 g_slist_free(hps_char_list);
427 hps_char_list = NULL;
430 static void delete_all_notify_read_status(void)
433 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
435 struct hps_notify_read_info *notify_read_info = tmp->data;
436 if (notify_read_info->char_path)
437 g_free(notify_read_info->char_path);
438 hps_notify_read_list = g_slist_delete_link(hps_notify_read_list, tmp->data);
441 g_slist_free(hps_notify_read_list);
442 hps_notify_read_list = NULL;
445 static void delete_notify_read_status(const char *obj_path)
448 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
450 struct hps_notify_read_info *notify_read_info = tmp->data;
451 if (!g_strcmp0(notify_read_info->char_path, obj_path)) {
452 if (notify_read_info->char_path)
453 g_free(notify_read_info->char_path);
454 hps_notify_read_list = g_slist_delete_link(hps_notify_read_list, tmp->data);
462 int _bt_hps_uri_write_cb(char *uri, int len, int offset)
464 if ((len < 1) || (len > MAX_URI_LENGTH)) {
465 BT_ERR("Wrong URI length %d", len);
466 return BLUETOOTH_ERROR_INTERNAL;
469 /* g_uri will be used commonly for all HTTP methods whereever applicable */
472 g_uri = g_strndup(uri, len);
474 _bt_hps_set_char_value(http_uri_obj_path, g_uri, len, offset);
476 return BLUETOOTH_ERROR_NONE;
479 int _bt_hps_http_header_write_cb(char *header, int len, int offset)
481 if ((len < 1) || (len > MAX_HEADER_LENGTH)) {
482 BT_ERR("Wrong Header length %d", len);
483 return BLUETOOTH_ERROR_INTERNAL;
486 /* g_header will be used commonly for all HTTP methods where ever applicable
487 general-header, request-header, entity-header
491 g_header = g_strndup(header, len);
493 _bt_hps_set_char_value(http_hdr_obj_path, g_header, len, offset);
496 return BLUETOOTH_ERROR_NONE;
499 int _bt_hps_entity_body_write_cb(char *entity, int len, int offset)
501 if ((len < 1) || (len > MAX_ENTITY_LENGTH)) {
502 BT_ERR("Wrong Entity length %d", len);
503 return BLUETOOTH_ERROR_INTERNAL;
506 /* g_entity will be used commonly for all HTTP methods whereever applicable */
509 g_entity = g_strndup(entity, len);
511 _bt_hps_set_char_value(http_entity_obj_path, g_entity, len, offset);
514 return BLUETOOTH_ERROR_NONE;
518 int _bt_hps_read_cb(const char *obj_path, char **value, int *len)
520 struct hps_char_info *info = NULL;
521 struct hps_notify_read_info *notify_read_info = NULL;
522 guint data_status = -1;
524 gboolean is_header = FALSE;
527 BT_ERR("Wrong Obj path");
531 if (!g_strcmp0(http_hdr_obj_path, obj_path))
534 info = hps_get_char_value(obj_path);
537 if (info->char_value == NULL || info->value_length == 0)
540 notify_read_info = _bt_hps_get_notify_read_status(obj_path);
541 if (notify_read_info && notify_read_info->read_status != DS_BODY_RECEIVED &&
542 notify_read_info->read_status != DS_HEADER_RECEIVED) {
543 offset = notify_read_info->offset_status;
544 if ((info->value_length - offset) > 0 &&
545 (info->value_length - offset) > MAX_ENTITY_LENGTH) {
547 data_status = DS_HEADER_TRUNCATED;
549 data_status = DS_BODY_TRUNCATED;
550 _bt_hps_set_notify_read_status(obj_path, offset + MAX_ENTITY_LENGTH,
551 data_status, notify_read_info->https_status);
552 *value = g_strdup(&info->char_value[offset]);
553 *len = MAX_ENTITY_LENGTH;
554 } else if ((info->value_length - offset) > 0 &&
555 (info->value_length - offset) <= MAX_ENTITY_LENGTH) {
557 data_status = DS_HEADER_RECEIVED;
559 data_status = DS_BODY_RECEIVED;
560 _bt_hps_set_notify_read_status(obj_path, offset, data_status, notify_read_info->https_status);
561 *value = g_strdup(&info->char_value[offset]);
562 *len = info->value_length - offset;
564 } else if (notify_read_info && (notify_read_info->read_status == DS_BODY_RECEIVED ||
565 notify_read_info->read_status == DS_HEADER_RECEIVED)) {
567 data_status = DS_HEADER_RECEIVED;
569 data_status = DS_BODY_RECEIVED;
570 delete_notify_read_status(obj_path);
571 *value = g_strdup(&info->char_value[offset]);
572 *len = info->value_length;
580 void _bt_hps_head_response_cb(SoupSession *session,
581 SoupMessage *msg, gpointer user_data)
583 unsigned short http_status = 0x00;
585 unsigned char status[3] = {0x00};
587 const char *device_address = user_data;
588 bluetooth_device_address_t addr_hex = { {0,} };
589 unsigned char data_status = DS_NONE;
590 _hps_convert_address_to_hex(&addr_hex, device_address);
593 if (hps_soup_session != session) {
594 BT_ERR("Wrong Session");
599 BT_ERR("Wrong Message");
604 req_state = HTTP_REQ_STATE_EXECUTED;
606 http_status = msg->status_code;
608 // Process Header in Response Body
609 if (msg->response_headers) {
611 const char *content = NULL;
612 const char *length = NULL;
615 length = soup_message_headers_get_one(msg->request_headers,
617 // Check "Content-MD5" is the right name to get header content
618 content = soup_message_headers_get_one(msg->response_headers,
620 if (content == NULL || length == NULL) {
621 BT_ERR("Wrong Response Header");
622 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
626 hdr_len = soup_message_headers_get_content_length(msg->response_headers);
628 // Write Data to Header Characteristic
630 _bt_hps_set_char_value(http_hdr_obj_path, content, hdr_len, 0);
632 bluetooth_gatt_set_characteristic_value(http_hdr_obj_path, content, hdr_len);
634 // TODO : Handle Truncated Header
636 // Write Data to Status Code Characteristic
638 data_status = (hdr_len > MAX_ENTITY_LENGTH) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
640 if (data_status == DS_BODY_TRUNCATED && SOUP_STATUS_IS_SUCCESSFUL(http_status))
641 _bt_hps_set_notify_read_status(http_hdr_obj_path, 0, data_status, http_status);
643 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
645 status[0] = http_status & 0x0F;
646 status[1] = (http_status >> 8) & 0x0F;
647 status[2] = (hdr_len > MAX_HEADER_LENGTH) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
649 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
652 BT_ERR("HEAD Response is NULL");
653 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
659 void _bt_hps_http_response_cb(SoupSession *session,
660 SoupMessage *msg, gpointer user_data)
662 unsigned short http_status = 0x00;
664 unsigned char status[3] = {0x00};
666 const char *device_address = user_data;
667 bluetooth_device_address_t addr_hex = { {0,} };
668 unsigned char data_status = DS_NONE;
669 _hps_convert_address_to_hex(&addr_hex, device_address);
672 if (hps_soup_session != session) {
673 BT_ERR("Wrong Session");
678 BT_ERR("Wrong Message");
684 req_state = HTTP_REQ_STATE_EXECUTED;
686 http_status = msg->status_code;
688 // Write Data to Status Code Characteristic
690 status[0] = http_status & 0x0F;
691 status[1] = (http_status >> 8) & 0x0F;
692 status[2] = DS_HEADER_RECEIVED;
693 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
695 data_status = DS_HEADER_RECEIVED;
696 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
702 void _bt_hps_get_response_cb(SoupSession *session,
703 SoupMessage *msg, gpointer user_data)
705 SoupBuffer *body = NULL;
706 unsigned short http_status = 0x00;
708 unsigned char status[3] = {0x00};
710 const char *device_address = user_data;
711 bluetooth_device_address_t addr_hex = { {0,} };
712 unsigned char data_status = DS_NONE;
713 _hps_convert_address_to_hex(&addr_hex, device_address);
716 if (hps_soup_session != session) {
717 BT_ERR("Wrong Session");
722 BT_ERR("Wrong Message");
728 req_state = HTTP_REQ_STATE_EXECUTED;
730 http_status = msg->status_code;
732 // Process Entity Body in Response Message
733 if (msg->response_body) {
735 body = soup_message_body_flatten(msg->response_body);
737 BT_ERR("Wrong Response Body");
739 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
743 if (body->data == NULL || body->length <= 0) {
744 BT_ERR("Wrong Response");
745 soup_buffer_free(body);
747 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
751 // Write Data to Entity Body Characteristic
753 _bt_hps_set_char_value(http_entity_obj_path, body->data, body->length, 0);
755 bluetooth_gatt_set_characteristic_value(http_entity_obj_path, body->data, body->length);
757 // TODO : Handle Truncated Entiry Body
759 // Write Data to Status Code Characteristic
761 data_status = (body->length > MAX_ENTITY_LENGTH) ? DS_BODY_TRUNCATED : DS_BODY_RECEIVED;
763 if (data_status == DS_BODY_TRUNCATED && SOUP_STATUS_IS_SUCCESSFUL(http_status))
764 _bt_hps_set_notify_read_status(http_entity_obj_path, 0, data_status, http_status);
766 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
769 status[0] = http_status & 0x0F;
770 status[1] = (http_status >> 8) & 0x0F;
771 status[2] = (body->length > MAX_HEADER_LENGTH) ? DS_BODY_TRUNCATED : DS_BODY_TRUNCATED;
773 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
775 soup_buffer_free(body);
777 BT_ERR("GET Response Body is NULL");
779 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
783 // Process Header in Response Body
784 if (msg->response_headers) {
786 const char *content = NULL;
787 const char *length = NULL;
790 length = soup_message_headers_get_one(msg->request_headers,
792 // Check "Content-MD5" is the right name to get header content
793 content = soup_message_headers_get_one(msg->response_headers,
795 if (content == NULL || length == NULL) {
796 BT_ERR("Wrong Response Header");
797 data_status = DS_NONE;
798 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
802 hdr_len = soup_message_headers_get_content_length(msg->response_headers);
803 // Write Data to Header Characteristic
805 _bt_hps_set_char_value(http_hdr_obj_path, content, hdr_len, 0);
807 bluetooth_gatt_set_characteristic_value(http_hdr_obj_path, content, hdr_len);
809 // TODO : Handle Truncated Header
811 // Write Data to Status Code Characteristic
813 data_status = (hdr_len > MAX_HEADER_LENGTH) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
815 if (data_status == DS_HEADER_TRUNCATED && SOUP_STATUS_IS_SUCCESSFUL(http_status))
816 _bt_hps_set_notify_read_status(http_hdr_obj_path, 0, data_status, http_status);
818 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
820 status[0] = http_status & 0x0F;
821 status[1] = (http_status >> 8) & 0x0F;
822 status[2] = (hdr_len > MAX_HEADER_LENGTH) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
824 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
827 BT_ERR("GET Response Header is NULL");
829 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
837 int _bt_hps_control_point_write_cb(const char *value, int len, char *addr)
839 int _bt_hps_control_point_write_cb(char *value, int len)
843 GTlsCertificate *cert = NULL;
844 GTlsCertificateFlags flags;
845 gboolean https_status = FALSE;
846 int result = BLUETOOTH_ERROR_NONE;
847 BT_INFO("Opcode %0x", opcode);
850 _bt_hps_set_char_value(http_cp_obj_path, value, len, 0);
854 case HTTP_GET_REQUEST:
855 if (req_state == HTTP_REQ_STATE_EXECUTED) {
856 req_state = HTTP_REQ_STATE_INPROGRESS;
857 hps_soup_msg = soup_message_new("GET", g_uri);
859 g_object_ref(hps_soup_msg);
860 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, addr);
862 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, NULL);
865 BT_ERR("HTTP GET request in progress, message dropped");
866 result = BLUETOOTH_ERROR_INTERNAL;
870 case HTTP_POST_REQUEST:
871 if (req_state == HTTP_REQ_STATE_EXECUTED) {
872 req_state = HTTP_REQ_STATE_INPROGRESS;
873 hps_soup_msg = soup_message_new("POST", g_uri);
874 if (hps_soup_msg == NULL || g_entity == NULL) {
875 BT_ERR("Soup Message NULL");
876 result = BLUETOOTH_ERROR_INTERNAL;
877 req_state = HTTP_REQ_STATE_EXECUTED;
880 soup_message_set_request(hps_soup_msg, "text/xml", SOUP_MEMORY_COPY,
881 g_entity, strlen(g_entity));
883 g_object_ref(hps_soup_msg);
884 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
886 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
889 BT_ERR("HTTP POST request in progress, message dropped");
890 result = BLUETOOTH_ERROR_INTERNAL;
894 case HTTP_HEAD_REQUEST:
895 if (req_state == HTTP_REQ_STATE_EXECUTED) {
896 req_state = HTTP_REQ_STATE_INPROGRESS;
897 hps_soup_msg = soup_message_new("HEAD", g_uri);
898 if (hps_soup_msg == NULL) {
899 BT_ERR("Soup Message NULL");
900 result = BLUETOOTH_ERROR_INTERNAL;
901 req_state = HTTP_REQ_STATE_EXECUTED;
905 g_object_ref(hps_soup_msg);
906 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, addr);
908 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, NULL);
911 BT_ERR("HTTP HEAD request in progress, message dropped");
912 result = BLUETOOTH_ERROR_INTERNAL;
916 case HTTP_PUT_REQUEST:
917 if (req_state == HTTP_REQ_STATE_EXECUTED) {
919 req_state = HTTP_REQ_STATE_INPROGRESS;
920 hps_soup_msg = soup_message_new("PUT", g_uri);
921 if (hps_soup_msg == NULL || g_entity == NULL) {
922 BT_ERR("Soup Message NULL");
923 result = BLUETOOTH_ERROR_INTERNAL;
924 req_state = HTTP_REQ_STATE_EXECUTED;
927 buf = soup_buffer_new(SOUP_MEMORY_TAKE, g_entity, strlen(g_entity));
928 soup_message_body_append_buffer(hps_soup_msg->request_body, buf);
929 soup_message_body_set_accumulate(hps_soup_msg->request_body, FALSE);
931 g_object_ref(hps_soup_msg);
932 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
934 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
938 BT_ERR("HTTP PUT request in progress, message dropped");
939 result = BLUETOOTH_ERROR_INTERNAL;
943 case HTTP_DELETE_REQUEST:
944 if (req_state == HTTP_REQ_STATE_EXECUTED) {
945 req_state = HTTP_REQ_STATE_INPROGRESS;
946 hps_soup_msg = soup_message_new("DELETE", g_uri);
947 if (hps_soup_msg == NULL) {
948 BT_ERR("Soup Message NULL");
949 result = BLUETOOTH_ERROR_INTERNAL;
950 req_state = HTTP_REQ_STATE_EXECUTED;
954 g_object_ref(hps_soup_msg);
955 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
957 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
960 BT_ERR("HTTP DELETE request in progress, message dropped");
961 result = BLUETOOTH_ERROR_INTERNAL;
965 case HTTPS_GET_REQUEST:
966 if (req_state == HTTP_REQ_STATE_EXECUTED) {
967 req_state = HTTP_REQ_STATE_INPROGRESS;
968 hps_soup_msg = soup_message_new("GET", g_uri);
969 if (hps_soup_msg == NULL) {
970 BT_ERR("Soup Message NULL");
971 result = BLUETOOTH_ERROR_INTERNAL;
972 req_state = HTTP_REQ_STATE_EXECUTED;
976 g_object_ref(hps_soup_msg);
977 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, addr);
979 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, NULL);
981 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
983 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1, 0);
985 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
988 BT_ERR("HTTPS GET request in progress, message dropped");
989 result = BLUETOOTH_ERROR_INTERNAL;
993 case HTTPS_HEAD_REQUEST:
994 if (req_state == HTTP_REQ_STATE_EXECUTED) {
995 req_state = HTTP_REQ_STATE_INPROGRESS;
996 hps_soup_msg = soup_message_new("HEAD", g_uri);
997 if (hps_soup_msg == NULL) {
998 BT_ERR("Soup Message NULL");
999 result = BLUETOOTH_ERROR_INTERNAL;
1000 req_state = HTTP_REQ_STATE_EXECUTED;
1004 g_object_ref(hps_soup_msg);
1005 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, addr);
1007 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, NULL);
1009 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
1011 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1, 0);
1013 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
1016 BT_ERR("HTTPS HEAD request in progress, message dropped");
1017 result = BLUETOOTH_ERROR_INTERNAL;
1021 case HTTPS_POST_REQUEST:
1022 if (req_state == HTTP_REQ_STATE_EXECUTED) {
1023 req_state = HTTP_REQ_STATE_INPROGRESS;
1024 hps_soup_msg = soup_message_new("POST", g_uri);
1025 if (hps_soup_msg == NULL) {
1026 BT_ERR("Soup Message NULL");
1027 result = BLUETOOTH_ERROR_INTERNAL;
1028 req_state = HTTP_REQ_STATE_EXECUTED;
1031 soup_message_set_request(hps_soup_msg, "text/xml", SOUP_MEMORY_STATIC,
1032 g_entity, strlen(g_entity));
1034 g_object_ref(hps_soup_msg);
1035 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
1037 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
1040 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
1042 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1, 0);
1044 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
1047 BT_ERR("HTTPS POST request in progress, message dropped");
1048 result = BLUETOOTH_ERROR_INTERNAL;
1052 case HTTPS_PUT_REQUEST:
1053 if (req_state == HTTP_REQ_STATE_EXECUTED) {
1055 req_state = HTTP_REQ_STATE_INPROGRESS;
1056 hps_soup_msg = soup_message_new("PUT", g_uri);
1057 if (hps_soup_msg == NULL) {
1058 BT_ERR("Soup Message NULL");
1059 result = BLUETOOTH_ERROR_INTERNAL;
1060 req_state = HTTP_REQ_STATE_EXECUTED;
1063 buf = soup_buffer_new(SOUP_MEMORY_TAKE, g_entity, strlen(g_entity));
1064 soup_message_body_append_buffer(hps_soup_msg->request_body, buf);
1065 soup_message_body_set_accumulate(hps_soup_msg->request_body, FALSE);
1067 g_object_ref(hps_soup_msg);
1068 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
1070 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
1072 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
1074 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1, 0);
1076 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
1079 BT_ERR("HTTPS PUT request in progress, message dropped");
1080 result = BLUETOOTH_ERROR_INTERNAL;
1084 case HTTPS_DELETE_REQUEST:
1085 if (req_state == HTTP_REQ_STATE_EXECUTED) {
1086 req_state = HTTP_REQ_STATE_INPROGRESS;
1087 hps_soup_msg = soup_message_new("DELETE", g_uri);
1088 if (hps_soup_msg == NULL) {
1089 BT_ERR("Soup Message NULL");
1090 result = BLUETOOTH_ERROR_INTERNAL;
1091 req_state = HTTP_REQ_STATE_EXECUTED;
1095 g_object_ref(hps_soup_msg);
1096 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
1098 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
1101 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
1103 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1, 0);
1105 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
1108 BT_ERR("HTTPS DELETE request in progress, message dropped");
1109 result = BLUETOOTH_ERROR_INTERNAL;
1113 case HTTP_REQUEST_CANCEL:
1114 /* Cancel the outstanding request */
1115 if (req_state == HTTP_REQ_STATE_INPROGRESS) {
1116 req_state = HTTP_REQ_STATE_IDLE;
1117 if (hps_soup_msg == NULL) {
1118 BT_ERR("Soup Message NULL");
1119 result = BLUETOOTH_ERROR_INTERNAL;
1120 req_state = HTTP_REQ_STATE_EXECUTED;
1123 soup_session_cancel_message(hps_soup_session, hps_soup_msg, SOUP_STATUS_CANCELLED);
1124 hps_soup_msg = NULL;
1129 BT_ERR("Unknown opcode %0x", opcode);
1130 result = BLUETOOTH_ERROR_INTERNAL;
1137 void _bt_hps_security_read_cb(char *value, int len)
1139 BT_INFO("HPS Client Read the value");
1144 void _bt_hps_gatt_char_property_changed_event(GVariant *msg,
1147 int result = BLUETOOTH_ERROR_NONE;
1148 GVariantIter value_iter;
1149 const char *property = NULL;
1150 const char * char_path = NULL;
1151 const char * svc_handle = NULL;
1152 GVariant *var = NULL;
1153 GVariant *val = NULL;
1154 g_variant_iter_init(&value_iter, msg);
1156 while ((g_variant_iter_loop(&value_iter, "{sv}", &property, &var))) {
1158 if (property == NULL) {
1159 BT_ERR("Property NULL");
1163 if (!g_strcmp0(property, "WriteValue")) {
1165 BT_INFO("WriteValue");
1166 BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
1173 g_variant_get(var, "(&s&s&syq@ay)", &char_path,
1174 &svc_handle, &addr, &req_id, &offset, &val);
1176 len = g_variant_get_size(val);
1178 BT_DBG("Len = %d, Offset = %d", len, offset);
1180 value = (char *) g_variant_get_data(val);
1183 if (!g_strcmp0(char_path, http_uri_obj_path)) {
1185 result = _bt_hps_uri_write_cb(value, len, offset);;
1186 } else if (!g_strcmp0(char_path, http_hdr_obj_path)) {
1187 /* Retrive HEADER */
1188 result = _bt_hps_http_header_write_cb(value, len, offset);
1189 } else if (!g_strcmp0(char_path, http_entity_obj_path)) {
1190 /* Retrive ENTITY BODY */
1191 result = _bt_hps_entity_body_write_cb(value, len, offset);
1192 } else if (!g_strcmp0(char_path, http_cp_obj_path)) {
1193 result = _bt_hps_control_point_write_cb(value, len, addr);
1195 BT_ERR("Wrong Object Path %s", char_path);
1196 result = BLUETOOTH_ERROR_INTERNAL;
1198 bluetooth_gatt_send_response(req_id, BLUETOOTH_GATT_ATT_REQUEST_TYPE_WRITE, result, 0, NULL, 0);
1200 BT_ERR("Array Len 0");
1203 BT_ERR("var==NULL");
1205 } else if (!g_strcmp0(property, "ReadValue")) {
1211 int data_status = -1;
1212 BT_INFO("ReadValue");
1213 BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
1215 g_variant_get(var, "(&s&s&syq)", &char_path, &svc_handle,
1216 &addr, &req_id, &offset);
1218 data_status = _bt_hps_read_cb(char_path, &value, &len);
1219 if (data_status >= DS_NONE) {
1220 struct hps_notify_read_info *notify_read_info = NULL;
1221 bluetooth_device_address_t addr_hex = { {0,} };
1222 _hps_convert_address_to_hex(&addr_hex, addr);
1223 bluetooth_gatt_send_response(req_id, BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ,
1224 BLUETOOTH_ERROR_NONE, offset, value, len);
1225 notify_read_info = _bt_hps_get_notify_read_status(char_path);
1226 if (notify_read_info) {
1227 _bt_hps_send_status_notification(notify_read_info->https_status,
1228 data_status, &addr_hex);
1230 if (data_status == DS_BODY_RECEIVED ||
1231 data_status == DS_HEADER_RECEIVED) {
1232 _bt_hps_set_char_value(char_path, NULL, 0, 0);
1238 BT_ERR("ReadValue failed %s", char_path);
1239 bluetooth_gatt_send_response(req_id, BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ,
1240 BLUETOOTH_ERROR_INTERNAL, offset, NULL, 0);
1247 void _bt_hps_gatt_char_property_changed_event(GVariant *msg,
1250 GVariantIter value_iter;
1251 char *property = NULL;
1252 char * char_handle = NULL;
1253 GVariant *val = NULL;
1254 int result = BLUETOOTH_ERROR_NONE;
1255 GVariant *param = NULL;
1256 g_variant_iter_init(&value_iter, msg);
1257 char_handle = g_strdup(path);
1259 while ((g_variant_iter_loop(&value_iter, "{sv}", &property, &val))) {
1261 if (property == NULL) {
1262 BT_ERR("Property NULL");
1266 if (strcasecmp(property, "ChangedValue") == 0) {
1269 GByteArray *gp_byte_array = NULL;
1270 BT_INFO("Type '%s'\n", g_variant_get_type_string(val));
1273 gp_byte_array = g_byte_array_new();
1274 len = g_variant_get_size(val);
1275 BT_DBG("Len = %d", len);
1276 g_byte_array_append(gp_byte_array,
1277 (const guint8 *)g_variant_get_data(val), len);
1278 if (gp_byte_array->len != 0) {
1279 GVariant *byte_array = NULL;
1280 byte_array = g_variant_new_from_data(
1281 G_VARIANT_TYPE_BYTESTRING,
1282 gp_byte_array->data,
1285 param = g_variant_new("(is@ay)", result, char_handle,
1288 if (strcmp(path, http_uri_obj_path)) {
1290 _bt_hps_uri_write_cb(NULL, len);
1291 } else if (strcmp(path, http_hdr_obj_path)) {
1293 _bt_hps_http_header_write_cb(NULL, len);
1294 } else if (strcmp(path, http_entity_obj_path)) {
1295 //Retrive ENTITY BODY
1296 _bt_hps_entity_body_write_cb(NULL, len);
1297 } else if (strcmp(path, http_cp_obj_path)) {
1298 _bt_hps_control_point_write_cb(NULL, len);
1299 } else if (strcmp(path, http_security_obj_path)) {
1300 _bt_hps_security_read_cb(NULL, len);
1302 BT_ERR("Wrong Object Path %s", path);
1305 BT_ERR("Array Len 0");
1307 g_byte_array_free(gp_byte_array, TRUE);
1309 BT_ERR("val==NULL");
1313 g_free(char_handle);
1319 void _bt_hps_property_event_filter(GDBusConnection *connection,
1320 const gchar *sender_name,
1321 const gchar *object_path,
1322 const gchar *interface_name,
1323 const gchar *signal_name,
1324 GVariant *parameters,
1329 if (signal_name == NULL) {
1330 BT_ERR("Wrong Signal");
1335 if (g_strcmp0(signal_name, PROPERTIES_CHANGED) == 0) {
1337 g_variant_get(parameters, "(@a{sv}@as)", &value, NULL);
1339 _bt_hps_gatt_char_property_changed_event(value, object_path);
1341 if (g_strcmp0(interface_name, BT_HPS_PROPERTIES_INTERFACE) == 0) {
1343 g_variant_get(parameters, "(&s@a{sv}@as)", &interface_name, &value, NULL);
1345 _bt_hps_gatt_char_property_changed_event(value, object_path);
1348 //BT_ERR("Wrong Interface %s", interface_name);
1355 void _bt_hps_adapter_event_filter(GDBusConnection *connection,
1356 const gchar *sender_name,
1357 const gchar *object_path,
1358 const gchar *interface_name,
1359 const gchar *signal_name,
1360 GVariant *parameters,
1363 int result = BLUETOOTH_ERROR_NONE;
1366 if (signal_name == NULL) {
1367 BT_ERR("Wrong Signal");
1371 BT_INFO("Interface %s, Signal %s", interface_name, signal_name);
1373 if (g_strcmp0(interface_name, BT_HPS_INTERFACE_NAME) == 0) {
1375 g_variant_get(parameters, "(&s@a{sv}@as)", &interface_name, &value, NULL);
1377 if (strcasecmp(signal_name, BLE_ENABLED) == 0) {
1378 g_variant_get(parameters, "(i)", &result);
1380 if (_bt_hps_prepare_httpproxy() != BLUETOOTH_ERROR_NONE) {
1381 BT_ERR("Fail to prepare HTTP Proxy");
1385 if (_bt_hps_set_advertising_data() != BLUETOOTH_ERROR_NONE) {
1386 BT_ERR("Fail to set advertising data");
1391 BT_ERR("Wrong Signal %s", signal_name);
1398 int _bt_hps_init_event_receiver()
1400 GError *error = NULL;
1405 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
1406 if (error != NULL) {
1407 BT_ERR("ERROR: Can't get on system bus [%s]", error->message);
1408 g_clear_error(&error);
1412 property_sub_id = g_dbus_connection_signal_subscribe(conn,
1413 NULL, BT_HPS_INTERFACE_NAME,
1414 PROPERTIES_CHANGED, BT_HPS_OBJECT_PATH, NULL, 0,
1415 _bt_hps_property_event_filter,
1418 adapter_sub_id = g_dbus_connection_signal_subscribe(conn,
1419 NULL, BT_HPS_INTERFACE_NAME,
1420 BLE_ENABLED, BT_HPS_OBJECT_PATH, NULL, 0,
1421 _bt_hps_adapter_event_filter,
1427 void _bt_hps_deinit_event_receiver(void)
1430 g_dbus_connection_signal_unsubscribe(conn, property_sub_id);
1431 g_dbus_connection_signal_unsubscribe(conn, adapter_sub_id);
1436 int _bt_hps_set_advertising_data(void)
1441 guint8 data[4] = {0x03, 0x02, 0x23, 0x18};
1442 bluetooth_advertising_data_t adv;
1444 BT_DBG("%x %x %x %x", data[0], data[1], data[2], data[3]);
1445 memcpy(adv.data, data, sizeof(data));
1446 ret = bluetooth_set_advertising_data(0, &adv, sizeof(data));
1447 if (ret != BLUETOOTH_ERROR_NONE) {
1448 BT_ERR("Failed to set ADV data %d", ret);
1452 ret = bluetooth_set_advertising(0, TRUE);
1453 if (ret != BLUETOOTH_ERROR_NONE) {
1454 BT_ERR("Failed to set ADV %d", ret);
1461 int _bt_hps_prepare_httpproxy(void)
1463 int ret = BLUETOOTH_ERROR_NONE;
1467 bt_gatt_characteristic_property_t props;
1469 char value[MAX_URI_LENGTH] = { 0 };
1470 struct hps_char_info *char_info = NULL;
1472 char status[3] = { 0 };
1477 ret = bluetooth_gatt_init();
1478 if (ret != BLUETOOTH_ERROR_NONE) {
1479 BT_ERR("Failed to Init GATT %d", ret);
1483 service_uuid = __hps_convert_uuid_to_uuid128(HPS_UUID);
1484 ret = bluetooth_gatt_add_service(service_uuid, &hps_obj_path);
1485 if (ret != BLUETOOTH_ERROR_NONE) {
1486 BT_ERR("Failed to add service %d", ret);
1490 /* Characteristic URI */
1491 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1492 char_uuid = __hps_convert_uuid_to_uuid128(HTTP_URI_UUID);
1493 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_uri_obj_path);
1494 if (ret != BLUETOOTH_ERROR_NONE) {
1495 BT_ERR("Failed to add new char %d", ret);
1500 ret = bluetooth_gatt_set_characteristic_value(http_uri_obj_path, value, MAX_URI_LENGTH);
1501 if (ret != BLUETOOTH_ERROR_NONE) {
1502 BT_ERR("Failed to add new char %d", ret);
1506 /* Store requets information */
1507 char_info = g_new0(struct hps_char_info, 1);
1508 char_info->char_path = g_strdup(http_uri_obj_path);
1509 hps_char_list = g_slist_append(hps_char_list, char_info);
1510 _bt_hps_set_char_value(http_uri_obj_path, value, MAX_URI_LENGTH, 0);
1513 /* Characteristic HTTP Headers */
1514 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1515 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1516 char_uuid = __hps_convert_uuid_to_uuid128(HTTP_HDR_UUID);
1517 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_hdr_obj_path);
1518 if (ret != BLUETOOTH_ERROR_NONE) {
1519 BT_ERR("Failed to add new char %d", ret);
1523 ret = bluetooth_gatt_set_characteristic_value(http_hdr_obj_path, value, MAX_HEADER_LENGTH);
1524 if (ret != BLUETOOTH_ERROR_NONE) {
1525 BT_ERR("Failed to add new char %d", ret);
1529 /* Store Characterisitc information */
1530 char_info = g_new0(struct hps_char_info, 1);
1531 char_info->char_path = g_strdup(http_hdr_obj_path);
1532 hps_char_list = g_slist_append(hps_char_list, char_info);
1533 _bt_hps_set_char_value(http_hdr_obj_path, value, MAX_HEADER_LENGTH, 0);
1536 /* Characteristic HTTP Entity Body */
1537 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1538 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1539 char_uuid = __hps_convert_uuid_to_uuid128(HTTP_ENTITY_UUID);
1540 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_entity_obj_path);
1541 if (ret != BLUETOOTH_ERROR_NONE) {
1542 BT_ERR("Failed to add new char %d", ret);
1546 ret = bluetooth_gatt_set_characteristic_value(http_entity_obj_path, value, MAX_ENTITY_LENGTH);
1547 if (ret != BLUETOOTH_ERROR_NONE) {
1548 BT_ERR("Failed to add new char %d", ret);
1552 /* Store Characterisitc information */
1553 char_info = g_new0(struct hps_char_info, 1);
1554 char_info->char_path = g_strdup(http_entity_obj_path);
1555 hps_char_list = g_slist_append(hps_char_list, char_info);
1556 _bt_hps_set_char_value(http_entity_obj_path, value, MAX_ENTITY_LENGTH, 0);
1559 /* Characteristic HTTP Control Point */
1560 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1561 char_uuid = __hps_convert_uuid_to_uuid128(HTTP_CP_UUID);
1562 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_cp_obj_path);
1563 if (ret != BLUETOOTH_ERROR_NONE) {
1564 BT_ERR("Failed to add new char %d", ret);
1568 ret = bluetooth_gatt_set_characteristic_value(http_cp_obj_path, &cp, 1);
1569 if (ret != BLUETOOTH_ERROR_NONE) {
1570 BT_ERR("Failed to add new char %d", ret);
1574 /* Store Characterisitc information */
1575 char_info = g_new0(struct hps_char_info, 1);
1576 char_info->char_path = g_strdup(http_cp_obj_path);
1577 hps_char_list = g_slist_append(hps_char_list, char_info);
1578 _bt_hps_set_char_value(http_cp_obj_path, &cp, 1, 0);
1581 /* Characteristic HTTP Status Code */
1582 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1583 char_uuid = __hps_convert_uuid_to_uuid128(HTTP_STATUS_UUID);
1584 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_status_obj_path);
1585 if (ret != BLUETOOTH_ERROR_NONE) {
1586 BT_ERR("Failed to add new char %d", ret);
1590 ret = bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
1591 if (ret != BLUETOOTH_ERROR_NONE) {
1592 BT_ERR("Failed to add new char %d", ret);
1596 desc_uuid = __hps_convert_uuid_to_uuid128(HTTP_STATUS_CCC_DESC_UUID);
1597 ret = bluetooth_gatt_add_descriptor(http_status_obj_path, desc_uuid,
1598 (BLUETOOTH_GATT_PERMISSION_READ | BLUETOOTH_GATT_PERMISSION_WRITE),
1599 &http_status_desc_obj_path);
1600 if (ret != BLUETOOTH_ERROR_NONE) {
1601 BT_ERR("Failed to add new char descriptor %d", ret);
1605 /* Store Characterisitc information */
1606 char_info = g_new0(struct hps_char_info, 1);
1607 char_info->char_path = g_strdup(http_status_obj_path);
1608 hps_char_list = g_slist_append(hps_char_list, char_info);
1609 _bt_hps_set_char_value(http_status_obj_path, status, 3, 0);
1612 /* Characteristic HTTPS Security */
1613 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
1614 char_uuid = __hps_convert_uuid_to_uuid128(HTTP_SECURITY_UUID);
1615 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_security_obj_path);
1616 if (ret != BLUETOOTH_ERROR_NONE) {
1617 BT_ERR("Failed to add new char %d", ret);
1621 ret = bluetooth_gatt_set_characteristic_value(http_security_obj_path, &cp, 1);
1622 if (ret != BLUETOOTH_ERROR_NONE) {
1623 BT_ERR("Failed to add new char %d", ret);
1627 /* Store Characterisitc information */
1628 char_info = g_new0(struct hps_char_info, 1);
1629 char_info->char_path = g_strdup(http_security_obj_path);
1630 hps_char_list = g_slist_append(hps_char_list, char_info);
1631 _bt_hps_set_char_value(http_security_obj_path, &cp, 1, 0);
1634 ret = bluetooth_gatt_register_service(hps_obj_path);
1635 if (ret != BLUETOOTH_ERROR_NONE) {
1636 BT_ERR("Failed to register service %d", ret);
1640 ret = bluetooth_gatt_register_application();
1641 if (ret != BLUETOOTH_ERROR_NONE) {
1642 BT_ERR("Failed to register application %d", ret);
1650 delete_all_characterisitc();
1651 delete_all_notify_read_status();
1657 static void _bt_hps_sig_handler(int sig)
1663 BT_DBG("caught signal - sigterm\n");
1666 BT_DBG("caught signal - sigint\n");
1669 BT_DBG("caught signal - sigkill\n");
1672 BT_DBG("caught signal %d and ignored\n", sig);
1677 void _bt_hps_exit(void)
1682 if (g_uri != NULL) {
1687 if (g_header != NULL) {
1692 if (g_entity != NULL) {
1697 soup_session_abort(hps_soup_session);
1698 g_assert_cmpint(G_OBJECT(hps_soup_session)->ref_count, ==, 1);
1699 g_object_unref(hps_soup_session);
1702 delete_all_characterisitc();
1705 ret = bluetooth_gatt_deinit();
1706 if (ret != BLUETOOTH_ERROR_NONE)
1707 BT_ERR("Failed to Deinit GATT %d", ret);
1709 ret = bluetooth_unregister_callback();
1710 if (ret != BLUETOOTH_ERROR_NONE)
1711 BT_ERR("Failed to Unregister callback %d", ret);
1713 _bt_hps_deinit_event_receiver();
1715 _bt_hps_unregister_interface();
1717 if (main_loop != NULL)
1718 g_main_loop_quit(main_loop);
1721 void bt_hps_event_callback(int event, bluetooth_event_param_t* param,
1724 BT_DBG("HPS event %d", event);
1728 /* HTTP Proxy Service Main loop */
1731 struct sigaction sa;
1733 BT_ERR("Starting the bt-httpproxy daemon");
1735 /* Values taken from http://www.browserscope.org/ following
1736 * the rule "Do What Every Other Modern Browser Is Doing". They seem
1737 * to significantly improve page loading time compared to soup's
1739 * Change MAX_CONNECTIONS_PER_HOST value 6 -> 12, and maxConnections is changed from 35 to 60.
1740 * Enhanced network loading speed apply tunning value. */
1741 static const int maxConnections = 60;
1742 static const int maxConnectionsPerHost = 12;
1744 memset(&sa, 0, sizeof(sa));
1745 sa.sa_handler = _bt_hps_sig_handler;
1746 sa.sa_flags = SA_SIGINFO;
1747 sigaction(SIGINT, &sa, NULL);
1748 sigaction(SIGTERM, &sa, NULL);
1749 sigaction(SIGKILL, &sa, NULL);
1752 if (bluetooth_register_callback(bt_hps_event_callback, NULL) != BLUETOOTH_ERROR_NONE) {
1753 BT_ERR("bluetooth_register_callback returned failiure");
1758 if (_bt_hps_register_interface() != BLUETOOTH_ERROR_NONE) {
1759 BT_ERR("Fail to register http proxy service");
1763 if (_bt_hps_init_event_receiver() != BLUETOOTH_ERROR_NONE) {
1764 BT_ERR("Fail to init event reciever");
1768 hps_soup_session = soup_session_async_new();
1769 if (hps_soup_session == NULL) {
1770 BT_ERR("Failed to soup_session_async_new");
1773 /* Set Soup Session Fetures */
1774 g_object_set(hps_soup_session,
1775 SOUP_SESSION_MAX_CONNS, maxConnections,
1776 SOUP_SESSION_MAX_CONNS_PER_HOST, maxConnectionsPerHost,
1777 SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER,
1778 SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_SNIFFER,
1779 SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_RESOLVER_DEFAULT,
1780 SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
1783 main_loop = g_main_loop_new(NULL, FALSE);
1785 g_main_loop_run(main_loop);
1787 BT_DBG("g_main_loop_quit called!");
1789 if (main_loop != NULL)
1790 g_main_loop_unref(main_loop);