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 guint property_sub_id;
48 static guint adapter_sub_id;
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;
74 char *g_header = NULL;
75 char *g_entity = NULL;
77 static SoupSession *hps_soup_session = NULL;
78 static SoupMessage *hps_soup_msg = NULL;
81 static const gchar hps_introspection_xml[] =
83 " <interface name='org.projectx.httpproxy_service'>"
84 " <method name='enable'>"
85 " <arg type='y' name='status' direction='out'/>"
87 " <method name='disable'>"
88 " <arg type='y' name='status' direction='out'/>"
94 static void _bt_hps_set_char_value(const char *obj_path, const char* value, int value_length, int offset);
96 static void _hps_convert_address_to_hex(bluetooth_device_address_t *addr_hex, const char *addr_str)
98 char *ptr1, *ptr2, *ptr3, *ptr4, *ptr5;
100 if (addr_str == NULL || addr_str[0] == '\0')
103 addr_hex->addr[0] = strtol(addr_str, &ptr5, 16);
104 addr_hex->addr[1] = strtol(ptr5 + 1, &ptr4, 16);
105 addr_hex->addr[2] = strtol(ptr4 + 1, &ptr3, 16);
106 addr_hex->addr[3] = strtol(ptr3 + 1, &ptr2, 16);
107 addr_hex->addr[4] = strtol(ptr2 + 1, &ptr1, 16);
108 addr_hex->addr[5] = strtol(ptr1 + 1, NULL, 16);
111 static char *__hps_convert_uuid_to_uuid128(const char *uuid)
121 uuid128 = g_strdup_printf("0000%s-0000-1000-8000-00805F9B34FB", uuid);
126 uuid128 = g_strdup_printf("%s-0000-1000-8000-00805F9B34FB", uuid);
131 uuid128 = strdup(uuid);
141 static void _bt_hps_send_status_notification(unsigned short http_status,
142 unsigned char data_status,
143 bluetooth_device_address_t *unicast_address)
145 char status[3] = {0x00};
146 int ret = BLUETOOTH_ERROR_NONE;
150 status[0] = http_status & 0xFF;
151 status[1] = (http_status >> 8) & 0xFF;
152 status[2] = data_status;
153 BT_DBG("Status %d %04x", http_status, http_status);
155 /* Store the status value */
156 _bt_hps_set_char_value(http_status_obj_path, status, 3, 0);
158 /* Send unicast notification */
159 ret = bluetooth_gatt_server_set_notification(http_status_obj_path, unicast_address);
160 if (ret != BLUETOOTH_ERROR_NONE) {
161 BT_ERR("_bt_hps_send_status_notification failed");
164 ret = bluetooth_gatt_update_characteristic(http_status_obj_path, status, 3);
165 if (ret != BLUETOOTH_ERROR_NONE) {
166 BT_ERR("_bt_hps_send_status_notification failed");
172 static void _bt_httpproxy_method(GDBusConnection *connection,
174 const gchar *object_path,
175 const gchar *interface_name,
176 const gchar *method_name,
177 GVariant *parameters,
178 GDBusMethodInvocation *invocation,
183 BT_DBG("Method[%s] Object Path[%s] Interface Name[%s]",
184 method_name, object_path, interface_name);
186 if (g_strcmp0(method_name, "enable") == 0) {
187 g_dbus_method_invocation_return_value(invocation, g_variant_new("(y)", status));
188 } else if (g_strcmp0(method_name, "disable") == 0) {
190 g_dbus_method_invocation_return_value(invocation, g_variant_new("(y)", status));
196 static const GDBusInterfaceVTable hps_method_table = {
197 _bt_httpproxy_method,
202 static void _bt_hps_on_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
204 GDBusNodeInfo *node_info = NULL;
206 GError *error = NULL;
212 node_info = g_dbus_node_info_new_for_xml(hps_introspection_xml, &error);
214 BT_ERR("Failed to install: %s", error->message);
215 g_clear_error(&error);
219 object_id = g_dbus_connection_register_object(connection, BT_HPS_OBJECT_PATH,
220 node_info->interfaces[0],
223 g_dbus_node_info_unref(node_info);
224 if (object_id == 0) {
225 BT_ERR("Failed to register method table: %s", error->message);
232 static void _bt_hps_on_name_acquired(GDBusConnection *connection,
240 static void _bt_hps_on_name_lost(GDBusConnection *connection,
245 g_object_unref(g_conn);
247 g_bus_unown_name(g_owner_id);
252 int _bt_hps_register_interface(void)
258 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
260 G_BUS_NAME_OWNER_FLAGS_NONE,
261 _bt_hps_on_bus_acquired, _bt_hps_on_name_acquired, _bt_hps_on_name_lost,
263 g_owner_id = owner_id;
264 BT_DBG("owner_id is [%d]\n", owner_id);
266 return BLUETOOTH_ERROR_NONE;
269 void _bt_hps_unregister_interface(void)
273 g_object_unref(g_conn);
275 g_bus_unown_name(g_owner_id);
281 static struct hps_char_info *hps_get_char_value(const char *path)
285 for (tmp = hps_char_list; tmp != NULL; tmp = tmp->next) {
287 struct hps_char_info *char_info = tmp->data;
288 if (!g_strcmp0(char_info->char_path, path))
295 static int char_info_cmp(gconstpointer a1, gconstpointer a2)
297 const struct hps_char_info *attrib1 = a1;
298 const struct hps_char_info *attrib2 = a2;
300 return g_strcmp0(attrib1->char_path, attrib2->char_path);
303 static int notify_info_cmp(gconstpointer a1, gconstpointer a2)
305 const struct hps_notify_read_info *attrib1 = a1;
306 const struct hps_notify_read_info *attrib2 = a2;
308 return g_strcmp0(attrib1->char_path, attrib2->char_path);
311 static void _bt_hps_set_char_value(const char *obj_path, const char* value, int value_length, int offset)
317 for (tmp = hps_char_list; tmp != NULL; tmp = tmp->next) {
319 struct hps_char_info *char_info = tmp->data;
320 if (!g_strcmp0(char_info->char_path, obj_path)) {
322 if (char_info->char_value == NULL) {
323 char_info->char_value = g_malloc0(offset + value_length);
324 char_info->value_length = offset + value_length;
325 } else if (char_info->value_length >= offset + value_length) {
326 /* Just change from offset */
327 memcpy(&char_info->char_value[offset], value, value_length);
329 /* Values crossing pervious allocated limit realloc */
330 data = g_memdup(char_info->char_value, char_info->value_length);
331 char_info->char_value = g_try_realloc(char_info->char_value, offset + value_length);
332 memcpy(char_info->char_value, data, char_info->value_length);
333 memcpy(&char_info->char_value[offset], value, value_length);
334 char_info->value_length = offset + value_length;
337 hps_char_list = g_slist_insert_sorted(hps_char_list,
338 char_info, char_info_cmp);
346 static void _bt_hps_set_notify_read_status(const char *obj_path,
347 guint offset_status, guint read_status, int https_status)
349 struct hps_notify_read_info *notify_read_info = NULL;
352 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
354 notify_read_info = tmp->data;
355 if (!g_strcmp0(notify_read_info->char_path, obj_path)) {
356 notify_read_info->read_status = read_status;
357 notify_read_info->offset_status = offset_status;
358 notify_read_info->https_status = https_status;
359 hps_notify_read_list = g_slist_insert_sorted(hps_notify_read_list,
360 notify_read_info, notify_info_cmp);
366 if (!hps_notify_read_list) {
367 /* Store Notification information */
368 notify_read_info = g_new0(struct hps_notify_read_info, 1);
369 if (notify_read_info) {
370 notify_read_info->char_path = g_strdup(obj_path);
371 notify_read_info->read_status = read_status;
372 notify_read_info->offset_status = offset_status;
373 notify_read_info->https_status = https_status;
374 hps_notify_read_list = g_slist_append(hps_notify_read_list, notify_read_info);
378 /* Store Notification information */
379 notify_read_info = g_new0(struct hps_notify_read_info, 1);
380 if (notify_read_info) {
381 notify_read_info->char_path = g_strdup(obj_path);
382 notify_read_info->read_status = read_status;
383 notify_read_info->offset_status = offset_status;
384 notify_read_info->https_status = https_status;
385 hps_notify_read_list = g_slist_append(hps_notify_read_list, notify_read_info);
391 static struct hps_notify_read_info *_bt_hps_get_notify_read_status(const char *obj_path)
395 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
397 struct hps_notify_read_info *notify_read_info = tmp->data;
398 if (!g_strcmp0(notify_read_info->char_path, obj_path))
399 return notify_read_info;
406 static void delete_all_characterisitc(void)
409 for (tmp = hps_char_list; tmp != NULL; tmp = tmp->next) {
411 struct hps_char_info *char_info = tmp->data;
412 if (char_info->char_path)
413 g_free(char_info->char_path);
414 if (char_info->char_value)
415 g_free(char_info->char_value);
416 hps_char_list = g_slist_delete_link(hps_char_list, tmp->data);
419 g_slist_free(hps_char_list);
420 hps_char_list = NULL;
423 static void delete_all_notify_read_status(void)
426 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
428 struct hps_notify_read_info *notify_read_info = tmp->data;
429 if (notify_read_info->char_path)
430 g_free(notify_read_info->char_path);
431 hps_notify_read_list = g_slist_delete_link(hps_notify_read_list, tmp->data);
434 g_slist_free(hps_notify_read_list);
435 hps_notify_read_list = NULL;
438 static void delete_notify_read_status(const char *obj_path)
441 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
443 struct hps_notify_read_info *notify_read_info = tmp->data;
444 if (!g_strcmp0(notify_read_info->char_path, obj_path)) {
445 if (notify_read_info->char_path)
446 g_free(notify_read_info->char_path);
447 hps_notify_read_list = g_slist_delete_link(hps_notify_read_list, tmp->data);
455 int _bt_hps_uri_write_cb(char *uri, int len, int offset)
457 if ((len < 1) || (len > MAX_URI_LENGTH)) {
458 BT_ERR("Wrong URI length %d", len);
459 return BLUETOOTH_ERROR_INTERNAL;
462 /* g_uri will be used commonly for all HTTP methods whereever applicable */
465 g_uri = g_strndup(uri, len);
467 _bt_hps_set_char_value(http_uri_obj_path, g_uri, len, offset);
469 return BLUETOOTH_ERROR_NONE;
472 int _bt_hps_http_header_write_cb(char *header, int len, int offset)
474 if ((len < 1) || (len > MAX_HEADER_LENGTH)) {
475 BT_ERR("Wrong Header length %d", len);
476 return BLUETOOTH_ERROR_INTERNAL;
479 /* g_header will be used commonly for all HTTP methods where ever applicable
480 general-header, request-header, entity-header
484 g_header = g_strndup(header, len);
486 _bt_hps_set_char_value(http_hdr_obj_path, g_header, len, offset);
489 return BLUETOOTH_ERROR_NONE;
492 int _bt_hps_entity_body_write_cb(char *entity, int len, int offset)
494 if ((len < 1) || (len > MAX_ENTITY_LENGTH)) {
495 BT_ERR("Wrong Entity length %d", len);
496 return BLUETOOTH_ERROR_INTERNAL;
499 /* g_entity will be used commonly for all HTTP methods whereever applicable */
502 g_entity = g_strndup(entity, len);
504 _bt_hps_set_char_value(http_entity_obj_path, g_entity, len, offset);
507 return BLUETOOTH_ERROR_NONE;
511 int _bt_hps_read_cb(const char *obj_path, char **value, int *len)
513 struct hps_char_info *info = NULL;
514 struct hps_notify_read_info *notify_read_info = NULL;
515 guint data_status = -1;
517 gboolean is_header = FALSE;
520 BT_ERR("Wrong Obj path");
524 if (!g_strcmp0(http_hdr_obj_path, obj_path))
527 info = hps_get_char_value(obj_path);
530 if (info->char_value == NULL || info->value_length == 0)
533 notify_read_info = _bt_hps_get_notify_read_status(obj_path);
534 if (notify_read_info && notify_read_info->read_status != DS_BODY_RECEIVED &&
535 notify_read_info->read_status != DS_HEADER_RECEIVED) {
536 offset = notify_read_info->offset_status;
537 if ((info->value_length - offset) > 0 &&
538 (info->value_length - offset) > MAX_ENTITY_LENGTH) {
540 data_status = DS_HEADER_TRUNCATED;
542 data_status = DS_BODY_TRUNCATED;
543 _bt_hps_set_notify_read_status(obj_path, offset + MAX_ENTITY_LENGTH,
544 data_status, notify_read_info->https_status);
545 *value = g_strdup(&info->char_value[offset]);
546 *len = MAX_ENTITY_LENGTH;
547 } else if ((info->value_length - offset) > 0 &&
548 (info->value_length - offset) <= MAX_ENTITY_LENGTH) {
550 data_status = DS_HEADER_RECEIVED;
552 data_status = DS_BODY_RECEIVED;
553 _bt_hps_set_notify_read_status(obj_path, offset, data_status, notify_read_info->https_status);
554 *value = g_strdup(&info->char_value[offset]);
555 *len = info->value_length - offset;
557 } else if (notify_read_info && (notify_read_info->read_status == DS_BODY_RECEIVED ||
558 notify_read_info->read_status == DS_HEADER_RECEIVED)) {
560 data_status = DS_HEADER_RECEIVED;
562 data_status = DS_BODY_RECEIVED;
563 delete_notify_read_status(obj_path);
564 *value = g_strdup(&info->char_value[offset]);
565 *len = info->value_length;
573 void _bt_hps_head_response_cb(SoupSession *session,
574 SoupMessage *msg, gpointer user_data)
576 unsigned short http_status = 0x00;
578 unsigned char status[3] = {0x00};
580 const char *device_address = user_data;
581 bluetooth_device_address_t addr_hex = { {0,} };
582 unsigned char data_status = DS_NONE;
583 _hps_convert_address_to_hex(&addr_hex, device_address);
586 if (hps_soup_session != session) {
587 BT_ERR("Wrong Session");
592 BT_ERR("Wrong Message");
597 req_state = HTTP_REQ_STATE_EXECUTED;
599 http_status = msg->status_code;
601 // Process Header in Response Body
602 if (msg->response_headers) {
604 const char *content = NULL;
605 const char *length = NULL;
608 length = soup_message_headers_get_one(msg->request_headers,
610 // Check "Content-MD5" is the right name to get header content
611 content = soup_message_headers_get_one(msg->response_headers,
613 if (content == NULL || length == NULL) {
614 BT_ERR("Wrong Response Header");
615 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
619 hdr_len = soup_message_headers_get_content_length(msg->response_headers);
621 // Write Data to Header Characteristic
623 _bt_hps_set_char_value(http_hdr_obj_path, content, hdr_len, 0);
625 bluetooth_gatt_set_characteristic_value(http_hdr_obj_path, content, hdr_len);
627 // TODO : Handle Truncated Header
629 // Write Data to Status Code Characteristic
631 data_status = (hdr_len > MAX_ENTITY_LENGTH) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
633 if (data_status == DS_BODY_TRUNCATED && SOUP_STATUS_IS_SUCCESSFUL(http_status))
634 _bt_hps_set_notify_read_status(http_hdr_obj_path, 0, data_status, http_status);
636 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
638 status[0] = http_status & 0x0F;
639 status[1] = (http_status >> 8) & 0x0F;
640 status[2] = (hdr_len > MAX_HEADER_LENGTH) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
642 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
645 BT_ERR("HEAD Response is NULL");
646 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
652 void _bt_hps_http_response_cb(SoupSession *session,
653 SoupMessage *msg, gpointer user_data)
655 unsigned short http_status = 0x00;
657 unsigned char status[3] = {0x00};
659 const char *device_address = user_data;
660 bluetooth_device_address_t addr_hex = { {0,} };
661 unsigned char data_status = DS_NONE;
662 _hps_convert_address_to_hex(&addr_hex, device_address);
665 if (hps_soup_session != session) {
666 BT_ERR("Wrong Session");
671 BT_ERR("Wrong Message");
677 req_state = HTTP_REQ_STATE_EXECUTED;
679 http_status = msg->status_code;
681 // Write Data to Status Code Characteristic
683 status[0] = http_status & 0x0F;
684 status[1] = (http_status >> 8) & 0x0F;
685 status[2] = DS_HEADER_RECEIVED;
686 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
688 data_status = DS_HEADER_RECEIVED;
689 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
695 void _bt_hps_get_response_cb(SoupSession *session,
696 SoupMessage *msg, gpointer user_data)
698 SoupBuffer *body = NULL;
699 unsigned short http_status = 0x00;
701 unsigned char status[3] = {0x00};
703 const char *device_address = user_data;
704 bluetooth_device_address_t addr_hex = { {0,} };
705 unsigned char data_status = DS_NONE;
706 _hps_convert_address_to_hex(&addr_hex, device_address);
709 if (hps_soup_session != session) {
710 BT_ERR("Wrong Session");
715 BT_ERR("Wrong Message");
721 req_state = HTTP_REQ_STATE_EXECUTED;
723 http_status = msg->status_code;
725 // Process Entity Body in Response Message
726 if (msg->response_body) {
728 body = soup_message_body_flatten(msg->response_body);
730 BT_ERR("Wrong Response Body");
732 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
736 if (body->data == NULL || body->length <= 0) {
737 BT_ERR("Wrong Response");
738 soup_buffer_free(body);
740 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
744 // Write Data to Entity Body Characteristic
746 _bt_hps_set_char_value(http_entity_obj_path, body->data, body->length, 0);
748 bluetooth_gatt_set_characteristic_value(http_entity_obj_path, body->data, body->length);
750 // TODO : Handle Truncated Entiry Body
752 // Write Data to Status Code Characteristic
754 data_status = (body->length > MAX_ENTITY_LENGTH) ? DS_BODY_TRUNCATED : DS_BODY_RECEIVED;
756 if (data_status == DS_BODY_TRUNCATED && SOUP_STATUS_IS_SUCCESSFUL(http_status))
757 _bt_hps_set_notify_read_status(http_entity_obj_path, 0, data_status, http_status);
759 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
762 status[0] = http_status & 0x0F;
763 status[1] = (http_status >> 8) & 0x0F;
764 status[2] = (body->length > MAX_HEADER_LENGTH) ? DS_BODY_TRUNCATED : DS_BODY_TRUNCATED;
766 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
768 soup_buffer_free(body);
770 BT_ERR("GET Response Body is NULL");
772 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
776 // Process Header in Response Body
777 if (msg->response_headers) {
779 const char *content = NULL;
780 const char *length = NULL;
783 length = soup_message_headers_get_one(msg->request_headers,
785 // Check "Content-MD5" is the right name to get header content
786 content = soup_message_headers_get_one(msg->response_headers,
788 if (content == NULL || length == NULL) {
789 BT_ERR("Wrong Response Header");
790 data_status = DS_NONE;
791 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
795 hdr_len = soup_message_headers_get_content_length(msg->response_headers);
796 // Write Data to Header Characteristic
798 _bt_hps_set_char_value(http_hdr_obj_path, content, hdr_len, 0);
800 bluetooth_gatt_set_characteristic_value(http_hdr_obj_path, content, hdr_len);
802 // TODO : Handle Truncated Header
804 // Write Data to Status Code Characteristic
806 data_status = (hdr_len > MAX_HEADER_LENGTH) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
808 if (data_status == DS_HEADER_TRUNCATED && SOUP_STATUS_IS_SUCCESSFUL(http_status))
809 _bt_hps_set_notify_read_status(http_hdr_obj_path, 0, data_status, http_status);
811 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
813 status[0] = http_status & 0x0F;
814 status[1] = (http_status >> 8) & 0x0F;
815 status[2] = (hdr_len > MAX_HEADER_LENGTH) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
817 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
820 BT_ERR("GET Response Header is NULL");
822 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
830 int _bt_hps_control_point_write_cb(const char *value, int len, char *addr)
832 int _bt_hps_control_point_write_cb(char *value, int len)
836 GTlsCertificate *cert = NULL;
837 GTlsCertificateFlags flags;
838 gboolean https_status = FALSE;
839 int result = BLUETOOTH_ERROR_NONE;
840 BT_INFO("Opcode %0x", opcode);
843 _bt_hps_set_char_value(http_cp_obj_path, value, len, 0);
847 case HTTP_GET_REQUEST:
848 if (req_state == HTTP_REQ_STATE_EXECUTED) {
849 req_state = HTTP_REQ_STATE_INPROGRESS;
850 hps_soup_msg = soup_message_new("GET", g_uri);
852 g_object_ref(hps_soup_msg);
853 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, addr);
855 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, NULL);
858 BT_ERR("HTTP GET request in progress, message dropped");
859 result = BLUETOOTH_ERROR_INTERNAL;
863 case HTTP_POST_REQUEST:
864 if (req_state == HTTP_REQ_STATE_EXECUTED) {
865 req_state = HTTP_REQ_STATE_INPROGRESS;
866 hps_soup_msg = soup_message_new("POST", g_uri);
867 if (hps_soup_msg == NULL || g_entity == NULL) {
868 BT_ERR("Soup Message NULL");
869 result = BLUETOOTH_ERROR_INTERNAL;
870 req_state = HTTP_REQ_STATE_EXECUTED;
873 soup_message_set_request(hps_soup_msg, "text/xml", SOUP_MEMORY_COPY,
874 g_entity, strlen(g_entity));
876 g_object_ref(hps_soup_msg);
877 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
879 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
882 BT_ERR("HTTP POST request in progress, message dropped");
883 result = BLUETOOTH_ERROR_INTERNAL;
887 case HTTP_HEAD_REQUEST:
888 if (req_state == HTTP_REQ_STATE_EXECUTED) {
889 req_state = HTTP_REQ_STATE_INPROGRESS;
890 hps_soup_msg = soup_message_new("HEAD", g_uri);
891 if (hps_soup_msg == NULL) {
892 BT_ERR("Soup Message NULL");
893 result = BLUETOOTH_ERROR_INTERNAL;
894 req_state = HTTP_REQ_STATE_EXECUTED;
898 g_object_ref(hps_soup_msg);
899 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, addr);
901 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, NULL);
904 BT_ERR("HTTP HEAD request in progress, message dropped");
905 result = BLUETOOTH_ERROR_INTERNAL;
909 case HTTP_PUT_REQUEST:
910 if (req_state == HTTP_REQ_STATE_EXECUTED) {
912 req_state = HTTP_REQ_STATE_INPROGRESS;
913 hps_soup_msg = soup_message_new("PUT", g_uri);
914 if (hps_soup_msg == NULL || g_entity == NULL) {
915 BT_ERR("Soup Message NULL");
916 result = BLUETOOTH_ERROR_INTERNAL;
917 req_state = HTTP_REQ_STATE_EXECUTED;
920 buf = soup_buffer_new(SOUP_MEMORY_TAKE, g_entity, strlen(g_entity));
921 soup_message_body_append_buffer(hps_soup_msg->request_body, buf);
922 soup_message_body_set_accumulate(hps_soup_msg->request_body, FALSE);
924 g_object_ref(hps_soup_msg);
925 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
927 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
931 BT_ERR("HTTP PUT request in progress, message dropped");
932 result = BLUETOOTH_ERROR_INTERNAL;
936 case HTTP_DELETE_REQUEST:
937 if (req_state == HTTP_REQ_STATE_EXECUTED) {
938 req_state = HTTP_REQ_STATE_INPROGRESS;
939 hps_soup_msg = soup_message_new("DELETE", g_uri);
940 if (hps_soup_msg == NULL) {
941 BT_ERR("Soup Message NULL");
942 result = BLUETOOTH_ERROR_INTERNAL;
943 req_state = HTTP_REQ_STATE_EXECUTED;
947 g_object_ref(hps_soup_msg);
948 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
950 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
953 BT_ERR("HTTP DELETE request in progress, message dropped");
954 result = BLUETOOTH_ERROR_INTERNAL;
958 case HTTPS_GET_REQUEST:
959 if (req_state == HTTP_REQ_STATE_EXECUTED) {
960 req_state = HTTP_REQ_STATE_INPROGRESS;
961 hps_soup_msg = soup_message_new("GET", g_uri);
962 if (hps_soup_msg == NULL) {
963 BT_ERR("Soup Message NULL");
964 result = BLUETOOTH_ERROR_INTERNAL;
965 req_state = HTTP_REQ_STATE_EXECUTED;
969 g_object_ref(hps_soup_msg);
970 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, addr);
972 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, NULL);
974 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
976 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1, 0);
978 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
981 BT_ERR("HTTPS GET request in progress, message dropped");
982 result = BLUETOOTH_ERROR_INTERNAL;
986 case HTTPS_HEAD_REQUEST:
987 if (req_state == HTTP_REQ_STATE_EXECUTED) {
988 req_state = HTTP_REQ_STATE_INPROGRESS;
989 hps_soup_msg = soup_message_new("HEAD", g_uri);
990 if (hps_soup_msg == NULL) {
991 BT_ERR("Soup Message NULL");
992 result = BLUETOOTH_ERROR_INTERNAL;
993 req_state = HTTP_REQ_STATE_EXECUTED;
997 g_object_ref(hps_soup_msg);
998 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, addr);
1000 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, NULL);
1002 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
1004 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1, 0);
1006 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
1009 BT_ERR("HTTPS HEAD request in progress, message dropped");
1010 result = BLUETOOTH_ERROR_INTERNAL;
1014 case HTTPS_POST_REQUEST:
1015 if (req_state == HTTP_REQ_STATE_EXECUTED) {
1016 req_state = HTTP_REQ_STATE_INPROGRESS;
1017 hps_soup_msg = soup_message_new("POST", g_uri);
1018 if (hps_soup_msg == NULL) {
1019 BT_ERR("Soup Message NULL");
1020 result = BLUETOOTH_ERROR_INTERNAL;
1021 req_state = HTTP_REQ_STATE_EXECUTED;
1024 soup_message_set_request(hps_soup_msg, "text/xml", SOUP_MEMORY_STATIC,
1025 g_entity, strlen(g_entity));
1027 g_object_ref(hps_soup_msg);
1028 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
1030 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
1033 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
1035 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1, 0);
1037 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
1040 BT_ERR("HTTPS POST request in progress, message dropped");
1041 result = BLUETOOTH_ERROR_INTERNAL;
1045 case HTTPS_PUT_REQUEST:
1046 if (req_state == HTTP_REQ_STATE_EXECUTED) {
1048 req_state = HTTP_REQ_STATE_INPROGRESS;
1049 hps_soup_msg = soup_message_new("PUT", g_uri);
1050 if (hps_soup_msg == NULL) {
1051 BT_ERR("Soup Message NULL");
1052 result = BLUETOOTH_ERROR_INTERNAL;
1053 req_state = HTTP_REQ_STATE_EXECUTED;
1056 buf = soup_buffer_new(SOUP_MEMORY_TAKE, g_entity, strlen(g_entity));
1057 soup_message_body_append_buffer(hps_soup_msg->request_body, buf);
1058 soup_message_body_set_accumulate(hps_soup_msg->request_body, FALSE);
1060 g_object_ref(hps_soup_msg);
1061 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
1063 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
1065 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
1067 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1, 0);
1069 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
1072 BT_ERR("HTTPS PUT request in progress, message dropped");
1073 result = BLUETOOTH_ERROR_INTERNAL;
1077 case HTTPS_DELETE_REQUEST:
1078 if (req_state == HTTP_REQ_STATE_EXECUTED) {
1079 req_state = HTTP_REQ_STATE_INPROGRESS;
1080 hps_soup_msg = soup_message_new("DELETE", g_uri);
1081 if (hps_soup_msg == NULL) {
1082 BT_ERR("Soup Message NULL");
1083 result = BLUETOOTH_ERROR_INTERNAL;
1084 req_state = HTTP_REQ_STATE_EXECUTED;
1088 g_object_ref(hps_soup_msg);
1089 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
1091 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
1094 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
1096 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1, 0);
1098 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
1101 BT_ERR("HTTPS DELETE request in progress, message dropped");
1102 result = BLUETOOTH_ERROR_INTERNAL;
1106 case HTTP_REQUEST_CANCEL:
1107 /* Cancel the outstanding request */
1108 if (req_state == HTTP_REQ_STATE_INPROGRESS) {
1109 req_state = HTTP_REQ_STATE_IDLE;
1110 if (hps_soup_msg == NULL) {
1111 BT_ERR("Soup Message NULL");
1112 result = BLUETOOTH_ERROR_INTERNAL;
1113 req_state = HTTP_REQ_STATE_EXECUTED;
1116 soup_session_cancel_message(hps_soup_session, hps_soup_msg, SOUP_STATUS_CANCELLED);
1117 hps_soup_msg = NULL;
1122 BT_ERR("Unknown opcode %0x", opcode);
1123 result = BLUETOOTH_ERROR_INTERNAL;
1130 void _bt_hps_security_read_cb(char *value, int len)
1132 BT_INFO("HPS Client Read the value");
1137 void _bt_hps_gatt_char_property_changed_event(GVariant *msg,
1140 int result = BLUETOOTH_ERROR_NONE;
1141 GVariantIter value_iter;
1142 const char *property = NULL;
1143 const char * char_path = NULL;
1144 const char * svc_handle = NULL;
1145 GVariant *var = NULL;
1146 GVariant *val = NULL;
1147 g_variant_iter_init(&value_iter, msg);
1149 while ((g_variant_iter_loop(&value_iter, "{sv}", &property, &var))) {
1151 if (property == NULL) {
1152 BT_ERR("Property NULL");
1156 if (!g_strcmp0(property, "WriteValue")) {
1158 BT_INFO("WriteValue");
1159 BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
1166 g_variant_get(var, "(&s&s&syq@ay)", &char_path,
1167 &svc_handle, &addr, &req_id, &offset, &val);
1169 len = g_variant_get_size(val);
1171 BT_DBG("Len = %d, Offset = %d", len, offset);
1173 value = (char *) g_variant_get_data(val);
1176 if (!g_strcmp0(char_path, http_uri_obj_path)) {
1178 result = _bt_hps_uri_write_cb(value, len, offset);;
1179 } else if (!g_strcmp0(char_path, http_hdr_obj_path)) {
1180 /* Retrive HEADER */
1181 result = _bt_hps_http_header_write_cb(value, len, offset);
1182 } else if (!g_strcmp0(char_path, http_entity_obj_path)) {
1183 /* Retrive ENTITY BODY */
1184 result = _bt_hps_entity_body_write_cb(value, len, offset);
1185 } else if (!g_strcmp0(char_path, http_cp_obj_path)) {
1186 result = _bt_hps_control_point_write_cb(value, len, addr);
1188 BT_ERR("Wrong Object Path %s", char_path);
1189 result = BLUETOOTH_ERROR_INTERNAL;
1191 bluetooth_gatt_send_response(req_id, BLUETOOTH_GATT_ATT_REQUEST_TYPE_WRITE, result, 0, NULL, 0);
1193 BT_ERR("Array Len 0");
1196 BT_ERR("var==NULL");
1198 } else if (!g_strcmp0(property, "ReadValue")) {
1204 int data_status = -1;
1205 BT_INFO("ReadValue");
1206 BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
1208 g_variant_get(var, "(&s&s&syq)", &char_path, &svc_handle,
1209 &addr, &req_id, &offset);
1211 data_status = _bt_hps_read_cb(char_path, &value, &len);
1212 if (data_status >= DS_NONE) {
1213 struct hps_notify_read_info *notify_read_info = NULL;
1214 bluetooth_device_address_t addr_hex = { {0,} };
1215 _hps_convert_address_to_hex(&addr_hex, addr);
1216 bluetooth_gatt_send_response(req_id, BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ,
1217 BLUETOOTH_ERROR_NONE, offset, value, len);
1218 notify_read_info = _bt_hps_get_notify_read_status(char_path);
1219 if (notify_read_info) {
1220 _bt_hps_send_status_notification(notify_read_info->https_status,
1221 data_status, &addr_hex);
1223 if (data_status == DS_BODY_RECEIVED ||
1224 data_status == DS_HEADER_RECEIVED) {
1225 _bt_hps_set_char_value(char_path, NULL, 0, 0);
1231 BT_ERR("ReadValue failed %s", char_path);
1232 bluetooth_gatt_send_response(req_id, BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ,
1233 BLUETOOTH_ERROR_INTERNAL, offset, NULL, 0);
1240 void _bt_hps_gatt_char_property_changed_event(GVariant *msg,
1243 GVariantIter value_iter;
1244 char *property = NULL;
1245 char * char_handle = NULL;
1246 GVariant *val = NULL;
1247 int result = BLUETOOTH_ERROR_NONE;
1248 GVariant *param = NULL;
1249 g_variant_iter_init(&value_iter, msg);
1250 char_handle = g_strdup(path);
1252 while ((g_variant_iter_loop(&value_iter, "{sv}", &property, &val))) {
1254 if (property == NULL) {
1255 BT_ERR("Property NULL");
1259 if (strcasecmp(property, "ChangedValue") == 0) {
1262 GByteArray *gp_byte_array = NULL;
1263 BT_INFO("Type '%s'\n", g_variant_get_type_string(val));
1266 gp_byte_array = g_byte_array_new();
1267 len = g_variant_get_size(val);
1268 BT_DBG("Len = %d", len);
1269 g_byte_array_append(gp_byte_array,
1270 (const guint8 *)g_variant_get_data(val), len);
1271 if (gp_byte_array->len != 0) {
1272 GVariant *byte_array = NULL;
1273 byte_array = g_variant_new_from_data(
1274 G_VARIANT_TYPE_BYTESTRING,
1275 gp_byte_array->data,
1278 param = g_variant_new("(is@ay)", result, char_handle,
1281 if (strcmp(path, http_uri_obj_path)) {
1283 _bt_hps_uri_write_cb(NULL, len);
1284 } else if (strcmp(path, http_hdr_obj_path)) {
1286 _bt_hps_http_header_write_cb(NULL, len);
1287 } else if (strcmp(path, http_entity_obj_path)) {
1288 //Retrive ENTITY BODY
1289 _bt_hps_entity_body_write_cb(NULL, len);
1290 } else if (strcmp(path, http_cp_obj_path)) {
1291 _bt_hps_control_point_write_cb(NULL, len);
1292 } else if (strcmp(path, http_security_obj_path)) {
1293 _bt_hps_security_read_cb(NULL, len);
1295 BT_ERR("Wrong Object Path %s", path);
1298 BT_ERR("Array Len 0");
1300 g_byte_array_free(gp_byte_array, TRUE);
1302 BT_ERR("val==NULL");
1306 g_free(char_handle);
1312 void _bt_hps_property_event_filter(GDBusConnection *connection,
1313 const gchar *sender_name,
1314 const gchar *object_path,
1315 const gchar *interface_name,
1316 const gchar *signal_name,
1317 GVariant *parameters,
1322 if (signal_name == NULL) {
1323 BT_ERR("Wrong Signal");
1328 if (g_strcmp0(signal_name, PROPERTIES_CHANGED) == 0) {
1330 g_variant_get(parameters, "(@a{sv}@as)", &value, NULL);
1332 _bt_hps_gatt_char_property_changed_event(value, object_path);
1334 if (g_strcmp0(interface_name, BT_HPS_PROPERTIES_INTERFACE) == 0) {
1336 g_variant_get(parameters, "(&s@a{sv}@as)", &interface_name, &value, NULL);
1338 _bt_hps_gatt_char_property_changed_event(value, object_path);
1341 //BT_ERR("Wrong Interface %s", interface_name);
1348 void _bt_hps_adapter_event_filter(GDBusConnection *connection,
1349 const gchar *sender_name,
1350 const gchar *object_path,
1351 const gchar *interface_name,
1352 const gchar *signal_name,
1353 GVariant *parameters,
1356 int result = BLUETOOTH_ERROR_NONE;
1359 if (signal_name == NULL) {
1360 BT_ERR("Wrong Signal");
1364 BT_INFO("Interface %s, Signal %s", interface_name, signal_name);
1366 if (g_strcmp0(interface_name, BT_HPS_INTERFACE_NAME) == 0) {
1368 g_variant_get(parameters, "(&s@a{sv}@as)", &interface_name, &value, NULL);
1370 if (strcasecmp(signal_name, BLE_ENABLED) == 0) {
1371 g_variant_get(parameters, "(i)", &result);
1373 if (_bt_hps_prepare_httpproxy() != BLUETOOTH_ERROR_NONE) {
1374 BT_ERR("Fail to prepare HTTP Proxy");
1378 if (_bt_hps_set_advertising_data() != BLUETOOTH_ERROR_NONE) {
1379 BT_ERR("Fail to set advertising data");
1384 BT_ERR("Wrong Signal %s", signal_name);
1391 int _bt_hps_init_event_receiver()
1393 GError *error = NULL;
1398 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
1399 if (error != NULL) {
1400 BT_ERR("ERROR: Can't get on system bus [%s]", error->message);
1401 g_clear_error(&error);
1405 property_sub_id = g_dbus_connection_signal_subscribe(conn,
1406 NULL, BT_HPS_INTERFACE_NAME,
1407 PROPERTIES_CHANGED, BT_HPS_OBJECT_PATH, NULL, 0,
1408 _bt_hps_property_event_filter,
1411 adapter_sub_id = g_dbus_connection_signal_subscribe(conn,
1412 NULL, BT_HPS_INTERFACE_NAME,
1413 BLE_ENABLED, BT_HPS_OBJECT_PATH, NULL, 0,
1414 _bt_hps_adapter_event_filter,
1420 void _bt_hps_deinit_event_receiver(void)
1427 if (property_sub_id > 0) {
1428 g_dbus_connection_signal_unsubscribe(conn, property_sub_id);
1429 property_sub_id = 0;
1432 if (adapter_sub_id) {
1433 g_dbus_connection_signal_unsubscribe(conn, adapter_sub_id);
1442 int _bt_hps_set_advertising_data(void)
1447 guint8 data[4] = {0x03, 0x02, 0x23, 0x18};
1448 bluetooth_advertising_data_t adv;
1450 BT_DBG("%x %x %x %x", data[0], data[1], data[2], data[3]);
1451 memcpy(adv.data, data, sizeof(data));
1452 ret = bluetooth_set_advertising_data(0, &adv, sizeof(data));
1453 if (ret != BLUETOOTH_ERROR_NONE) {
1454 BT_ERR("Failed to set ADV data %d", ret);
1458 ret = bluetooth_set_advertising(0, TRUE);
1459 if (ret != BLUETOOTH_ERROR_NONE) {
1460 BT_ERR("Failed to set ADV %d", ret);
1467 int _bt_hps_prepare_httpproxy(void)
1469 int ret = BLUETOOTH_ERROR_NONE;
1473 bt_gatt_characteristic_property_t props;
1475 char value[MAX_URI_LENGTH] = { 0 };
1476 struct hps_char_info *char_info = NULL;
1478 char status[3] = { 0 };
1483 ret = bluetooth_gatt_init();
1484 if (ret != BLUETOOTH_ERROR_NONE) {
1485 BT_ERR("Failed to Init GATT %d", ret);
1489 service_uuid = __hps_convert_uuid_to_uuid128(HPS_UUID);
1490 ret = bluetooth_gatt_add_service(service_uuid, &hps_obj_path);
1491 if (ret != BLUETOOTH_ERROR_NONE) {
1492 BT_ERR("Failed to add service %d", ret);
1496 /* Characteristic URI */
1497 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1498 char_uuid = __hps_convert_uuid_to_uuid128(HTTP_URI_UUID);
1499 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_uri_obj_path);
1500 if (ret != BLUETOOTH_ERROR_NONE) {
1501 BT_ERR("Failed to add new char %d", ret);
1506 ret = bluetooth_gatt_set_characteristic_value(http_uri_obj_path, value, MAX_URI_LENGTH);
1507 if (ret != BLUETOOTH_ERROR_NONE) {
1508 BT_ERR("Failed to add new char %d", ret);
1512 /* Store requets information */
1513 char_info = g_new0(struct hps_char_info, 1);
1514 char_info->char_path = g_strdup(http_uri_obj_path);
1515 hps_char_list = g_slist_append(hps_char_list, char_info);
1516 _bt_hps_set_char_value(http_uri_obj_path, value, MAX_URI_LENGTH, 0);
1519 /* Characteristic HTTP Headers */
1520 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1521 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1522 char_uuid = __hps_convert_uuid_to_uuid128(HTTP_HDR_UUID);
1523 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_hdr_obj_path);
1524 if (ret != BLUETOOTH_ERROR_NONE) {
1525 BT_ERR("Failed to add new char %d", ret);
1529 ret = bluetooth_gatt_set_characteristic_value(http_hdr_obj_path, value, MAX_HEADER_LENGTH);
1530 if (ret != BLUETOOTH_ERROR_NONE) {
1531 BT_ERR("Failed to add new char %d", ret);
1535 /* Store Characterisitc information */
1536 char_info = g_new0(struct hps_char_info, 1);
1537 char_info->char_path = g_strdup(http_hdr_obj_path);
1538 hps_char_list = g_slist_append(hps_char_list, char_info);
1539 _bt_hps_set_char_value(http_hdr_obj_path, value, MAX_HEADER_LENGTH, 0);
1542 /* Characteristic HTTP Entity Body */
1543 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1544 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1545 char_uuid = __hps_convert_uuid_to_uuid128(HTTP_ENTITY_UUID);
1546 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_entity_obj_path);
1547 if (ret != BLUETOOTH_ERROR_NONE) {
1548 BT_ERR("Failed to add new char %d", ret);
1552 ret = bluetooth_gatt_set_characteristic_value(http_entity_obj_path, value, MAX_ENTITY_LENGTH);
1553 if (ret != BLUETOOTH_ERROR_NONE) {
1554 BT_ERR("Failed to add new char %d", ret);
1558 /* Store Characterisitc information */
1559 char_info = g_new0(struct hps_char_info, 1);
1560 char_info->char_path = g_strdup(http_entity_obj_path);
1561 hps_char_list = g_slist_append(hps_char_list, char_info);
1562 _bt_hps_set_char_value(http_entity_obj_path, value, MAX_ENTITY_LENGTH, 0);
1565 /* Characteristic HTTP Control Point */
1566 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1567 char_uuid = __hps_convert_uuid_to_uuid128(HTTP_CP_UUID);
1568 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_cp_obj_path);
1569 if (ret != BLUETOOTH_ERROR_NONE) {
1570 BT_ERR("Failed to add new char %d", ret);
1574 ret = bluetooth_gatt_set_characteristic_value(http_cp_obj_path, &cp, 1);
1575 if (ret != BLUETOOTH_ERROR_NONE) {
1576 BT_ERR("Failed to add new char %d", ret);
1580 /* Store Characterisitc information */
1581 char_info = g_new0(struct hps_char_info, 1);
1582 char_info->char_path = g_strdup(http_cp_obj_path);
1583 hps_char_list = g_slist_append(hps_char_list, char_info);
1584 _bt_hps_set_char_value(http_cp_obj_path, &cp, 1, 0);
1587 /* Characteristic HTTP Status Code */
1588 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1589 char_uuid = __hps_convert_uuid_to_uuid128(HTTP_STATUS_UUID);
1590 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_status_obj_path);
1591 if (ret != BLUETOOTH_ERROR_NONE) {
1592 BT_ERR("Failed to add new char %d", ret);
1596 ret = bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
1597 if (ret != BLUETOOTH_ERROR_NONE) {
1598 BT_ERR("Failed to add new char %d", ret);
1602 desc_uuid = __hps_convert_uuid_to_uuid128(HTTP_STATUS_CCC_DESC_UUID);
1603 ret = bluetooth_gatt_add_descriptor(http_status_obj_path, desc_uuid,
1604 (BLUETOOTH_GATT_PERMISSION_READ | BLUETOOTH_GATT_PERMISSION_WRITE),
1605 &http_status_desc_obj_path);
1606 if (ret != BLUETOOTH_ERROR_NONE) {
1607 BT_ERR("Failed to add new char descriptor %d", ret);
1611 /* Store Characterisitc information */
1612 char_info = g_new0(struct hps_char_info, 1);
1613 char_info->char_path = g_strdup(http_status_obj_path);
1614 hps_char_list = g_slist_append(hps_char_list, char_info);
1615 _bt_hps_set_char_value(http_status_obj_path, status, 3, 0);
1618 /* Characteristic HTTPS Security */
1619 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
1620 char_uuid = __hps_convert_uuid_to_uuid128(HTTP_SECURITY_UUID);
1621 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_security_obj_path);
1622 if (ret != BLUETOOTH_ERROR_NONE) {
1623 BT_ERR("Failed to add new char %d", ret);
1627 ret = bluetooth_gatt_set_characteristic_value(http_security_obj_path, &cp, 1);
1628 if (ret != BLUETOOTH_ERROR_NONE) {
1629 BT_ERR("Failed to add new char %d", ret);
1633 /* Store Characterisitc information */
1634 char_info = g_new0(struct hps_char_info, 1);
1635 char_info->char_path = g_strdup(http_security_obj_path);
1636 hps_char_list = g_slist_append(hps_char_list, char_info);
1637 _bt_hps_set_char_value(http_security_obj_path, &cp, 1, 0);
1640 ret = bluetooth_gatt_register_service(hps_obj_path);
1641 if (ret != BLUETOOTH_ERROR_NONE) {
1642 BT_ERR("Failed to register service %d", ret);
1646 ret = bluetooth_gatt_register_application();
1647 if (ret != BLUETOOTH_ERROR_NONE) {
1648 BT_ERR("Failed to register application %d", ret);
1656 delete_all_characterisitc();
1657 delete_all_notify_read_status();
1663 static void _bt_hps_sig_handler(int sig)
1669 BT_DBG("caught signal - sigterm\n");
1672 BT_DBG("caught signal - sigint\n");
1675 BT_DBG("caught signal - sigkill\n");
1678 BT_DBG("caught signal %d and ignored\n", sig);
1683 void _bt_hps_exit(void)
1688 if (g_uri != NULL) {
1693 if (g_header != NULL) {
1698 if (g_entity != NULL) {
1703 soup_session_abort(hps_soup_session);
1704 g_assert_cmpint(G_OBJECT(hps_soup_session)->ref_count, ==, 1);
1705 g_object_unref(hps_soup_session);
1708 delete_all_characterisitc();
1711 ret = bluetooth_gatt_deinit();
1712 if (ret != BLUETOOTH_ERROR_NONE)
1713 BT_ERR("Failed to Deinit GATT %d", ret);
1715 ret = bluetooth_unregister_callback();
1716 if (ret != BLUETOOTH_ERROR_NONE)
1717 BT_ERR("Failed to Unregister callback %d", ret);
1719 _bt_hps_deinit_event_receiver();
1721 _bt_hps_unregister_interface();
1723 if (main_loop != NULL)
1724 g_main_loop_quit(main_loop);
1727 void bt_hps_event_callback(int event, bluetooth_event_param_t* param,
1730 BT_DBG("HPS event %d", event);
1734 /* HTTP Proxy Service Main loop */
1737 struct sigaction sa;
1739 BT_ERR("Starting the bt-httpproxy daemon");
1741 /* Values taken from http://www.browserscope.org/ following
1742 * the rule "Do What Every Other Modern Browser Is Doing". They seem
1743 * to significantly improve page loading time compared to soup's
1745 * Change MAX_CONNECTIONS_PER_HOST value 6 -> 12, and maxConnections is changed from 35 to 60.
1746 * Enhanced network loading speed apply tunning value. */
1747 static const int maxConnections = 60;
1748 static const int maxConnectionsPerHost = 12;
1750 memset(&sa, 0, sizeof(sa));
1751 sa.sa_handler = _bt_hps_sig_handler;
1752 sa.sa_flags = SA_SIGINFO;
1753 sigaction(SIGINT, &sa, NULL);
1754 sigaction(SIGTERM, &sa, NULL);
1755 sigaction(SIGKILL, &sa, NULL);
1758 if (bluetooth_register_callback(bt_hps_event_callback, NULL) != BLUETOOTH_ERROR_NONE) {
1759 BT_ERR("bluetooth_register_callback returned failiure");
1764 if (_bt_hps_register_interface() != BLUETOOTH_ERROR_NONE) {
1765 BT_ERR("Fail to register http proxy service");
1769 if (_bt_hps_init_event_receiver() != BLUETOOTH_ERROR_NONE) {
1770 BT_ERR("Fail to init event reciever");
1774 hps_soup_session = soup_session_async_new();
1775 if (hps_soup_session == NULL) {
1776 BT_ERR("Failed to soup_session_async_new");
1779 /* Set Soup Session Fetures */
1780 g_object_set(hps_soup_session,
1781 SOUP_SESSION_MAX_CONNS, maxConnections,
1782 SOUP_SESSION_MAX_CONNS_PER_HOST, maxConnectionsPerHost,
1783 SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER,
1784 SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_SNIFFER,
1785 SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_RESOLVER_DEFAULT,
1786 SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
1789 main_loop = g_main_loop_new(NULL, FALSE);
1791 g_main_loop_run(main_loop);
1793 BT_DBG("g_main_loop_quit called!");
1795 if (main_loop != NULL)
1796 g_main_loop_unref(main_loop);