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>
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);
110 for (i = 0; i < BLUETOOTH_ADDRESS_LENGTH; i++) {
111 addr_hex->addr[i] = (unsigned char)addr[i];
115 static void _bt_hps_send_status_notification(unsigned short http_status,
116 unsigned char data_status,
117 bluetooth_device_address_t *unicast_address)
119 char status[3] = {0x00};
120 int ret = BLUETOOTH_ERROR_NONE;
124 status[0] = http_status & 0xFF;
125 status[1] = (http_status >> 8 )& 0xFF;
126 status[2] = data_status;
127 BT_DBG("Status %d %04x", http_status, http_status);
129 /* Store the status value */
130 _bt_hps_set_char_value(http_status_obj_path, status, 3);
132 /* Send unicast notification */
133 ret = bluetooth_gatt_server_set_notification(http_status_obj_path, unicast_address);
134 if (ret != BLUETOOTH_ERROR_NONE) {
135 BT_ERR("_bt_hps_send_status_notification failed");
138 ret = bluetooth_gatt_update_characteristic(http_status_obj_path, status, 3);
139 if (ret != BLUETOOTH_ERROR_NONE) {
140 BT_ERR("_bt_hps_send_status_notification failed");
146 static void _bt_httpproxy_method(GDBusConnection *connection,
148 const gchar *object_path,
149 const gchar *interface_name,
150 const gchar *method_name,
151 GVariant *parameters,
152 GDBusMethodInvocation *invocation,
157 BT_DBG("Method[%s] Object Path[%s] Interface Name[%s]",
158 method_name, object_path, interface_name);
160 if (g_strcmp0(method_name, "enable") == 0) {
161 g_dbus_method_invocation_return_value(invocation, g_variant_new("(y)", status));
162 } else if (g_strcmp0(method_name, "disable") == 0) {
164 g_dbus_method_invocation_return_value(invocation, g_variant_new("(y)", status));
170 static const GDBusInterfaceVTable hps_method_table = {
171 _bt_httpproxy_method,
176 static void _bt_hps_on_bus_acquired (GDBusConnection *connection, const gchar *name, gpointer user_data)
179 GError *error = NULL;
185 object_id = g_dbus_connection_register_object(connection, BT_HPS_OBJECT_PATH,
186 hps_node_info->interfaces[0],
189 if (object_id == 0) {
190 BT_ERR("Failed to register method table: %s", error->message);
192 g_dbus_node_info_unref(hps_node_info);
198 static void _bt_hps_on_name_acquired (GDBusConnection *connection,
206 static void _bt_hps_on_name_lost (GDBusConnection *connection,
211 g_object_unref(g_conn);
213 g_dbus_node_info_unref(hps_node_info);
214 g_bus_unown_name(g_owner_id);
219 int _bt_hps_register_interface(void)
221 GError *error = NULL;
226 hps_node_info = g_dbus_node_info_new_for_xml (hps_introspection_xml, &error);
227 if (!hps_node_info) {
228 BT_ERR("Failed to install: %s", error->message);
229 return BLUETOOTH_ERROR_INTERNAL;
232 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
234 G_BUS_NAME_OWNER_FLAGS_NONE,
235 _bt_hps_on_bus_acquired, _bt_hps_on_name_acquired, _bt_hps_on_name_lost,
237 g_owner_id = owner_id;
238 BT_DBG("owner_id is [%d]\n", owner_id);
240 return BLUETOOTH_ERROR_NONE;
243 void _bt_hps_unregister_interface(void)
247 g_object_unref(g_conn);
249 g_dbus_node_info_unref(hps_node_info);
250 g_bus_unown_name(g_owner_id);
256 static struct hps_char_info *hps_get_char_value(const char *path)
260 for (tmp = hps_char_list; tmp != NULL; tmp = tmp->next) {
262 struct hps_char_info *char_info = tmp->data;
263 if(!g_strcmp0(char_info->char_path, path))
270 static int char_info_cmp(gconstpointer a1, gconstpointer a2)
272 const struct hps_char_info *attrib1 = a1;
273 const struct hps_char_info *attrib2 = a2;
275 return g_strcmp0(attrib1->char_path, attrib2->char_path);
278 static int notify_info_cmp(gconstpointer a1, gconstpointer a2)
280 const struct hps_notify_read_info *attrib1 = a1;
281 const struct hps_notify_read_info *attrib2 = a2;
283 return g_strcmp0(attrib1->char_path, attrib2->char_path);
286 static void _bt_hps_set_char_value(const char *obj_path, const char* value, int value_length)
292 for (tmp = hps_char_list; tmp != NULL; tmp = tmp->next) {
294 struct hps_char_info *char_info = tmp->data;
295 if(!g_strcmp0(char_info->char_path, obj_path)) {
296 char_info->char_value = g_try_realloc(char_info->char_value, value_length);
297 if (char_info->char_value) {
298 memcpy(char_info->char_value, value, value_length);
299 char_info->value_length = value_length;
300 hps_char_list = g_slist_insert_sorted (hps_char_list,
301 char_info, char_info_cmp);
310 static void _bt_hps_set_notify_read_status(const char *obj_path,
311 guint offset_status, guint read_status, int https_status)
313 struct hps_notify_read_info *notify_read_info = NULL;
316 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
318 notify_read_info = tmp->data;
319 if(!g_strcmp0(notify_read_info->char_path, obj_path)) {
320 notify_read_info->read_status = read_status;
321 notify_read_info->offset_status = offset_status;
322 notify_read_info->https_status = https_status;
323 hps_notify_read_list = g_slist_insert_sorted (hps_notify_read_list,
324 notify_read_info, notify_info_cmp);
330 if (!hps_notify_read_list) {
331 /* Store Notification information */
332 notify_read_info = g_new0(struct hps_notify_read_info, 1);
333 if (notify_read_info) {
334 notify_read_info->char_path = g_strdup(obj_path);
335 notify_read_info->read_status = read_status;
336 notify_read_info->offset_status = offset_status;
337 notify_read_info->https_status = https_status;
338 hps_notify_read_list = g_slist_append(hps_notify_read_list, notify_read_info);
342 /* Store Notification information */
343 notify_read_info = g_new0(struct hps_notify_read_info, 1);
344 if (notify_read_info) {
345 notify_read_info->char_path = g_strdup(obj_path);
346 notify_read_info->read_status = read_status;
347 notify_read_info->offset_status = offset_status;
348 notify_read_info->https_status = https_status;
349 hps_notify_read_list = g_slist_append(hps_notify_read_list, notify_read_info);
355 static struct hps_notify_read_info *_bt_hps_get_notify_read_status(const char *obj_path)
359 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
361 struct hps_notify_read_info *notify_read_info = tmp->data;
362 if(!g_strcmp0(notify_read_info->char_path, obj_path)) {
363 return notify_read_info;
371 static void delete_all_characterisitc(void)
374 for (tmp = hps_char_list; tmp != NULL; tmp = tmp->next) {
376 struct hps_char_info *char_info = tmp->data;
377 if (char_info->char_path)
378 g_free(char_info->char_path);
379 if (char_info->char_value)
380 g_free(char_info->char_value);
381 hps_char_list = g_slist_delete_link(hps_char_list, tmp->data);
384 g_slist_free(hps_char_list);
385 hps_char_list = NULL;
388 static void delete_all_notify_read_status(void)
391 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
393 struct hps_notify_read_info *notify_read_info = tmp->data;
394 if (notify_read_info->char_path)
395 g_free(notify_read_info->char_path);
396 hps_notify_read_list = g_slist_delete_link(hps_notify_read_list, tmp->data);
399 g_slist_free(hps_notify_read_list);
400 hps_notify_read_list = NULL;
403 static void delete_notify_read_status(const char *obj_path)
406 for (tmp = hps_notify_read_list; tmp != NULL; tmp = tmp->next) {
408 struct hps_notify_read_info *notify_read_info = tmp->data;
409 if(!g_strcmp0(notify_read_info->char_path, obj_path)) {
410 if (notify_read_info->char_path)
411 g_free(notify_read_info->char_path);
412 hps_notify_read_list = g_slist_delete_link(hps_notify_read_list, tmp->data);
420 int _bt_hps_uri_write_cb(char *uri, int len)
422 if((len < 1) || (len > MAX_URI_LENGTH)) {
423 BT_ERR("Wrong URI length %d", len);
424 return BLUETOOTH_ERROR_INTERNAL;
427 /* g_uri will be used commonly for all HTTP methods whereever applicable */
430 g_uri = g_strndup(uri, len);
432 _bt_hps_set_char_value(http_uri_obj_path, g_uri, len);
434 return BLUETOOTH_ERROR_NONE;
437 int _bt_hps_http_header_write_cb(char *header, int len)
439 if((len < 1) || (len > MAX_HEADER_LENGTH)) {
440 BT_ERR("Wrong Header length %d", len);
441 return BLUETOOTH_ERROR_INTERNAL;
444 /* g_header will be used commonly for all HTTP methods where ever applicable
445 general-header, request-header, entity-header
449 g_header = g_strndup(header, len);
451 _bt_hps_set_char_value(http_hdr_obj_path, g_header, len);
454 return BLUETOOTH_ERROR_NONE;
457 int _bt_hps_entity_body_write_cb(char *entity, int len)
459 if((len < 1) || (len > MAX_ENTITY_LENGTH)) {
460 BT_ERR("Wrong Entity length %d", len);
461 return BLUETOOTH_ERROR_INTERNAL;
464 /* g_entity will be used commonly for all HTTP methods whereever applicable */
467 g_entity = g_strndup(entity, len);
469 _bt_hps_set_char_value(http_entity_obj_path, g_entity, len);
472 return BLUETOOTH_ERROR_NONE;
476 int _bt_hps_read_cb(const char *obj_path, char **value, int *len)
478 struct hps_char_info *info = NULL;
479 struct hps_notify_read_info *notify_read_info = NULL;
480 guint data_status = -1;
482 gboolean is_header = FALSE;
485 BT_ERR("Wrong Obj path");
489 if (!g_strcmp0(http_hdr_obj_path, obj_path))
492 info = hps_get_char_value(obj_path);
495 if (info->char_value == NULL || info->value_length == 0)
498 notify_read_info = _bt_hps_get_notify_read_status(obj_path);
499 if (notify_read_info && notify_read_info->read_status != DS_BODY_RECEIVED &&
500 notify_read_info->read_status != DS_HEADER_RECEIVED) {
501 offset = notify_read_info->offset_status;
502 if ((info->value_length - offset) > 0 &&
503 (info->value_length - offset) > MAX_ENTITY_LENGTH) {
505 data_status = DS_HEADER_TRUNCATED;
507 data_status = DS_BODY_TRUNCATED;
508 _bt_hps_set_notify_read_status(obj_path, offset + MAX_ENTITY_LENGTH,
509 data_status, notify_read_info->https_status);
510 *value = g_strdup(&info->char_value[offset]);
511 *len = info->value_length;
512 } else if ((info->value_length - offset) > 0 &&
513 (info->value_length - offset) <= MAX_ENTITY_LENGTH) {
515 data_status = DS_HEADER_RECEIVED;
517 data_status = DS_BODY_RECEIVED;
518 _bt_hps_set_notify_read_status(obj_path, offset, data_status, notify_read_info->https_status);
519 *value = g_strdup(&info->char_value[offset]);
520 *len = info->value_length;
522 } else if (notify_read_info && (notify_read_info->read_status == DS_BODY_RECEIVED ||
523 notify_read_info->read_status == DS_HEADER_RECEIVED)) {
525 data_status = DS_HEADER_RECEIVED;
527 data_status = DS_BODY_RECEIVED;
528 delete_notify_read_status(obj_path);
529 *value = g_strdup(&info->char_value[offset]);
530 *len = info->value_length;
538 void _bt_hps_head_response_cb(SoupSession *session,
539 SoupMessage *msg, gpointer user_data)
541 unsigned short http_status = 0x00;
543 unsigned char status[3] = {0x00};
545 const char *device_address = user_data;
546 bluetooth_device_address_t addr_hex = { {0,} };
547 unsigned char data_status = DS_NONE;
548 _hps_convert_address_to_hex(&addr_hex, device_address);
551 if(hps_soup_session != session) {
552 BT_ERR("Wrong Session");
557 BT_ERR("Wrong Message");
562 req_state = HTTP_REQ_STATE_EXECUTED;
564 http_status = msg->status_code;
566 // Process Header in Response Body
567 if(msg->response_headers) {
569 const char *content = NULL;
570 const char *length = NULL;
573 length = soup_message_headers_get_one (msg->request_headers,
575 // Check "Content-MD5" is the right name to get header content
576 content = soup_message_headers_get_one (msg->response_headers,
578 if (content == NULL || length == NULL) {
579 BT_ERR("Wrong Response Header");
580 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
584 hdr_len = soup_message_headers_get_content_length(msg->response_headers);
586 // Write Data to Header Characteristic
588 _bt_hps_set_char_value(http_hdr_obj_path, content, hdr_len);
590 bluetooth_gatt_set_characteristic_value(http_hdr_obj_path, content, hdr_len);
592 // TODO : Handle Truncated Header
594 // Write Data to Status Code Characteristic
596 data_status = (hdr_len > MAX_ENTITY_LENGTH ) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
597 if (data_status == DS_BODY_TRUNCATED && SOUP_STATUS_IS_SUCCESSFUL(http_status)) {
598 _bt_hps_set_notify_read_status(http_hdr_obj_path, data_status, 0, http_status);
600 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
602 status[0] = http_status & 0x0F;
603 status[1] = (http_status >> 8 )& 0x0F;
604 status[2] = (hdr_len > MAX_HEADER_LENGTH ) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
606 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
609 BT_ERR("HEAD Response is NULL");
610 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
616 void _bt_hps_http_response_cb(SoupSession *session,
617 SoupMessage *msg, gpointer user_data)
619 unsigned short http_status = 0x00;
621 unsigned char status[3] = {0x00};
623 const char *device_address = user_data;
624 bluetooth_device_address_t addr_hex = { {0,} };
625 unsigned char data_status = DS_NONE;
626 _hps_convert_address_to_hex(&addr_hex, device_address);
629 if(hps_soup_session != session) {
630 BT_ERR("Wrong Session");
635 BT_ERR("Wrong Message");
641 req_state = HTTP_REQ_STATE_EXECUTED;
643 http_status = msg->status_code;
645 // Write Data to Status Code Characteristic
647 status[0] = http_status & 0x0F;
648 status[1] = (http_status >> 8 )& 0x0F;
649 status[2] = DS_HEADER_RECEIVED;
650 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
652 data_status = DS_HEADER_RECEIVED;
653 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
659 void _bt_hps_get_response_cb(SoupSession *session,
660 SoupMessage *msg, gpointer user_data)
662 SoupBuffer *body = NULL;
663 unsigned short http_status = 0x00;
665 unsigned char status[3] = {0x00};
667 const char *device_address = user_data;
668 bluetooth_device_address_t addr_hex = { {0,} };
669 unsigned char data_status = DS_NONE;
670 _hps_convert_address_to_hex(&addr_hex, device_address);
673 if(hps_soup_session != session) {
674 BT_ERR("Wrong Session");
679 BT_ERR("Wrong Message");
685 req_state = HTTP_REQ_STATE_EXECUTED;
687 http_status = msg->status_code;
689 // Process Entity Body in Response Message
690 if(msg->response_body) {
692 body = soup_message_body_flatten (msg->response_body);
694 BT_ERR("Wrong Response Body");
696 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
700 if (body->data == NULL || body->length <= 0) {
701 BT_ERR("Wrong Response");
702 soup_buffer_free(body);
704 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
708 // Write Data to Entity Body Characteristic
710 _bt_hps_set_char_value(http_entity_obj_path, body->data, body->length);
712 bluetooth_gatt_set_characteristic_value(http_entity_obj_path, body->data, body->length);
714 // TODO : Handle Truncated Entiry Body
716 // Write Data to Status Code Characteristic
718 data_status = (body->length > MAX_ENTITY_LENGTH ) ? DS_BODY_TRUNCATED : DS_BODY_RECEIVED;
719 if (data_status == DS_BODY_TRUNCATED && SOUP_STATUS_IS_SUCCESSFUL(http_status)) {
720 _bt_hps_set_notify_read_status(http_entity_obj_path, data_status, 0, http_status);
722 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
725 status[0] = http_status & 0x0F;
726 status[1] = (http_status >> 8 )& 0x0F;
727 status[2] = (body->length > MAX_HEADER_LENGTH ) ? DS_BODY_TRUNCATED : DS_BODY_TRUNCATED;
729 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
731 soup_buffer_free(body);
733 BT_ERR("GET Response Body is NULL");
735 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
739 // Process Header in Response Body
740 if(msg->response_headers) {
742 const char *content = NULL;
743 const char *length = NULL;
746 length = soup_message_headers_get_one (msg->request_headers,
748 // Check "Content-MD5" is the right name to get header content
749 content = soup_message_headers_get_one (msg->response_headers,
751 if (content == NULL || length == NULL) {
752 BT_ERR("Wrong Response Header");
753 data_status = DS_NONE;
754 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
758 hdr_len = soup_message_headers_get_content_length(msg->response_headers);
759 // Write Data to Header Characteristic
761 _bt_hps_set_char_value(http_hdr_obj_path, content, hdr_len);
763 bluetooth_gatt_set_characteristic_value(http_hdr_obj_path, content, hdr_len);
765 // TODO : Handle Truncated Header
767 // Write Data to Status Code Characteristic
769 data_status = (hdr_len > MAX_HEADER_LENGTH ) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
770 if (data_status == DS_HEADER_TRUNCATED && SOUP_STATUS_IS_SUCCESSFUL(http_status)) {
771 _bt_hps_set_notify_read_status(http_hdr_obj_path, data_status, 0, http_status);
773 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
775 status[0] = http_status & 0x0F;
776 status[1] = (http_status >> 8 )& 0x0F;
777 status[2] = (hdr_len > MAX_HEADER_LENGTH ) ? DS_HEADER_TRUNCATED : DS_HEADER_RECEIVED;
779 bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
782 BT_ERR("GET Response Header is NULL");
784 _bt_hps_send_status_notification(http_status, data_status, &addr_hex);
792 int _bt_hps_control_point_write_cb(const char *value, int len, char *addr)
794 int _bt_hps_control_point_write_cb(char *value, int len)
798 GTlsCertificate *cert = NULL;
799 GTlsCertificateFlags flags;
800 gboolean https_status = FALSE;
801 int result = BLUETOOTH_ERROR_NONE;
802 BT_INFO("Opcode %0x", opcode);
805 _bt_hps_set_char_value(http_cp_obj_path, value, len);
809 case HTTP_GET_REQUEST:
810 if(req_state == HTTP_REQ_STATE_EXECUTED) {
811 req_state = HTTP_REQ_STATE_INPROGRESS;
812 hps_soup_msg = soup_message_new("GET", g_uri);
814 g_object_ref (hps_soup_msg);
815 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, addr);
817 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, NULL);
820 BT_ERR("HTTP GET request in progress, message dropped");
821 result = BLUETOOTH_ERROR_INTERNAL;
825 case HTTP_POST_REQUEST:
826 if(req_state == HTTP_REQ_STATE_EXECUTED) {
827 req_state = HTTP_REQ_STATE_INPROGRESS;
828 hps_soup_msg = soup_message_new("POST", g_uri);
829 if(hps_soup_msg == NULL || g_entity == NULL) {
830 BT_ERR("Soup Message NULL");
831 result = BLUETOOTH_ERROR_INTERNAL;
832 req_state = HTTP_REQ_STATE_EXECUTED;
835 soup_message_set_request (hps_soup_msg, "text/xml", SOUP_MEMORY_COPY,
836 g_entity, strlen (g_entity));
838 g_object_ref (hps_soup_msg);
839 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
841 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
844 BT_ERR("HTTP POST request in progress, message dropped");
845 result = BLUETOOTH_ERROR_INTERNAL;
849 case HTTP_HEAD_REQUEST:
850 if(req_state == HTTP_REQ_STATE_EXECUTED) {
851 req_state = HTTP_REQ_STATE_INPROGRESS;
852 hps_soup_msg = soup_message_new("HEAD", g_uri);
853 if(hps_soup_msg == NULL) {
854 BT_ERR("Soup Message NULL");
855 result = BLUETOOTH_ERROR_INTERNAL;
856 req_state = HTTP_REQ_STATE_EXECUTED;
860 g_object_ref (hps_soup_msg);
861 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, addr);
863 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, NULL);
866 BT_ERR("HTTP HEAD request in progress, message dropped");
867 result = BLUETOOTH_ERROR_INTERNAL;
871 case HTTP_PUT_REQUEST:
872 if(req_state == HTTP_REQ_STATE_EXECUTED) {
874 req_state = HTTP_REQ_STATE_INPROGRESS;
875 hps_soup_msg = soup_message_new("PUT", g_uri);
876 if(hps_soup_msg == NULL || g_entity == NULL) {
877 BT_ERR("Soup Message NULL");
878 result = BLUETOOTH_ERROR_INTERNAL;
879 req_state = HTTP_REQ_STATE_EXECUTED;
882 buf = soup_buffer_new (SOUP_MEMORY_TAKE, g_entity, strlen (g_entity));
883 soup_message_body_append_buffer (hps_soup_msg->request_body, buf);
884 soup_message_body_set_accumulate (hps_soup_msg->request_body, FALSE);
886 g_object_ref (hps_soup_msg);
887 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
889 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
893 BT_ERR("HTTP PUT request in progress, message dropped");
894 result = BLUETOOTH_ERROR_INTERNAL;
898 case HTTP_DELETE_REQUEST:
899 if(req_state == HTTP_REQ_STATE_EXECUTED) {
900 req_state = HTTP_REQ_STATE_INPROGRESS;
901 hps_soup_msg = soup_message_new("DELETE", g_uri);
902 if(hps_soup_msg == NULL) {
903 BT_ERR("Soup Message NULL");
904 result = BLUETOOTH_ERROR_INTERNAL;
905 req_state = HTTP_REQ_STATE_EXECUTED;
909 g_object_ref (hps_soup_msg);
910 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
912 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
915 BT_ERR("HTTP DELETE request in progress, message dropped");
916 result = BLUETOOTH_ERROR_INTERNAL;
920 case HTTPS_GET_REQUEST:
921 if(req_state == HTTP_REQ_STATE_EXECUTED) {
922 req_state = HTTP_REQ_STATE_INPROGRESS;
923 hps_soup_msg = soup_message_new("GET", g_uri);
924 if(hps_soup_msg == NULL) {
925 BT_ERR("Soup Message NULL");
926 result = BLUETOOTH_ERROR_INTERNAL;
927 req_state = HTTP_REQ_STATE_EXECUTED;
931 g_object_ref (hps_soup_msg);
932 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, addr);
934 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_get_response_cb, NULL);
936 https_status = soup_message_get_https_status (hps_soup_msg, &cert, &flags);
938 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1);
940 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
943 BT_ERR("HTTPS GET request in progress, message dropped");
944 result = BLUETOOTH_ERROR_INTERNAL;
948 case HTTPS_HEAD_REQUEST:
949 if(req_state == HTTP_REQ_STATE_EXECUTED) {
950 req_state = HTTP_REQ_STATE_INPROGRESS;
951 hps_soup_msg = soup_message_new("HEAD", g_uri);
952 if(hps_soup_msg == NULL) {
953 BT_ERR("Soup Message NULL");
954 result = BLUETOOTH_ERROR_INTERNAL;
955 req_state = HTTP_REQ_STATE_EXECUTED;
959 g_object_ref (hps_soup_msg);
960 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, addr);
962 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_head_response_cb, NULL);
964 https_status = soup_message_get_https_status (hps_soup_msg, &cert, &flags);
966 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1);
968 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
971 BT_ERR("HTTPS HEAD request in progress, message dropped");
972 result = BLUETOOTH_ERROR_INTERNAL;
976 case HTTPS_POST_REQUEST:
977 if(req_state == HTTP_REQ_STATE_EXECUTED) {
978 req_state = HTTP_REQ_STATE_INPROGRESS;
979 hps_soup_msg = soup_message_new("POST", g_uri);
980 if(hps_soup_msg == NULL) {
981 BT_ERR("Soup Message NULL");
982 result = BLUETOOTH_ERROR_INTERNAL;
983 req_state = HTTP_REQ_STATE_EXECUTED;
986 soup_message_set_request (hps_soup_msg, "text/xml", SOUP_MEMORY_STATIC,
987 g_entity, strlen (g_entity));
989 g_object_ref (hps_soup_msg);
990 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
992 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
995 https_status = soup_message_get_https_status (hps_soup_msg, &cert, &flags);
997 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1);
999 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
1002 BT_ERR("HTTPS POST request in progress, message dropped");
1003 result = BLUETOOTH_ERROR_INTERNAL;
1007 case HTTPS_PUT_REQUEST:
1008 if(req_state == HTTP_REQ_STATE_EXECUTED) {
1010 req_state = HTTP_REQ_STATE_INPROGRESS;
1011 hps_soup_msg = soup_message_new("PUT", g_uri);
1012 if(hps_soup_msg == NULL) {
1013 BT_ERR("Soup Message NULL");
1014 result = BLUETOOTH_ERROR_INTERNAL;
1015 req_state = HTTP_REQ_STATE_EXECUTED;
1018 buf = soup_buffer_new (SOUP_MEMORY_TAKE, g_entity, strlen (g_entity));
1019 soup_message_body_append_buffer (hps_soup_msg->request_body, buf);
1020 soup_message_body_set_accumulate (hps_soup_msg->request_body, FALSE);
1022 g_object_ref (hps_soup_msg);
1023 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
1025 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
1027 https_status = soup_message_get_https_status (hps_soup_msg, &cert, &flags);
1029 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1);
1031 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
1034 BT_ERR("HTTPS PUT request in progress, message dropped");
1035 result = BLUETOOTH_ERROR_INTERNAL;
1039 case HTTPS_DELETE_REQUEST:
1040 if(req_state == HTTP_REQ_STATE_EXECUTED) {
1041 req_state = HTTP_REQ_STATE_INPROGRESS;
1042 hps_soup_msg = soup_message_new("DELETE", g_uri);
1043 if(hps_soup_msg == NULL) {
1044 BT_ERR("Soup Message NULL");
1045 result = BLUETOOTH_ERROR_INTERNAL;
1046 req_state = HTTP_REQ_STATE_EXECUTED;
1050 g_object_ref (hps_soup_msg);
1051 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, addr);
1053 soup_session_queue_message(hps_soup_session, hps_soup_msg, _bt_hps_http_response_cb, NULL);
1056 https_status = soup_message_get_https_status (hps_soup_msg, &cert, &flags);
1058 _bt_hps_set_char_value(http_security_obj_path, (const char *)&https_status, 1);
1060 bluetooth_gatt_set_characteristic_value(http_security_obj_path, (char *)&https_status, 1);
1063 BT_ERR("HTTPS DELETE request in progress, message dropped");
1064 result = BLUETOOTH_ERROR_INTERNAL;
1068 case HTTP_REQUEST_CANCEL:
1069 /* Cancel the outstanding request */
1070 if(req_state == HTTP_REQ_STATE_INPROGRESS) {
1071 req_state = HTTP_REQ_STATE_IDLE;
1072 if(hps_soup_msg == NULL) {
1073 BT_ERR("Soup Message NULL");
1074 result = BLUETOOTH_ERROR_INTERNAL;
1075 req_state = HTTP_REQ_STATE_EXECUTED;
1078 soup_session_cancel_message (hps_soup_session, hps_soup_msg, SOUP_STATUS_CANCELLED);
1079 hps_soup_msg = NULL;
1084 BT_ERR("Unknown opcode %0x", opcode);
1085 result = BLUETOOTH_ERROR_INTERNAL;
1092 void _bt_hps_security_read_cb (char *value, int len)
1094 BT_INFO("HPS Client Read the value");
1099 void _bt_hps_gatt_char_property_changed_event(GVariant *msg,
1102 int result = BLUETOOTH_ERROR_NONE;
1103 GVariantIter value_iter;
1104 const char *property = NULL;
1105 const char * char_path = NULL;
1106 const char * svc_handle = NULL;
1107 GVariant *var = NULL;
1108 GVariant *val = NULL;
1109 g_variant_iter_init (&value_iter, msg);
1111 while ((g_variant_iter_loop(&value_iter, "{sv}", &property, &var))) {
1113 if(property == NULL) {
1114 BT_ERR("Property NULL");
1118 if (!g_strcmp0(property, "WriteValue")) {
1120 BT_INFO("WriteValue");
1121 BT_INFO("Type '%s'\n", g_variant_get_type_string (var));
1128 g_variant_get(var, "(&s&s&syq@ay)", &char_path,
1129 &svc_handle, &addr, &req_id, &offset, &val);
1131 len = g_variant_get_size(val);
1133 BT_DBG("Len = %d", len);
1135 value = (char *) g_variant_get_data(val);
1138 if(!g_strcmp0(char_path, http_uri_obj_path)) {
1140 result = _bt_hps_uri_write_cb(value, len);
1141 } else if(!g_strcmp0(char_path, http_hdr_obj_path)) {
1142 /* Retrive HEADER */
1143 result = _bt_hps_http_header_write_cb(value, len);
1144 } else if(!g_strcmp0(char_path, http_entity_obj_path)) {
1145 /* Retrive ENTITY BODY */
1146 result = _bt_hps_entity_body_write_cb(value, len);
1147 } else if(!g_strcmp0(char_path, http_cp_obj_path)) {
1148 result = _bt_hps_control_point_write_cb(value, len, addr);
1150 BT_ERR("Wrong Object Path %s", char_path);
1151 result = BLUETOOTH_ERROR_INTERNAL;
1153 bluetooth_gatt_send_response(req_id, BLUETOOTH_GATT_ATT_REQUEST_TYPE_WRITE, result, 0, NULL, 0);
1155 BT_ERR("Array Len 0");
1158 BT_ERR("var==NULL");
1160 } else if (!g_strcmp0(property, "ReadValue")) {
1166 int data_status = -1;
1167 BT_INFO("ReadValue");
1168 BT_INFO("Type '%s'\n", g_variant_get_type_string (var));
1170 g_variant_get(var, "(&s&s&syq)", &char_path, &svc_handle,
1171 &addr, &req_id, &offset);
1173 data_status = _bt_hps_read_cb(char_path, &value, &len);
1174 if (data_status >= DS_NONE) {
1175 struct hps_notify_read_info *notify_read_info = NULL;
1176 bluetooth_device_address_t addr_hex = { {0,} };
1177 _hps_convert_address_to_hex(&addr_hex, addr);
1178 bluetooth_gatt_send_response(req_id, BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ,
1179 BLUETOOTH_ERROR_NONE, offset, value, len);
1180 notify_read_info = _bt_hps_get_notify_read_status(char_path);
1181 if (notify_read_info) {
1182 _bt_hps_send_status_notification(notify_read_info->https_status,
1183 data_status, &addr_hex);
1185 if (data_status == DS_BODY_RECEIVED ||
1186 data_status == DS_HEADER_RECEIVED) {
1187 _bt_hps_set_char_value(char_path, NULL, 0);
1193 BT_ERR("ReadValue failed %s", char_path);
1194 bluetooth_gatt_send_response(req_id, BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ,
1195 BLUETOOTH_ERROR_INTERNAL, offset, NULL, 0);
1202 void _bt_hps_gatt_char_property_changed_event(GVariant *msg,
1205 GVariantIter value_iter;
1206 char *property = NULL;
1207 char * char_handle = NULL;
1208 GVariant *val = NULL;
1209 int result = BLUETOOTH_ERROR_NONE;
1210 GVariant *param = NULL;
1211 g_variant_iter_init (&value_iter, msg);
1212 char_handle = g_strdup(path);
1214 while ((g_variant_iter_loop(&value_iter, "{sv}", &property, &val))) {
1216 if(property == NULL) {
1217 BT_ERR("Property NULL");
1221 if (strcasecmp(property, "ChangedValue") == 0) {
1224 GByteArray *gp_byte_array = NULL;
1225 BT_INFO("Type '%s'\n", g_variant_get_type_string (val));
1228 gp_byte_array = g_byte_array_new();
1229 len = g_variant_get_size(val);
1230 BT_DBG("Len = %d", len);
1231 g_byte_array_append (gp_byte_array,
1232 (const guint8 *) g_variant_get_data(val), len);
1233 if (gp_byte_array->len != 0) {
1234 GVariant *byte_array = NULL;
1235 byte_array = g_variant_new_from_data(
1236 G_VARIANT_TYPE_BYTESTRING,
1237 gp_byte_array->data,
1240 param = g_variant_new("(is@ay)", result, char_handle,
1243 if(strcmp(path, http_uri_obj_path)) {
1245 _bt_hps_uri_write_cb(NULL, len);
1246 } else if(strcmp(path, http_hdr_obj_path)) {
1248 _bt_hps_http_header_write_cb(NULL, len);
1249 } else if(strcmp(path, http_entity_obj_path)) {
1250 //Retrive ENTITY BODY
1251 _bt_hps_entity_body_write_cb(NULL, len);
1252 } else if(strcmp(path, http_cp_obj_path)) {
1253 _bt_hps_control_point_write_cb(NULL, len);
1254 } else if(strcmp(path, http_security_obj_path)) {
1255 _bt_hps_security_read_cb(NULL, len);
1257 BT_ERR("Wrong Object Path %s", path);
1260 BT_ERR("Array Len 0");
1262 g_byte_array_free(gp_byte_array, TRUE);
1264 BT_ERR("val==NULL");
1268 g_free(char_handle);
1274 void _bt_hps_property_event_filter(GDBusConnection *connection,
1275 const gchar *sender_name,
1276 const gchar *object_path,
1277 const gchar *interface_name,
1278 const gchar *signal_name,
1279 GVariant *parameters,
1284 if (signal_name == NULL) {
1285 BT_ERR("Wrong Signal");
1290 if (g_strcmp0(signal_name, PROPERTIES_CHANGED) == 0) {
1292 g_variant_get(parameters, "(@a{sv}@as)", &value, NULL);
1294 _bt_hps_gatt_char_property_changed_event(value, object_path);
1296 if (g_strcmp0(interface_name, BT_HPS_PROPERTIES_INTERFACE) == 0) {
1298 g_variant_get(parameters, "(&s@a{sv}@as)", &interface_name, &value, NULL);
1300 _bt_hps_gatt_char_property_changed_event(value, object_path);
1303 //BT_ERR("Wrong Interface %s", interface_name);
1310 void _bt_hps_adapter_event_filter(GDBusConnection *connection,
1311 const gchar *sender_name,
1312 const gchar *object_path,
1313 const gchar *interface_name,
1314 const gchar *signal_name,
1315 GVariant *parameters,
1318 int result = BLUETOOTH_ERROR_NONE;
1321 if (signal_name == NULL) {
1322 BT_ERR("Wrong Signal");
1326 BT_INFO("Interface %s, Signal %s", interface_name, signal_name);
1328 if (g_strcmp0(interface_name, BT_HPS_INTERFACE_NAME) == 0) {
1330 g_variant_get(parameters, "(&s@a{sv}@as)", &interface_name, &value, NULL);
1332 if (strcasecmp(signal_name, BLE_ENABLED) == 0) {
1333 g_variant_get(parameters, "(i)", &result);
1335 if (_bt_hps_prepare_httpproxy() != BLUETOOTH_ERROR_NONE) {
1336 BT_ERR("Fail to prepare HTTP Proxy");
1340 if (_bt_hps_set_advertising_data() != BLUETOOTH_ERROR_NONE) {
1341 BT_ERR("Fail to set advertising data");
1346 BT_ERR("Wrong Signal %s", signal_name);
1353 int _bt_hps_init_event_receiver()
1355 GError *error = NULL;
1360 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
1361 if (error != NULL) {
1362 BT_ERR("ERROR: Can't get on system bus [%s]", error->message);
1363 g_clear_error(&error);
1367 property_sub_id = g_dbus_connection_signal_subscribe(conn,
1368 NULL, BT_HPS_INTERFACE_NAME,
1369 PROPERTIES_CHANGED, BT_HPS_OBJECT_PATH, NULL, 0,
1370 _bt_hps_property_event_filter,
1373 adapter_sub_id = g_dbus_connection_signal_subscribe(conn,
1374 NULL, BT_HPS_INTERFACE_NAME,
1375 BLE_ENABLED, BT_HPS_OBJECT_PATH, NULL, 0,
1376 _bt_hps_adapter_event_filter,
1382 void _bt_hps_deinit_event_receiver(void)
1385 g_dbus_connection_signal_unsubscribe(conn, property_sub_id);
1386 g_dbus_connection_signal_unsubscribe(conn, adapter_sub_id);
1391 int _bt_hps_set_advertising_data(void)
1396 // Temporary UUID is used. SIG have not yet defined the UUID yet
1397 guint8 data[4] = {0x03, 0x02, 0x00, 0x19};
1398 bluetooth_advertising_data_t adv;
1400 BT_DBG("%x %x %x %x", data[0], data[1], data[2], data[3]);
1401 memcpy(adv.data, data, sizeof(data));
1402 ret = bluetooth_set_advertising_data(0, &adv, sizeof(data));
1403 if(ret != BLUETOOTH_ERROR_NONE) {
1404 BT_ERR("Failed to set ADV data %d", ret);
1408 ret = bluetooth_set_advertising(0, TRUE);
1409 if(ret != BLUETOOTH_ERROR_NONE) {
1410 BT_ERR("Failed to set ADV %d", ret);
1417 int _bt_hps_prepare_httpproxy(void)
1419 int ret = BLUETOOTH_ERROR_NONE;
1423 bt_gatt_characteristic_property_t props;
1425 char value[MAX_URI_LENGTH] = { 0 };
1426 struct hps_char_info *char_info = NULL;
1428 char status[3] = { 0 };
1433 ret = bluetooth_gatt_init();
1434 if(ret != BLUETOOTH_ERROR_NONE) {
1435 BT_ERR("Failed to Init GATT %d", ret);
1439 service_uuid = g_strdup(HPS_UUID);
1440 ret = bluetooth_gatt_add_service(service_uuid, &hps_obj_path);
1441 if(ret != BLUETOOTH_ERROR_NONE) {
1442 BT_ERR("Failed to add service %d", ret);
1446 /* Characteristic URI */
1447 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1448 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1449 char_uuid = g_strdup(HTTP_URI_UUID);
1450 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, props, &http_uri_obj_path);
1451 if(ret != BLUETOOTH_ERROR_NONE) {
1452 BT_ERR("Failed to add new char %d", ret);
1457 ret = bluetooth_gatt_set_characteristic_value(http_uri_obj_path, value, MAX_URI_LENGTH);
1458 if(ret != BLUETOOTH_ERROR_NONE) {
1459 BT_ERR("Failed to add new char %d", ret);
1463 /* Store requets information */
1464 char_info = g_new0(struct hps_char_info, 1);
1465 char_info->char_path = g_strdup(http_uri_obj_path);
1466 _bt_hps_set_char_value(http_uri_obj_path, value, MAX_URI_LENGTH);
1467 hps_char_list = g_slist_append(hps_char_list, char_info);
1470 /* Characteristic HTTP Headers */
1471 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1472 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1473 char_uuid = g_strdup(HTTP_HDR_UUID);
1474 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, props, &http_hdr_obj_path);
1475 if(ret != BLUETOOTH_ERROR_NONE) {
1476 BT_ERR("Failed to add new char %d", ret);
1480 ret = bluetooth_gatt_set_characteristic_value(http_hdr_obj_path, value, MAX_HEADER_LENGTH);
1481 if(ret != BLUETOOTH_ERROR_NONE) {
1482 BT_ERR("Failed to add new char %d", ret);
1486 /* Store Characterisitc information */
1487 char_info = g_new0(struct hps_char_info, 1);
1488 char_info->char_path = g_strdup(http_hdr_obj_path);
1489 _bt_hps_set_char_value(http_hdr_obj_path, value, MAX_HEADER_LENGTH);
1490 hps_char_list = g_slist_append(hps_char_list, char_info);
1493 /* Characteristic HTTP Entity Body */
1494 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1495 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1496 char_uuid = g_strdup(HTTP_ENTITY_UUID);
1497 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, props, &http_entity_obj_path);
1498 if(ret != BLUETOOTH_ERROR_NONE) {
1499 BT_ERR("Failed to add new char %d", ret);
1503 ret = bluetooth_gatt_set_characteristic_value(http_entity_obj_path, value, MAX_ENTITY_LENGTH);
1504 if(ret != BLUETOOTH_ERROR_NONE) {
1505 BT_ERR("Failed to add new char %d", ret);
1509 /* Store Characterisitc information */
1510 char_info = g_new0(struct hps_char_info, 1);
1511 char_info->char_path = g_strdup(http_entity_obj_path);
1512 _bt_hps_set_char_value(http_entity_obj_path, value, MAX_ENTITY_LENGTH);
1513 hps_char_list = g_slist_append(hps_char_list, char_info);
1516 /* Characteristic HTTP Control Point */
1517 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1518 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1519 char_uuid = g_strdup(HTTP_CP_UUID);
1520 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, props, &http_cp_obj_path);
1521 if(ret != BLUETOOTH_ERROR_NONE) {
1522 BT_ERR("Failed to add new char %d", ret);
1526 ret = bluetooth_gatt_set_characteristic_value(http_cp_obj_path, &cp, 1);
1527 if(ret != BLUETOOTH_ERROR_NONE) {
1528 BT_ERR("Failed to add new char %d", ret);
1532 /* Store Characterisitc information */
1533 char_info = g_new0(struct hps_char_info, 1);
1534 char_info->char_path = g_strdup(http_cp_obj_path);
1535 _bt_hps_set_char_value(http_cp_obj_path, &cp, 1);
1536 hps_char_list = g_slist_append(hps_char_list, char_info);
1539 /* Characteristic HTTP Status Code */
1540 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1541 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE |
1542 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1543 char_uuid = g_strdup(HTTP_STATUS_UUID);
1544 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, props, &http_status_obj_path);
1545 if(ret != BLUETOOTH_ERROR_NONE) {
1546 BT_ERR("Failed to add new char %d", ret);
1550 ret = bluetooth_gatt_set_characteristic_value(http_status_obj_path, status, 3);
1551 if(ret != BLUETOOTH_ERROR_NONE) {
1552 BT_ERR("Failed to add new char %d", ret);
1556 desc_uuid = g_strdup(HTTP_STATUS_CCC_DESC_UUID);
1557 ret = bluetooth_gatt_add_descriptor(http_status_obj_path, desc_uuid, &http_status_desc_obj_path);
1558 if(ret != BLUETOOTH_ERROR_NONE) {
1559 BT_ERR("Failed to add new char descriptor %d", ret);
1563 /* Store Characterisitc information */
1564 char_info = g_new0(struct hps_char_info, 1);
1565 char_info->char_path = g_strdup(http_status_obj_path);
1566 _bt_hps_set_char_value(http_status_obj_path, status, 3);
1567 hps_char_list = g_slist_append(hps_char_list, char_info);
1570 /* Characteristic HTTPS Security */
1571 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
1572 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1573 char_uuid = g_strdup(HTTP_SECURITY_UUID);
1574 ret = bluetooth_gatt_add_new_characteristic(hps_obj_path, char_uuid, props, &http_security_obj_path);
1575 if(ret != BLUETOOTH_ERROR_NONE) {
1576 BT_ERR("Failed to add new char %d", ret);
1580 ret = bluetooth_gatt_set_characteristic_value(http_security_obj_path, &cp, 1);
1581 if(ret != BLUETOOTH_ERROR_NONE) {
1582 BT_ERR("Failed to add new char %d", ret);
1586 /* Store Characterisitc information */
1587 char_info = g_new0(struct hps_char_info, 1);
1588 char_info->char_path = g_strdup(http_security_obj_path);
1589 _bt_hps_set_char_value(http_security_obj_path, &cp, 1);
1590 hps_char_list = g_slist_append(hps_char_list, char_info);
1593 ret = bluetooth_gatt_register_service(hps_obj_path);
1594 if(ret != BLUETOOTH_ERROR_NONE) {
1595 BT_ERR("Failed to register service %d", ret);
1603 delete_all_characterisitc();
1604 delete_all_notify_read_status();
1610 static void _bt_hps_sig_handler(int sig)
1616 BT_DBG("caught signal - sigterm\n");
1619 BT_DBG("caught signal - sigint\n");
1622 BT_DBG("caught signal - sigkill\n");
1625 BT_DBG("caught signal %d and ignored\n",sig);
1630 void _bt_hps_exit(void)
1640 if(g_header != NULL) {
1645 if(g_entity != NULL) {
1650 soup_session_abort(hps_soup_session);
1651 g_assert_cmpint(G_OBJECT (hps_soup_session)->ref_count, ==, 1);
1652 g_object_unref(hps_soup_session);
1655 delete_all_characterisitc();
1658 ret = bluetooth_gatt_deinit();
1659 if(ret != BLUETOOTH_ERROR_NONE) {
1660 BT_ERR("Failed to Deinit GATT %d", ret);
1663 ret = bluetooth_unregister_callback();
1664 if(ret != BLUETOOTH_ERROR_NONE) {
1665 BT_ERR("Failed to Unregister callback %d", ret);
1668 _bt_hps_deinit_event_receiver();
1670 _bt_hps_unregister_interface();
1672 if (main_loop != NULL) {
1673 g_main_loop_quit(main_loop);
1677 void bt_hps_event_callback(int event, bluetooth_event_param_t* param,
1680 BT_DBG("HPS event %d", event);
1684 /* HTTP Proxy Service Main loop */
1687 struct sigaction sa;
1689 BT_ERR("Starting the bt-httpproxy daemon");
1691 /* Values taken from http://www.browserscope.org/ following
1692 * the rule "Do What Every Other Modern Browser Is Doing". They seem
1693 * to significantly improve page loading time compared to soup's
1695 * Change MAX_CONNECTIONS_PER_HOST value 6 -> 12, and maxConnections is changed from 35 to 60.
1696 * Enhanced network loading speed apply tunning value. */
1697 static const int maxConnections = 60;
1698 static const int maxConnectionsPerHost = 12;
1700 memset(&sa, 0, sizeof(sa));
1701 sa.sa_handler = _bt_hps_sig_handler;
1702 sa.sa_flags = SA_SIGINFO;
1703 sigaction(SIGINT, &sa, NULL);
1704 sigaction(SIGTERM, &sa, NULL);
1705 sigaction(SIGKILL, &sa, NULL);
1708 if(bluetooth_register_callback(bt_hps_event_callback, NULL) != BLUETOOTH_ERROR_NONE) {
1709 BT_ERR("bluetooth_register_callback returned failiure");
1714 if (_bt_hps_register_interface() != BLUETOOTH_ERROR_NONE) {
1715 BT_ERR("Fail to register http proxy service");
1719 if (_bt_hps_init_event_receiver() != BLUETOOTH_ERROR_NONE) {
1720 BT_ERR("Fail to init event reciever");
1724 hps_soup_session = soup_session_async_new();
1725 if (hps_soup_session == NULL) {
1726 BT_ERR("Failed to soup_session_async_new");
1729 /* Set Soup Session Fetures */
1730 g_object_set(hps_soup_session,
1731 SOUP_SESSION_MAX_CONNS, maxConnections,
1732 SOUP_SESSION_MAX_CONNS_PER_HOST, maxConnectionsPerHost,
1733 SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER,
1734 SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_SNIFFER,
1735 SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_RESOLVER_DEFAULT,
1736 SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
1739 main_loop = g_main_loop_new(NULL, FALSE);
1741 g_main_loop_run(main_loop);
1743 BT_DBG("g_main_loop_quit called!");
1745 if (main_loop != NULL) {
1746 g_main_loop_unref(main_loop);