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);
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 void _bt_hps_send_status_notification(unsigned short http_status,
114 unsigned char data_status,
115 bluetooth_device_address_t *unicast_address)
117 char status[3] = {0x00};
118 int ret = BLUETOOTH_ERROR_NONE;
122 status[0] = http_status & 0xFF;
123 status[1] = (http_status >> 8) & 0xFF;
124 status[2] = data_status;
125 BT_DBG("Status %d %04x", http_status, http_status);
127 /* Store the status value */
128 _bt_hps_set_char_value(http_status_obj_path, status, 3);
130 /* Send unicast notification */
131 ret = bluetooth_gatt_server_set_notification(http_status_obj_path, unicast_address);
132 if (ret != BLUETOOTH_ERROR_NONE) {
133 BT_ERR("_bt_hps_send_status_notification failed");
136 ret = bluetooth_gatt_update_characteristic(http_status_obj_path, status, 3);
137 if (ret != BLUETOOTH_ERROR_NONE) {
138 BT_ERR("_bt_hps_send_status_notification failed");
144 static void _bt_httpproxy_method(GDBusConnection *connection,
146 const gchar *object_path,
147 const gchar *interface_name,
148 const gchar *method_name,
149 GVariant *parameters,
150 GDBusMethodInvocation *invocation,
155 BT_DBG("Method[%s] Object Path[%s] Interface Name[%s]",
156 method_name, object_path, interface_name);
158 if (g_strcmp0(method_name, "enable") == 0) {
159 g_dbus_method_invocation_return_value(invocation, g_variant_new("(y)", status));
160 } else if (g_strcmp0(method_name, "disable") == 0) {
162 g_dbus_method_invocation_return_value(invocation, g_variant_new("(y)", status));
168 static const GDBusInterfaceVTable hps_method_table = {
169 _bt_httpproxy_method,
174 static void _bt_hps_on_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
177 GError *error = NULL;
183 object_id = g_dbus_connection_register_object(connection, BT_HPS_OBJECT_PATH,
184 hps_node_info->interfaces[0],
187 if (object_id == 0) {
188 BT_ERR("Failed to register method table: %s", error->message);
190 g_dbus_node_info_unref(hps_node_info);
196 static void _bt_hps_on_name_acquired(GDBusConnection *connection,
204 static void _bt_hps_on_name_lost(GDBusConnection *connection,
209 g_object_unref(g_conn);
211 g_dbus_node_info_unref(hps_node_info);
212 g_bus_unown_name(g_owner_id);
217 int _bt_hps_register_interface(void)
219 GError *error = NULL;
224 hps_node_info = g_dbus_node_info_new_for_xml(hps_introspection_xml, &error);
225 if (!hps_node_info) {
226 BT_ERR("Failed to install: %s", error->message);
227 return BLUETOOTH_ERROR_INTERNAL;
230 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
232 G_BUS_NAME_OWNER_FLAGS_NONE,
233 _bt_hps_on_bus_acquired, _bt_hps_on_name_acquired, _bt_hps_on_name_lost,
235 g_owner_id = owner_id;
236 BT_DBG("owner_id is [%d]\n", owner_id);
238 return BLUETOOTH_ERROR_NONE;
241 void _bt_hps_unregister_interface(void)
245 g_object_unref(g_conn);
247 g_dbus_node_info_unref(hps_node_info);
248 g_bus_unown_name(g_owner_id);
254 static struct hps_char_info *hps_get_char_value(const char *path)
258 for (tmp = hps_char_list; tmp != NULL; tmp = tmp->next) {
260 struct hps_char_info *char_info = tmp->data;
261 if (!g_strcmp0(char_info->char_path, path))
268 static int char_info_cmp(gconstpointer a1, gconstpointer a2)
270 const struct hps_char_info *attrib1 = a1;
271 const struct hps_char_info *attrib2 = a2;
273 return g_strcmp0(attrib1->char_path, attrib2->char_path);
276 static int notify_info_cmp(gconstpointer a1, gconstpointer a2)
278 const struct hps_notify_read_info *attrib1 = a1;
279 const struct hps_notify_read_info *attrib2 = a2;
281 return g_strcmp0(attrib1->char_path, attrib2->char_path);
284 static void _bt_hps_set_char_value(const char *obj_path, const char* value, int value_length)
290 for (tmp = hps_char_list; tmp != NULL; tmp = tmp->next) {
292 struct hps_char_info *char_info = tmp->data;
293 if (!g_strcmp0(char_info->char_path, obj_path)) {
294 char_info->char_value = g_try_realloc(char_info->char_value, value_length);
295 if (char_info->char_value) {
296 memcpy(char_info->char_value, value, value_length);
297 char_info->value_length = value_length;
298 hps_char_list = g_slist_insert_sorted(hps_char_list,
299 char_info, char_info_cmp);
308 static void _bt_hps_set_notify_read_status(const char *obj_path,
309 guint offset_status, guint read_status, int https_status)
311 struct hps_notify_read_info *notify_read_info = NULL;
314 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
316 notify_read_info = tmp->data;
317 if (!g_strcmp0(notify_read_info->char_path, obj_path)) {
318 notify_read_info->read_status = read_status;
319 notify_read_info->offset_status = offset_status;
320 notify_read_info->https_status = https_status;
321 hps_notify_read_list = g_slist_insert_sorted(hps_notify_read_list,
322 notify_read_info, notify_info_cmp);
328 if (!hps_notify_read_list) {
329 /* Store Notification information */
330 notify_read_info = g_new0(struct hps_notify_read_info, 1);
331 if (notify_read_info) {
332 notify_read_info->char_path = g_strdup(obj_path);
333 notify_read_info->read_status = read_status;
334 notify_read_info->offset_status = offset_status;
335 notify_read_info->https_status = https_status;
336 hps_notify_read_list = g_slist_append(hps_notify_read_list, notify_read_info);
340 /* Store Notification information */
341 notify_read_info = g_new0(struct hps_notify_read_info, 1);
342 if (notify_read_info) {
343 notify_read_info->char_path = g_strdup(obj_path);
344 notify_read_info->read_status = read_status;
345 notify_read_info->offset_status = offset_status;
346 notify_read_info->https_status = https_status;
347 hps_notify_read_list = g_slist_append(hps_notify_read_list, notify_read_info);
353 static struct hps_notify_read_info *_bt_hps_get_notify_read_status(const char *obj_path)
357 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
359 struct hps_notify_read_info *notify_read_info = tmp->data;
360 if (!g_strcmp0(notify_read_info->char_path, obj_path))
361 return notify_read_info;
368 static void delete_all_characterisitc(void)
371 for (tmp = hps_char_list; tmp != NULL; tmp = tmp->next) {
373 struct hps_char_info *char_info = tmp->data;
374 if (char_info->char_path)
375 g_free(char_info->char_path);
376 if (char_info->char_value)
377 g_free(char_info->char_value);
378 hps_char_list = g_slist_delete_link(hps_char_list, tmp->data);
381 g_slist_free(hps_char_list);
382 hps_char_list = NULL;
385 static void delete_all_notify_read_status(void)
388 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
390 struct hps_notify_read_info *notify_read_info = tmp->data;
391 if (notify_read_info->char_path)
392 g_free(notify_read_info->char_path);
393 hps_notify_read_list = g_slist_delete_link(hps_notify_read_list, tmp->data);
396 g_slist_free(hps_notify_read_list);
397 hps_notify_read_list = NULL;
400 static void delete_notify_read_status(const char *obj_path)
403 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
405 struct hps_notify_read_info *notify_read_info = tmp->data;
406 if (!g_strcmp0(notify_read_info->char_path, obj_path)) {
407 if (notify_read_info->char_path)
408 g_free(notify_read_info->char_path);
409 hps_notify_read_list = g_slist_delete_link(hps_notify_read_list, tmp->data);
417 int _bt_hps_uri_write_cb(char *uri, int len)
419 if ((len < 1) || (len > MAX_URI_LENGTH)) {
420 BT_ERR("Wrong URI length %d", len);
421 return BLUETOOTH_ERROR_INTERNAL;
424 /* g_uri will be used commonly for all HTTP methods whereever applicable */
427 g_uri = g_strndup(uri, len);
429 _bt_hps_set_char_value(http_uri_obj_path, g_uri, len);
431 return BLUETOOTH_ERROR_NONE;
434 int _bt_hps_http_header_write_cb(char *header, int len)
436 if ((len < 1) || (len > MAX_HEADER_LENGTH)) {
437 BT_ERR("Wrong Header length %d", len);
438 return BLUETOOTH_ERROR_INTERNAL;
441 /* g_header will be used commonly for all HTTP methods where ever applicable
442 general-header, request-header, entity-header
446 g_header = g_strndup(header, len);
448 _bt_hps_set_char_value(http_hdr_obj_path, g_header, len);
451 return BLUETOOTH_ERROR_NONE;
454 int _bt_hps_entity_body_write_cb(char *entity, int len)
456 if ((len < 1) || (len > MAX_ENTITY_LENGTH)) {
457 BT_ERR("Wrong Entity length %d", len);
458 return BLUETOOTH_ERROR_INTERNAL;
461 /* g_entity will be used commonly for all HTTP methods whereever applicable */
464 g_entity = g_strndup(entity, len);
466 _bt_hps_set_char_value(http_entity_obj_path, g_entity, len);
469 return BLUETOOTH_ERROR_NONE;
473 int _bt_hps_read_cb(const char *obj_path, char **value, int *len)
475 struct hps_char_info *info = NULL;
476 struct hps_notify_read_info *notify_read_info = NULL;
477 guint data_status = -1;
479 gboolean is_header = FALSE;
482 BT_ERR("Wrong Obj path");
486 if (!g_strcmp0(http_hdr_obj_path, obj_path))
489 info = hps_get_char_value(obj_path);
492 if (info->char_value == NULL || info->value_length == 0)
495 notify_read_info = _bt_hps_get_notify_read_status(obj_path);
496 if (notify_read_info && notify_read_info->read_status != DS_BODY_RECEIVED &&
497 notify_read_info->read_status != DS_HEADER_RECEIVED) {
498 offset = notify_read_info->offset_status;
499 if ((info->value_length - offset) > 0 &&
500 (info->value_length - offset) > MAX_ENTITY_LENGTH) {
502 data_status = DS_HEADER_TRUNCATED;
504 data_status = DS_BODY_TRUNCATED;
505 _bt_hps_set_notify_read_status(obj_path, offset + MAX_ENTITY_LENGTH,
506 data_status, notify_read_info->https_status);
507 *value = g_strdup(&info->char_value[offset]);
508 *len = info->value_length;
509 } else if ((info->value_length - offset) > 0 &&
510 (info->value_length - offset) <= MAX_ENTITY_LENGTH) {
512 data_status = DS_HEADER_RECEIVED;
514 data_status = DS_BODY_RECEIVED;
515 _bt_hps_set_notify_read_status(obj_path, offset, data_status, notify_read_info->https_status);
516 *value = g_strdup(&info->char_value[offset]);
517 *len = info->value_length;
519 } else if (notify_read_info && (notify_read_info->read_status == DS_BODY_RECEIVED ||
520 notify_read_info->read_status == DS_HEADER_RECEIVED)) {
522 data_status = DS_HEADER_RECEIVED;
524 data_status = DS_BODY_RECEIVED;
525 delete_notify_read_status(obj_path);
526 *value = g_strdup(&info->char_value[offset]);
527 *len = info->value_length;
535 void _bt_hps_head_response_cb(SoupSession *session,
536 SoupMessage *msg, gpointer user_data)
538 unsigned short http_status = 0x00;
540 unsigned char status[3] = {0x00};
542 const char *device_address = user_data;
543 bluetooth_device_address_t addr_hex = { {0,} };
544 unsigned char data_status = DS_NONE;
545 _hps_convert_address_to_hex(&addr_hex, device_address);
548 if (hps_soup_session != session) {
549 BT_ERR("Wrong Session");
554 BT_ERR("Wrong Message");
559 req_state = HTTP_REQ_STATE_EXECUTED;
561 http_status = msg->status_code;
563 // Process Header in Response Body
564 if (msg->response_headers) {
566 const char *content = NULL;
567 const char *length = NULL;
570 length = soup_message_headers_get_one(msg->request_headers,
572 // Check "Content-MD5" is the right name to get header content
573 content = soup_message_headers_get_one(msg->response_headers,
575 if (content == NULL || length == NULL) {
576 BT_ERR("Wrong Response Header");
577 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
581 hdr_len = soup_message_headers_get_content_length(msg->response_headers);
583 // Write Data to Header Characteristic
585 _bt_hps_set_char_value(http_hdr_obj_path, content, hdr_len);
587 bluetooth_gatt_set_characteristic_value(http_hdr_obj_path, content, hdr_len);
589 // TODO : Handle Truncated Header
591 // Write Data to Status Code Characteristic
593 data_status = (hdr_len > MAX_ENTITY_LENGTH) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
594 if (data_status == DS_BODY_TRUNCATED && SOUP_STATUS_IS_SUCCESSFUL(http_status))
595 _bt_hps_set_notify_read_status(http_hdr_obj_path, data_status, 0, http_status);
597 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
599 status[0] = http_status & 0x0F;
600 status[1] = (http_status >> 8) & 0x0F;
601 status[2] = (hdr_len > MAX_HEADER_LENGTH) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
603 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
606 BT_ERR("HEAD Response is NULL");
607 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
613 void _bt_hps_http_response_cb(SoupSession *session,
614 SoupMessage *msg, gpointer user_data)
616 unsigned short http_status = 0x00;
618 unsigned char status[3] = {0x00};
620 const char *device_address = user_data;
621 bluetooth_device_address_t addr_hex = { {0,} };
622 unsigned char data_status = DS_NONE;
623 _hps_convert_address_to_hex(&addr_hex, device_address);
626 if (hps_soup_session != session) {
627 BT_ERR("Wrong Session");
632 BT_ERR("Wrong Message");
638 req_state = HTTP_REQ_STATE_EXECUTED;
640 http_status = msg->status_code;
642 // Write Data to Status Code Characteristic
644 status[0] = http_status & 0x0F;
645 status[1] = (http_status >> 8) & 0x0F;
646 status[2] = DS_HEADER_RECEIVED;
647 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
649 data_status = DS_HEADER_RECEIVED;
650 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
656 void _bt_hps_get_response_cb(SoupSession *session,
657 SoupMessage *msg, gpointer user_data)
659 SoupBuffer *body = NULL;
660 unsigned short http_status = 0x00;
662 unsigned char status[3] = {0x00};
664 const char *device_address = user_data;
665 bluetooth_device_address_t addr_hex = { {0,} };
666 unsigned char data_status = DS_NONE;
667 _hps_convert_address_to_hex(&addr_hex, device_address);
670 if (hps_soup_session != session) {
671 BT_ERR("Wrong Session");
676 BT_ERR("Wrong Message");
682 req_state = HTTP_REQ_STATE_EXECUTED;
684 http_status = msg->status_code;
686 // Process Entity Body in Response Message
687 if (msg->response_body) {
689 body = soup_message_body_flatten(msg->response_body);
691 BT_ERR("Wrong Response Body");
693 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
697 if (body->data == NULL || body->length <= 0) {
698 BT_ERR("Wrong Response");
699 soup_buffer_free(body);
701 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
705 // Write Data to Entity Body Characteristic
707 _bt_hps_set_char_value(http_entity_obj_path, body->data, body->length);
709 bluetooth_gatt_set_characteristic_value(http_entity_obj_path, body->data, body->length);
711 // TODO : Handle Truncated Entiry Body
713 // Write Data to Status Code Characteristic
715 data_status = (body->length > MAX_ENTITY_LENGTH) ? DS_BODY_TRUNCATED : DS_BODY_RECEIVED;
716 if (data_status == DS_BODY_TRUNCATED && SOUP_STATUS_IS_SUCCESSFUL(http_status))
717 _bt_hps_set_notify_read_status(http_entity_obj_path, data_status, 0, http_status);
719 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
722 status[0] = http_status & 0x0F;
723 status[1] = (http_status >> 8) & 0x0F;
724 status[2] = (body->length > MAX_HEADER_LENGTH) ? DS_BODY_TRUNCATED : DS_BODY_TRUNCATED;
726 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
728 soup_buffer_free(body);
730 BT_ERR("GET Response Body is NULL");
732 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
736 // Process Header in Response Body
737 if (msg->response_headers) {
739 const char *content = NULL;
740 const char *length = NULL;
743 length = soup_message_headers_get_one(msg->request_headers,
745 // Check "Content-MD5" is the right name to get header content
746 content = soup_message_headers_get_one(msg->response_headers,
748 if (content == NULL || length == NULL) {
749 BT_ERR("Wrong Response Header");
750 data_status = DS_NONE;
751 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
755 hdr_len = soup_message_headers_get_content_length(msg->response_headers);
756 // Write Data to Header Characteristic
758 _bt_hps_set_char_value(http_hdr_obj_path, content, hdr_len);
760 bluetooth_gatt_set_characteristic_value(http_hdr_obj_path, content, hdr_len);
762 // TODO : Handle Truncated Header
764 // Write Data to Status Code Characteristic
766 data_status = (hdr_len > MAX_HEADER_LENGTH) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
767 if (data_status == DS_HEADER_TRUNCATED && SOUP_STATUS_IS_SUCCESSFUL(http_status))
768 _bt_hps_set_notify_read_status(http_hdr_obj_path, data_status, 0, http_status);
770 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
772 status[0] = http_status & 0x0F;
773 status[1] = (http_status >> 8) & 0x0F;
774 status[2] = (hdr_len > MAX_HEADER_LENGTH) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
776 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
779 BT_ERR("GET Response Header is NULL");
781 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
789 int _bt_hps_control_point_write_cb(const char *value, int len, char *addr)
791 int _bt_hps_control_point_write_cb(char *value, int len)
795 GTlsCertificate *cert = NULL;
796 GTlsCertificateFlags flags;
797 gboolean https_status = FALSE;
798 int result = BLUETOOTH_ERROR_NONE;
799 BT_INFO("Opcode %0x", opcode);
802 _bt_hps_set_char_value(http_cp_obj_path, value, len);
806 case HTTP_GET_REQUEST:
807 if (req_state == HTTP_REQ_STATE_EXECUTED) {
808 req_state = HTTP_REQ_STATE_INPROGRESS;
809 hps_soup_msg = soup_message_new("GET", g_uri);
811 g_object_ref(hps_soup_msg);
812 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, addr);
814 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, NULL);
817 BT_ERR("HTTP GET request in progress, message dropped");
818 result = BLUETOOTH_ERROR_INTERNAL;
822 case HTTP_POST_REQUEST:
823 if (req_state == HTTP_REQ_STATE_EXECUTED) {
824 req_state = HTTP_REQ_STATE_INPROGRESS;
825 hps_soup_msg = soup_message_new("POST", g_uri);
826 if (hps_soup_msg == NULL || g_entity == NULL) {
827 BT_ERR("Soup Message NULL");
828 result = BLUETOOTH_ERROR_INTERNAL;
829 req_state = HTTP_REQ_STATE_EXECUTED;
832 soup_message_set_request(hps_soup_msg, "text/xml", SOUP_MEMORY_COPY,
833 g_entity, strlen(g_entity));
835 g_object_ref(hps_soup_msg);
836 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
838 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
841 BT_ERR("HTTP POST request in progress, message dropped");
842 result = BLUETOOTH_ERROR_INTERNAL;
846 case HTTP_HEAD_REQUEST:
847 if (req_state == HTTP_REQ_STATE_EXECUTED) {
848 req_state = HTTP_REQ_STATE_INPROGRESS;
849 hps_soup_msg = soup_message_new("HEAD", g_uri);
850 if (hps_soup_msg == NULL) {
851 BT_ERR("Soup Message NULL");
852 result = BLUETOOTH_ERROR_INTERNAL;
853 req_state = HTTP_REQ_STATE_EXECUTED;
857 g_object_ref(hps_soup_msg);
858 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, addr);
860 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, NULL);
863 BT_ERR("HTTP HEAD request in progress, message dropped");
864 result = BLUETOOTH_ERROR_INTERNAL;
868 case HTTP_PUT_REQUEST:
869 if (req_state == HTTP_REQ_STATE_EXECUTED) {
871 req_state = HTTP_REQ_STATE_INPROGRESS;
872 hps_soup_msg = soup_message_new("PUT", g_uri);
873 if (hps_soup_msg == NULL || g_entity == NULL) {
874 BT_ERR("Soup Message NULL");
875 result = BLUETOOTH_ERROR_INTERNAL;
876 req_state = HTTP_REQ_STATE_EXECUTED;
879 buf = soup_buffer_new(SOUP_MEMORY_TAKE, g_entity, strlen(g_entity));
880 soup_message_body_append_buffer(hps_soup_msg->request_body, buf);
881 soup_message_body_set_accumulate(hps_soup_msg->request_body, FALSE);
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);
890 BT_ERR("HTTP PUT request in progress, message dropped");
891 result = BLUETOOTH_ERROR_INTERNAL;
895 case HTTP_DELETE_REQUEST:
896 if (req_state == HTTP_REQ_STATE_EXECUTED) {
897 req_state = HTTP_REQ_STATE_INPROGRESS;
898 hps_soup_msg = soup_message_new("DELETE", g_uri);
899 if (hps_soup_msg == NULL) {
900 BT_ERR("Soup Message NULL");
901 result = BLUETOOTH_ERROR_INTERNAL;
902 req_state = HTTP_REQ_STATE_EXECUTED;
906 g_object_ref(hps_soup_msg);
907 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
909 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
912 BT_ERR("HTTP DELETE request in progress, message dropped");
913 result = BLUETOOTH_ERROR_INTERNAL;
917 case HTTPS_GET_REQUEST:
918 if (req_state == HTTP_REQ_STATE_EXECUTED) {
919 req_state = HTTP_REQ_STATE_INPROGRESS;
920 hps_soup_msg = soup_message_new("GET", g_uri);
921 if (hps_soup_msg == NULL) {
922 BT_ERR("Soup Message NULL");
923 result = BLUETOOTH_ERROR_INTERNAL;
924 req_state = HTTP_REQ_STATE_EXECUTED;
928 g_object_ref(hps_soup_msg);
929 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, addr);
931 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, NULL);
933 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
935 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1);
937 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
940 BT_ERR("HTTPS GET request in progress, message dropped");
941 result = BLUETOOTH_ERROR_INTERNAL;
945 case HTTPS_HEAD_REQUEST:
946 if (req_state == HTTP_REQ_STATE_EXECUTED) {
947 req_state = HTTP_REQ_STATE_INPROGRESS;
948 hps_soup_msg = soup_message_new("HEAD", g_uri);
949 if (hps_soup_msg == NULL) {
950 BT_ERR("Soup Message NULL");
951 result = BLUETOOTH_ERROR_INTERNAL;
952 req_state = HTTP_REQ_STATE_EXECUTED;
956 g_object_ref(hps_soup_msg);
957 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, addr);
959 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, NULL);
961 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
963 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1);
965 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
968 BT_ERR("HTTPS HEAD request in progress, message dropped");
969 result = BLUETOOTH_ERROR_INTERNAL;
973 case HTTPS_POST_REQUEST:
974 if (req_state == HTTP_REQ_STATE_EXECUTED) {
975 req_state = HTTP_REQ_STATE_INPROGRESS;
976 hps_soup_msg = soup_message_new("POST", g_uri);
977 if (hps_soup_msg == NULL) {
978 BT_ERR("Soup Message NULL");
979 result = BLUETOOTH_ERROR_INTERNAL;
980 req_state = HTTP_REQ_STATE_EXECUTED;
983 soup_message_set_request(hps_soup_msg, "text/xml", SOUP_MEMORY_STATIC,
984 g_entity, strlen(g_entity));
986 g_object_ref(hps_soup_msg);
987 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
989 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
992 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
994 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1);
996 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
999 BT_ERR("HTTPS POST request in progress, message dropped");
1000 result = BLUETOOTH_ERROR_INTERNAL;
1004 case HTTPS_PUT_REQUEST:
1005 if (req_state == HTTP_REQ_STATE_EXECUTED) {
1007 req_state = HTTP_REQ_STATE_INPROGRESS;
1008 hps_soup_msg = soup_message_new("PUT", g_uri);
1009 if (hps_soup_msg == NULL) {
1010 BT_ERR("Soup Message NULL");
1011 result = BLUETOOTH_ERROR_INTERNAL;
1012 req_state = HTTP_REQ_STATE_EXECUTED;
1015 buf = soup_buffer_new(SOUP_MEMORY_TAKE, g_entity, strlen(g_entity));
1016 soup_message_body_append_buffer(hps_soup_msg->request_body, buf);
1017 soup_message_body_set_accumulate(hps_soup_msg->request_body, FALSE);
1019 g_object_ref(hps_soup_msg);
1020 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
1022 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
1024 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
1026 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1);
1028 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
1031 BT_ERR("HTTPS PUT request in progress, message dropped");
1032 result = BLUETOOTH_ERROR_INTERNAL;
1036 case HTTPS_DELETE_REQUEST:
1037 if (req_state == HTTP_REQ_STATE_EXECUTED) {
1038 req_state = HTTP_REQ_STATE_INPROGRESS;
1039 hps_soup_msg = soup_message_new("DELETE", g_uri);
1040 if (hps_soup_msg == NULL) {
1041 BT_ERR("Soup Message NULL");
1042 result = BLUETOOTH_ERROR_INTERNAL;
1043 req_state = HTTP_REQ_STATE_EXECUTED;
1047 g_object_ref(hps_soup_msg);
1048 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
1050 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
1053 https_status = soup_message_get_https_status(hps_soup_msg, &cert, &flags);
1055 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1);
1057 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
1060 BT_ERR("HTTPS DELETE request in progress, message dropped");
1061 result = BLUETOOTH_ERROR_INTERNAL;
1065 case HTTP_REQUEST_CANCEL:
1066 /* Cancel the outstanding request */
1067 if (req_state == HTTP_REQ_STATE_INPROGRESS) {
1068 req_state = HTTP_REQ_STATE_IDLE;
1069 if (hps_soup_msg == NULL) {
1070 BT_ERR("Soup Message NULL");
1071 result = BLUETOOTH_ERROR_INTERNAL;
1072 req_state = HTTP_REQ_STATE_EXECUTED;
1075 soup_session_cancel_message(hps_soup_session, hps_soup_msg, SOUP_STATUS_CANCELLED);
1076 hps_soup_msg = NULL;
1081 BT_ERR("Unknown opcode %0x", opcode);
1082 result = BLUETOOTH_ERROR_INTERNAL;
1089 void _bt_hps_security_read_cb(char *value, int len)
1091 BT_INFO("HPS Client Read the value");
1096 void _bt_hps_gatt_char_property_changed_event(GVariant *msg,
1099 int result = BLUETOOTH_ERROR_NONE;
1100 GVariantIter value_iter;
1101 const char *property = NULL;
1102 const char * char_path = NULL;
1103 const char * svc_handle = NULL;
1104 GVariant *var = NULL;
1105 GVariant *val = NULL;
1106 g_variant_iter_init(&value_iter, msg);
1108 while ((g_variant_iter_loop(&value_iter, "{sv}", &property, &var))) {
1110 if (property == NULL) {
1111 BT_ERR("Property NULL");
1115 if (!g_strcmp0(property, "WriteValue")) {
1117 BT_INFO("WriteValue");
1118 BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
1125 g_variant_get(var, "(&s&s&syq@ay)", &char_path,
1126 &svc_handle, &addr, &req_id, &offset, &val);
1128 len = g_variant_get_size(val);
1130 BT_DBG("Len = %d", len);
1132 value = (char *) g_variant_get_data(val);
1135 if (!g_strcmp0(char_path, http_uri_obj_path)) {
1137 result = _bt_hps_uri_write_cb(value, len);
1138 } else if (!g_strcmp0(char_path, http_hdr_obj_path)) {
1139 /* Retrive HEADER */
1140 result = _bt_hps_http_header_write_cb(value, len);
1141 } else if (!g_strcmp0(char_path, http_entity_obj_path)) {
1142 /* Retrive ENTITY BODY */
1143 result = _bt_hps_entity_body_write_cb(value, len);
1144 } else if (!g_strcmp0(char_path, http_cp_obj_path)) {
1145 result = _bt_hps_control_point_write_cb(value, len, addr);
1147 BT_ERR("Wrong Object Path %s", char_path);
1148 result = BLUETOOTH_ERROR_INTERNAL;
1150 bluetooth_gatt_send_response(req_id, BLUETOOTH_GATT_ATT_REQUEST_TYPE_WRITE, result, 0, NULL, 0);
1152 BT_ERR("Array Len 0");
1155 BT_ERR("var==NULL");
1157 } else if (!g_strcmp0(property, "ReadValue")) {
1163 int data_status = -1;
1164 BT_INFO("ReadValue");
1165 BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
1167 g_variant_get(var, "(&s&s&syq)", &char_path, &svc_handle,
1168 &addr, &req_id, &offset);
1170 data_status = _bt_hps_read_cb(char_path, &value, &len);
1171 if (data_status >= DS_NONE) {
1172 struct hps_notify_read_info *notify_read_info = NULL;
1173 bluetooth_device_address_t addr_hex = { {0,} };
1174 _hps_convert_address_to_hex(&addr_hex, addr);
1175 bluetooth_gatt_send_response(req_id, BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ,
1176 BLUETOOTH_ERROR_NONE, offset, value, len);
1177 notify_read_info = _bt_hps_get_notify_read_status(char_path);
1178 if (notify_read_info) {
1179 _bt_hps_send_status_notification(notify_read_info->https_status,
1180 data_status, &addr_hex);
1182 if (data_status == DS_BODY_RECEIVED ||
1183 data_status == DS_HEADER_RECEIVED) {
1184 _bt_hps_set_char_value(char_path, NULL, 0);
1190 BT_ERR("ReadValue failed %s", char_path);
1191 bluetooth_gatt_send_response(req_id, BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ,
1192 BLUETOOTH_ERROR_INTERNAL, offset, NULL, 0);
1199 void _bt_hps_gatt_char_property_changed_event(GVariant *msg,
1202 GVariantIter value_iter;
1203 char *property = NULL;
1204 char * char_handle = NULL;
1205 GVariant *val = NULL;
1206 int result = BLUETOOTH_ERROR_NONE;
1207 GVariant *param = NULL;
1208 g_variant_iter_init(&value_iter, msg);
1209 char_handle = g_strdup(path);
1211 while ((g_variant_iter_loop(&value_iter, "{sv}", &property, &val))) {
1213 if (property == NULL) {
1214 BT_ERR("Property NULL");
1218 if (strcasecmp(property, "ChangedValue") == 0) {
1221 GByteArray *gp_byte_array = NULL;
1222 BT_INFO("Type '%s'\n", g_variant_get_type_string(val));
1225 gp_byte_array = g_byte_array_new();
1226 len = g_variant_get_size(val);
1227 BT_DBG("Len = %d", len);
1228 g_byte_array_append(gp_byte_array,
1229 (const guint8 *)g_variant_get_data(val), len);
1230 if (gp_byte_array->len != 0) {
1231 GVariant *byte_array = NULL;
1232 byte_array = g_variant_new_from_data(
1233 G_VARIANT_TYPE_BYTESTRING,
1234 gp_byte_array->data,
1237 param = g_variant_new("(is@ay)", result, char_handle,
1240 if (strcmp(path, http_uri_obj_path)) {
1242 _bt_hps_uri_write_cb(NULL, len);
1243 } else if (strcmp(path, http_hdr_obj_path)) {
1245 _bt_hps_http_header_write_cb(NULL, len);
1246 } else if (strcmp(path, http_entity_obj_path)) {
1247 //Retrive ENTITY BODY
1248 _bt_hps_entity_body_write_cb(NULL, len);
1249 } else if (strcmp(path, http_cp_obj_path)) {
1250 _bt_hps_control_point_write_cb(NULL, len);
1251 } else if (strcmp(path, http_security_obj_path)) {
1252 _bt_hps_security_read_cb(NULL, len);
1254 BT_ERR("Wrong Object Path %s", path);
1257 BT_ERR("Array Len 0");
1259 g_byte_array_free(gp_byte_array, TRUE);
1261 BT_ERR("val==NULL");
1265 g_free(char_handle);
1271 void _bt_hps_property_event_filter(GDBusConnection *connection,
1272 const gchar *sender_name,
1273 const gchar *object_path,
1274 const gchar *interface_name,
1275 const gchar *signal_name,
1276 GVariant *parameters,
1281 if (signal_name == NULL) {
1282 BT_ERR("Wrong Signal");
1287 if (g_strcmp0(signal_name, PROPERTIES_CHANGED) == 0) {
1289 g_variant_get(parameters, "(@a{sv}@as)", &value, NULL);
1291 _bt_hps_gatt_char_property_changed_event(value, object_path);
1293 if (g_strcmp0(interface_name, BT_HPS_PROPERTIES_INTERFACE) == 0) {
1295 g_variant_get(parameters, "(&s@a{sv}@as)", &interface_name, &value, NULL);
1297 _bt_hps_gatt_char_property_changed_event(value, object_path);
1300 //BT_ERR("Wrong Interface %s", interface_name);
1307 void _bt_hps_adapter_event_filter(GDBusConnection *connection,
1308 const gchar *sender_name,
1309 const gchar *object_path,
1310 const gchar *interface_name,
1311 const gchar *signal_name,
1312 GVariant *parameters,
1315 int result = BLUETOOTH_ERROR_NONE;
1318 if (signal_name == NULL) {
1319 BT_ERR("Wrong Signal");
1323 BT_INFO("Interface %s, Signal %s", interface_name, signal_name);
1325 if (g_strcmp0(interface_name, BT_HPS_INTERFACE_NAME) == 0) {
1327 g_variant_get(parameters, "(&s@a{sv}@as)", &interface_name, &value, NULL);
1329 if (strcasecmp(signal_name, BLE_ENABLED) == 0) {
1330 g_variant_get(parameters, "(i)", &result);
1332 if (_bt_hps_prepare_httpproxy() != BLUETOOTH_ERROR_NONE) {
1333 BT_ERR("Fail to prepare HTTP Proxy");
1337 if (_bt_hps_set_advertising_data() != BLUETOOTH_ERROR_NONE) {
1338 BT_ERR("Fail to set advertising data");
1343 BT_ERR("Wrong Signal %s", signal_name);
1350 int _bt_hps_init_event_receiver()
1352 GError *error = NULL;
1357 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
1358 if (error != NULL) {
1359 BT_ERR("ERROR: Can't get on system bus [%s]", error->message);
1360 g_clear_error(&error);
1364 property_sub_id = g_dbus_connection_signal_subscribe(conn,
1365 NULL, BT_HPS_INTERFACE_NAME,
1366 PROPERTIES_CHANGED, BT_HPS_OBJECT_PATH, NULL, 0,
1367 _bt_hps_property_event_filter,
1370 adapter_sub_id = g_dbus_connection_signal_subscribe(conn,
1371 NULL, BT_HPS_INTERFACE_NAME,
1372 BLE_ENABLED, BT_HPS_OBJECT_PATH, NULL, 0,
1373 _bt_hps_adapter_event_filter,
1379 void _bt_hps_deinit_event_receiver(void)
1382 g_dbus_connection_signal_unsubscribe(conn, property_sub_id);
1383 g_dbus_connection_signal_unsubscribe(conn, adapter_sub_id);
1388 int _bt_hps_set_advertising_data(void)
1393 // Temporary UUID is used. SIG have not yet defined the UUID yet
1394 guint8 data[4] = {0x03, 0x02, 0x00, 0x19};
1395 bluetooth_advertising_data_t adv;
1397 BT_DBG("%x %x %x %x", data[0], data[1], data[2], data[3]);
1398 memcpy(adv.data, data, sizeof(data));
1399 ret = bluetooth_set_advertising_data(0, &adv, sizeof(data));
1400 if (ret != BLUETOOTH_ERROR_NONE) {
1401 BT_ERR("Failed to set ADV data %d", ret);
1405 ret = bluetooth_set_advertising(0, TRUE);
1406 if (ret != BLUETOOTH_ERROR_NONE) {
1407 BT_ERR("Failed to set ADV %d", ret);
1414 int _bt_hps_prepare_httpproxy(void)
1416 int ret = BLUETOOTH_ERROR_NONE;
1420 bt_gatt_characteristic_property_t props;
1422 char value[MAX_URI_LENGTH] = { 0 };
1423 struct hps_char_info *char_info = NULL;
1425 char status[3] = { 0 };
1430 ret = bluetooth_gatt_init();
1431 if (ret != BLUETOOTH_ERROR_NONE) {
1432 BT_ERR("Failed to Init GATT %d", ret);
1436 service_uuid = g_strdup(HPS_UUID);
1437 ret = bluetooth_gatt_add_service(service_uuid, &hps_obj_path);
1438 if (ret != BLUETOOTH_ERROR_NONE) {
1439 BT_ERR("Failed to add service %d", ret);
1443 /* Characteristic URI */
1444 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1445 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1446 char_uuid = g_strdup(HTTP_URI_UUID);
1447 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_uri_obj_path);
1448 if (ret != BLUETOOTH_ERROR_NONE) {
1449 BT_ERR("Failed to add new char %d", ret);
1454 ret = bluetooth_gatt_set_characteristic_value(http_uri_obj_path, value, MAX_URI_LENGTH);
1455 if (ret != BLUETOOTH_ERROR_NONE) {
1456 BT_ERR("Failed to add new char %d", ret);
1460 /* Store requets information */
1461 char_info = g_new0(struct hps_char_info, 1);
1462 char_info->char_path = g_strdup(http_uri_obj_path);
1463 _bt_hps_set_char_value(http_uri_obj_path, value, MAX_URI_LENGTH);
1464 hps_char_list = g_slist_append(hps_char_list, char_info);
1467 /* Characteristic HTTP Headers */
1468 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1469 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1470 char_uuid = g_strdup(HTTP_HDR_UUID);
1471 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_hdr_obj_path);
1472 if (ret != BLUETOOTH_ERROR_NONE) {
1473 BT_ERR("Failed to add new char %d", ret);
1477 ret = bluetooth_gatt_set_characteristic_value(http_hdr_obj_path, value, MAX_HEADER_LENGTH);
1478 if (ret != BLUETOOTH_ERROR_NONE) {
1479 BT_ERR("Failed to add new char %d", ret);
1483 /* Store Characterisitc information */
1484 char_info = g_new0(struct hps_char_info, 1);
1485 char_info->char_path = g_strdup(http_hdr_obj_path);
1486 _bt_hps_set_char_value(http_hdr_obj_path, value, MAX_HEADER_LENGTH);
1487 hps_char_list = g_slist_append(hps_char_list, char_info);
1490 /* Characteristic HTTP Entity Body */
1491 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1492 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1493 char_uuid = g_strdup(HTTP_ENTITY_UUID);
1494 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_entity_obj_path);
1495 if (ret != BLUETOOTH_ERROR_NONE) {
1496 BT_ERR("Failed to add new char %d", ret);
1500 ret = bluetooth_gatt_set_characteristic_value(http_entity_obj_path, value, MAX_ENTITY_LENGTH);
1501 if (ret != BLUETOOTH_ERROR_NONE) {
1502 BT_ERR("Failed to add new char %d", ret);
1506 /* Store Characterisitc information */
1507 char_info = g_new0(struct hps_char_info, 1);
1508 char_info->char_path = g_strdup(http_entity_obj_path);
1509 _bt_hps_set_char_value(http_entity_obj_path, value, MAX_ENTITY_LENGTH);
1510 hps_char_list = g_slist_append(hps_char_list, char_info);
1513 /* Characteristic HTTP Control Point */
1514 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1515 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1516 char_uuid = g_strdup(HTTP_CP_UUID);
1517 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_cp_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_cp_obj_path, &cp, 1);
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_cp_obj_path);
1532 _bt_hps_set_char_value(http_cp_obj_path, &cp, 1);
1533 hps_char_list = g_slist_append(hps_char_list, char_info);
1536 /* Characteristic HTTP Status Code */
1537 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1538 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE |
1539 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1540 char_uuid = g_strdup(HTTP_STATUS_UUID);
1541 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_status_obj_path);
1542 if (ret != BLUETOOTH_ERROR_NONE) {
1543 BT_ERR("Failed to add new char %d", ret);
1547 ret = bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
1548 if (ret != BLUETOOTH_ERROR_NONE) {
1549 BT_ERR("Failed to add new char %d", ret);
1553 desc_uuid = g_strdup(HTTP_STATUS_CCC_DESC_UUID);
1554 ret = bluetooth_gatt_add_descriptor(http_status_obj_path, desc_uuid,
1555 (BLUETOOTH_GATT_PERMISSION_READ | BLUETOOTH_GATT_PERMISSION_WRITE),
1556 &http_status_desc_obj_path);
1557 if (ret != BLUETOOTH_ERROR_NONE) {
1558 BT_ERR("Failed to add new char descriptor %d", ret);
1562 /* Store Characterisitc information */
1563 char_info = g_new0(struct hps_char_info, 1);
1564 char_info->char_path = g_strdup(http_status_obj_path);
1565 _bt_hps_set_char_value(http_status_obj_path, status, 3);
1566 hps_char_list = g_slist_append(hps_char_list, char_info);
1569 /* Characteristic HTTPS Security */
1570 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1571 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1572 char_uuid = g_strdup(HTTP_SECURITY_UUID);
1573 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, 0, props, &http_security_obj_path);
1574 if (ret != BLUETOOTH_ERROR_NONE) {
1575 BT_ERR("Failed to add new char %d", ret);
1579 ret = bluetooth_gatt_set_characteristic_value(http_security_obj_path, &cp, 1);
1580 if (ret != BLUETOOTH_ERROR_NONE) {
1581 BT_ERR("Failed to add new char %d", ret);
1585 /* Store Characterisitc information */
1586 char_info = g_new0(struct hps_char_info, 1);
1587 char_info->char_path = g_strdup(http_security_obj_path);
1588 _bt_hps_set_char_value(http_security_obj_path, &cp, 1);
1589 hps_char_list = g_slist_append(hps_char_list, char_info);
1592 ret = bluetooth_gatt_register_service(hps_obj_path);
1593 if (ret != BLUETOOTH_ERROR_NONE) {
1594 BT_ERR("Failed to register service %d", ret);
1598 ret = bluetooth_gatt_register_application();
1599 if (ret != BLUETOOTH_ERROR_NONE) {
1600 BT_ERR("Failed to register application %d", ret);
1608 delete_all_characterisitc();
1609 delete_all_notify_read_status();
1615 static void _bt_hps_sig_handler(int sig)
1621 BT_DBG("caught signal - sigterm\n");
1624 BT_DBG("caught signal - sigint\n");
1627 BT_DBG("caught signal - sigkill\n");
1630 BT_DBG("caught signal %d and ignored\n", sig);
1635 void _bt_hps_exit(void)
1640 if (g_uri != NULL) {
1645 if (g_header != NULL) {
1650 if (g_entity != NULL) {
1655 soup_session_abort(hps_soup_session);
1656 g_assert_cmpint(G_OBJECT(hps_soup_session)->ref_count, ==, 1);
1657 g_object_unref(hps_soup_session);
1660 delete_all_characterisitc();
1663 ret = bluetooth_gatt_deinit();
1664 if (ret != BLUETOOTH_ERROR_NONE)
1665 BT_ERR("Failed to Deinit GATT %d", ret);
1667 ret = bluetooth_unregister_callback();
1668 if (ret != BLUETOOTH_ERROR_NONE)
1669 BT_ERR("Failed to Unregister callback %d", ret);
1671 _bt_hps_deinit_event_receiver();
1673 _bt_hps_unregister_interface();
1675 if (main_loop != NULL)
1676 g_main_loop_quit(main_loop);
1679 void bt_hps_event_callback(int event, bluetooth_event_param_t* param,
1682 BT_DBG("HPS event %d", event);
1686 /* HTTP Proxy Service Main loop */
1689 struct sigaction sa;
1691 BT_ERR("Starting the bt-httpproxy daemon");
1693 /* Values taken from http://www.browserscope.org/ following
1694 * the rule "Do What Every Other Modern Browser Is Doing". They seem
1695 * to significantly improve page loading time compared to soup's
1697 * Change MAX_CONNECTIONS_PER_HOST value 6 -> 12, and maxConnections is changed from 35 to 60.
1698 * Enhanced network loading speed apply tunning value. */
1699 static const int maxConnections = 60;
1700 static const int maxConnectionsPerHost = 12;
1702 memset(&sa, 0, sizeof(sa));
1703 sa.sa_handler = _bt_hps_sig_handler;
1704 sa.sa_flags = SA_SIGINFO;
1705 sigaction(SIGINT, &sa, NULL);
1706 sigaction(SIGTERM, &sa, NULL);
1707 sigaction(SIGKILL, &sa, NULL);
1710 if (bluetooth_register_callback(bt_hps_event_callback, NULL) != BLUETOOTH_ERROR_NONE) {
1711 BT_ERR("bluetooth_register_callback returned failiure");
1716 if (_bt_hps_register_interface() != BLUETOOTH_ERROR_NONE) {
1717 BT_ERR("Fail to register http proxy service");
1721 if (_bt_hps_init_event_receiver() != BLUETOOTH_ERROR_NONE) {
1722 BT_ERR("Fail to init event reciever");
1726 hps_soup_session = soup_session_async_new();
1727 if (hps_soup_session == NULL) {
1728 BT_ERR("Failed to soup_session_async_new");
1731 /* Set Soup Session Fetures */
1732 g_object_set(hps_soup_session,
1733 SOUP_SESSION_MAX_CONNS, maxConnections,
1734 SOUP_SESSION_MAX_CONNS_PER_HOST, maxConnectionsPerHost,
1735 SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER,
1736 SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_SNIFFER,
1737 SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_RESOLVER_DEFAULT,
1738 SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
1741 main_loop = g_main_loop_new(NULL, FALSE);
1743 g_main_loop_run(main_loop);
1745 BT_DBG("g_main_loop_quit called!");
1747 if (main_loop != NULL)
1748 g_main_loop_unref(main_loop);