diff options
Diffstat (limited to 'hcid')
-rw-r--r-- | hcid/dbus-database.c | 134 |
1 files changed, 130 insertions, 4 deletions
diff --git a/hcid/dbus-database.c b/hcid/dbus-database.c index 3421c5b3..ac7e07d3 100644 --- a/hcid/dbus-database.c +++ b/hcid/dbus-database.c @@ -25,25 +25,99 @@ #include <config.h> #endif +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include <bluetooth/bluetooth.h> +#include <bluetooth/sdp.h> +#include <bluetooth/sdp_lib.h> + #include <dbus/dbus.h> #include "dbus.h" #include "hcid.h" +#include "sdpd.h" +#include "sdp-xml.h" #include "dbus-common.h" #include "dbus-error.h" #include "dbus-database.h" +static GSList *records = NULL; + +struct record_data { + uint32_t handle; + char *sender; +}; + +static struct record_data *find_record(uint32_t handle, const char *sender) +{ + GSList *list; + + for (list = records; list; list = list->next) { + struct record_data *data = list->data; + if (handle == data->handle && !strcmp(sender, data->sender)) + return data; + } + + return NULL; +} + +static void exit_callback(const char *name, void *user_data) +{ + struct record_data *user_record = user_data; + + records = g_slist_remove(records, user_record); + + remove_record_from_server(user_record->handle); + + free(user_record); +} + static DBusHandlerResult add_service_record(DBusConnection *conn, DBusMessage *msg, void *data) { DBusMessage *reply; - dbus_uint32_t handle = 0x12345; + DBusMessageIter iter, array; + const char *sender; + struct record_data *user_record; + const uint8_t *record; + uint32_t size = 0; + int len = -1; + + dbus_message_iter_init(msg, &iter); + dbus_message_iter_recurse(&iter, &array); + + dbus_message_iter_get_fixed_array(&array, &record, &len); + if (len <= 0) + return error_invalid_arguments(conn, msg); + + user_record = malloc(sizeof(*user_record)); + if (!user_record) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + size = len; + + if (register_sdp_record((uint8_t *) record, size, + &user_record->handle) < 0) { + error("Failed to register service record"); + free(user_record); + return error_failed(conn, msg, errno); + } + + sender = dbus_message_get_sender(msg); + + user_record->sender = strdup(sender); + + records = g_slist_append(records, user_record); + + name_listener_add(conn, sender, exit_callback, user_record); reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; - dbus_message_append_args(reply, DBUS_TYPE_UINT32, &handle, + dbus_message_append_args(reply, DBUS_TYPE_UINT32, &user_record->handle, DBUS_TYPE_INVALID); return send_message_and_unref(conn, reply); @@ -53,13 +127,46 @@ static DBusHandlerResult add_service_record_from_xml(DBusConnection *conn, DBusMessage *msg, void *data) { DBusMessage *reply; - dbus_uint32_t handle = 0x12345; + const char *sender, *record; + struct record_data *user_record; + sdp_record_t *sdp_record; + + if (dbus_message_get_args(msg, NULL, + DBUS_TYPE_STRING, &record, DBUS_TYPE_INVALID) == FALSE) + return error_invalid_arguments(conn, msg); + + user_record = malloc(sizeof(*user_record)); + if (!user_record) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + sdp_record = sdp_xml_parse_record(record, strlen(record)); + if (!sdp_record) { + error("Parsing of XML service record failed"); + free(user_record); + return error_failed(conn, msg, EIO); + } + + if (add_record_to_server(sdp_record) < 0) { + error("Failed to register service record"); + free(user_record); + sdp_record_free(sdp_record); + return error_failed(conn, msg, EIO); + } + + sender = dbus_message_get_sender(msg); + + user_record->handle = sdp_record->handle; + user_record->sender = strdup(sender); + + records = g_slist_append(records, user_record); + + name_listener_add(conn, sender, exit_callback, user_record); reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; - dbus_message_append_args(reply, DBUS_TYPE_UINT32, &handle, + dbus_message_append_args(reply, DBUS_TYPE_UINT32, &user_record->handle, DBUS_TYPE_INVALID); return send_message_and_unref(conn, reply); @@ -69,6 +176,25 @@ static DBusHandlerResult remove_service_record(DBusConnection *conn, DBusMessage *msg, void *data) { DBusMessage *reply; + dbus_uint32_t handle; + const char *sender; + struct record_data *user_record; + + if (dbus_message_get_args(msg, NULL, + DBUS_TYPE_UINT32, &handle, DBUS_TYPE_INVALID) == FALSE) + return error_invalid_arguments(conn, msg); + + sender = dbus_message_get_sender(msg); + + user_record = find_record(handle, sender); + if (!user_record) + return error_not_available(conn, msg); + + name_listener_remove(conn, sender, exit_callback, user_record); + + remove_record_from_server(handle); + + free(user_record); reply = dbus_message_new_method_return(msg); if (!reply) |