service.c revision 20ccc578c85111ca8790bd773b6fa337e80b4c71
11591693c7b415e9869157c711fe11263c95d74eDavid Li/* 21591693c7b415e9869157c711fe11263c95d74eDavid Li * 31591693c7b415e9869157c711fe11263c95d74eDavid Li * BlueZ - Bluetooth protocol stack for Linux 41591693c7b415e9869157c711fe11263c95d74eDavid Li * 51591693c7b415e9869157c711fe11263c95d74eDavid Li * Copyright (C) 2006-2010 Nokia Corporation 61591693c7b415e9869157c711fe11263c95d74eDavid Li * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org> 71591693c7b415e9869157c711fe11263c95d74eDavid Li * 81591693c7b415e9869157c711fe11263c95d74eDavid Li * 91591693c7b415e9869157c711fe11263c95d74eDavid Li * This program is free software; you can redistribute it and/or modify 101591693c7b415e9869157c711fe11263c95d74eDavid Li * it under the terms of the GNU General Public License as published by 111591693c7b415e9869157c711fe11263c95d74eDavid Li * the Free Software Foundation; either version 2 of the License, or 121591693c7b415e9869157c711fe11263c95d74eDavid Li * (at your option) any later version. 131591693c7b415e9869157c711fe11263c95d74eDavid Li * 141591693c7b415e9869157c711fe11263c95d74eDavid Li * This program is distributed in the hope that it will be useful, 151591693c7b415e9869157c711fe11263c95d74eDavid Li * but WITHOUT ANY WARRANTY; without even the implied warranty of 161591693c7b415e9869157c711fe11263c95d74eDavid Li * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 171591693c7b415e9869157c711fe11263c95d74eDavid Li * GNU General Public License for more details. 181591693c7b415e9869157c711fe11263c95d74eDavid Li * 191591693c7b415e9869157c711fe11263c95d74eDavid Li * You should have received a copy of the GNU General Public License 201591693c7b415e9869157c711fe11263c95d74eDavid Li * along with this program; if not, write to the Free Software 211591693c7b415e9869157c711fe11263c95d74eDavid Li * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 221591693c7b415e9869157c711fe11263c95d74eDavid Li * 231591693c7b415e9869157c711fe11263c95d74eDavid Li */ 241591693c7b415e9869157c711fe11263c95d74eDavid Li 251591693c7b415e9869157c711fe11263c95d74eDavid Li#ifdef HAVE_CONFIG_H 261591693c7b415e9869157c711fe11263c95d74eDavid Li#include <config.h> 271591693c7b415e9869157c711fe11263c95d74eDavid Li#endif 281591693c7b415e9869157c711fe11263c95d74eDavid Li 291591693c7b415e9869157c711fe11263c95d74eDavid Li#include <errno.h> 301591693c7b415e9869157c711fe11263c95d74eDavid Li#include <stdlib.h> 311591693c7b415e9869157c711fe11263c95d74eDavid Li#include <string.h> 321591693c7b415e9869157c711fe11263c95d74eDavid Li 331591693c7b415e9869157c711fe11263c95d74eDavid Li#include <bluetooth/bluetooth.h> 341591693c7b415e9869157c711fe11263c95d74eDavid Li#include <bluetooth/sdp.h> 351591693c7b415e9869157c711fe11263c95d74eDavid Li#include <bluetooth/sdp_lib.h> 361591693c7b415e9869157c711fe11263c95d74eDavid Li 371591693c7b415e9869157c711fe11263c95d74eDavid Li#include <gdbus.h> 381591693c7b415e9869157c711fe11263c95d74eDavid Li 391591693c7b415e9869157c711fe11263c95d74eDavid Li#include "sdpd.h" 401591693c7b415e9869157c711fe11263c95d74eDavid Li#include "sdp-xml.h" 411591693c7b415e9869157c711fe11263c95d74eDavid Li#include "plugin.h" 421591693c7b415e9869157c711fe11263c95d74eDavid Li#include "adapter.h" 431591693c7b415e9869157c711fe11263c95d74eDavid Li#include "error.h" 441591693c7b415e9869157c711fe11263c95d74eDavid Li#include "log.h" 451591693c7b415e9869157c711fe11263c95d74eDavid Li 461591693c7b415e9869157c711fe11263c95d74eDavid Li#define SERVICE_INTERFACE "org.bluez.Service" 471591693c7b415e9869157c711fe11263c95d74eDavid Li 481591693c7b415e9869157c711fe11263c95d74eDavid Listatic DBusConnection *connection; 491591693c7b415e9869157c711fe11263c95d74eDavid Li 501591693c7b415e9869157c711fe11263c95d74eDavid Listruct record_data { 511591693c7b415e9869157c711fe11263c95d74eDavid Li uint32_t handle; 521591693c7b415e9869157c711fe11263c95d74eDavid Li char *sender; 531591693c7b415e9869157c711fe11263c95d74eDavid Li guint listener_id; 541591693c7b415e9869157c711fe11263c95d74eDavid Li struct service_adapter *serv_adapter; 551591693c7b415e9869157c711fe11263c95d74eDavid Li}; 561591693c7b415e9869157c711fe11263c95d74eDavid Li 571591693c7b415e9869157c711fe11263c95d74eDavid Listruct context_data { 581591693c7b415e9869157c711fe11263c95d74eDavid Li sdp_record_t *record; 591591693c7b415e9869157c711fe11263c95d74eDavid Li sdp_data_t attr_data; 601591693c7b415e9869157c711fe11263c95d74eDavid Li struct sdp_xml_data *stack_head; 611591693c7b415e9869157c711fe11263c95d74eDavid Li uint16_t attr_id; 621591693c7b415e9869157c711fe11263c95d74eDavid Li}; 631591693c7b415e9869157c711fe11263c95d74eDavid Li 641591693c7b415e9869157c711fe11263c95d74eDavid Listruct pending_auth { 651591693c7b415e9869157c711fe11263c95d74eDavid Li DBusConnection *conn; 661591693c7b415e9869157c711fe11263c95d74eDavid Li DBusMessage *msg; 671591693c7b415e9869157c711fe11263c95d74eDavid Li char *sender; 681591693c7b415e9869157c711fe11263c95d74eDavid Li bdaddr_t dst; 691591693c7b415e9869157c711fe11263c95d74eDavid Li char uuid[MAX_LEN_UUID_STR]; 701591693c7b415e9869157c711fe11263c95d74eDavid Li}; 71c0025eb1a3d421c0355a21db9d8ea2bd81278460David Li 72c0025eb1a3d421c0355a21db9d8ea2bd81278460David Listruct service_adapter { 731591693c7b415e9869157c711fe11263c95d74eDavid Li struct btd_adapter *adapter; 74d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li GSList *pending_list; 751591693c7b415e9869157c711fe11263c95d74eDavid Li GSList *records; 761591693c7b415e9869157c711fe11263c95d74eDavid Li}; 771591693c7b415e9869157c711fe11263c95d74eDavid Li 781591693c7b415e9869157c711fe11263c95d74eDavid Listatic struct service_adapter *serv_adapter_any = NULL; 791591693c7b415e9869157c711fe11263c95d74eDavid Li 801591693c7b415e9869157c711fe11263c95d74eDavid Listatic int compute_seq_size(sdp_data_t *data) 811591693c7b415e9869157c711fe11263c95d74eDavid Li{ 821591693c7b415e9869157c711fe11263c95d74eDavid Li int unit_size = data->unitSize; 831591693c7b415e9869157c711fe11263c95d74eDavid Li sdp_data_t *seq = data->val.dataseq; 841591693c7b415e9869157c711fe11263c95d74eDavid Li 851591693c7b415e9869157c711fe11263c95d74eDavid Li for (; seq; seq = seq->next) 861591693c7b415e9869157c711fe11263c95d74eDavid Li unit_size += seq->unitSize; 871591693c7b415e9869157c711fe11263c95d74eDavid Li 881591693c7b415e9869157c711fe11263c95d74eDavid Li return unit_size; 891591693c7b415e9869157c711fe11263c95d74eDavid Li} 901591693c7b415e9869157c711fe11263c95d74eDavid Li 911591693c7b415e9869157c711fe11263c95d74eDavid Listatic void element_start(GMarkupParseContext *context, 921591693c7b415e9869157c711fe11263c95d74eDavid Li const gchar *element_name, const gchar **attribute_names, 931591693c7b415e9869157c711fe11263c95d74eDavid Li const gchar **attribute_values, gpointer user_data, GError **err) 941591693c7b415e9869157c711fe11263c95d74eDavid Li{ 951591693c7b415e9869157c711fe11263c95d74eDavid Li struct context_data *ctx_data = user_data; 961591693c7b415e9869157c711fe11263c95d74eDavid Li 971591693c7b415e9869157c711fe11263c95d74eDavid Li if (!strcmp(element_name, "record")) 981591693c7b415e9869157c711fe11263c95d74eDavid Li return; 991591693c7b415e9869157c711fe11263c95d74eDavid Li 1001591693c7b415e9869157c711fe11263c95d74eDavid Li if (!strcmp(element_name, "attribute")) { 1011591693c7b415e9869157c711fe11263c95d74eDavid Li int i; 1021591693c7b415e9869157c711fe11263c95d74eDavid Li for (i = 0; attribute_names[i]; i++) { 1031591693c7b415e9869157c711fe11263c95d74eDavid Li if (!strcmp(attribute_names[i], "id")) { 1041591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->attr_id = strtol(attribute_values[i], 0, 0); 1051591693c7b415e9869157c711fe11263c95d74eDavid Li break; 1061591693c7b415e9869157c711fe11263c95d74eDavid Li } 1071591693c7b415e9869157c711fe11263c95d74eDavid Li } 1081591693c7b415e9869157c711fe11263c95d74eDavid Li DBG("New attribute 0x%04x", ctx_data->attr_id); 1091591693c7b415e9869157c711fe11263c95d74eDavid Li return; 1101591693c7b415e9869157c711fe11263c95d74eDavid Li } 1111591693c7b415e9869157c711fe11263c95d74eDavid Li 1121591693c7b415e9869157c711fe11263c95d74eDavid Li if (ctx_data->stack_head) { 1131591693c7b415e9869157c711fe11263c95d74eDavid Li struct sdp_xml_data *newelem = sdp_xml_data_alloc(); 1141591693c7b415e9869157c711fe11263c95d74eDavid Li newelem->next = ctx_data->stack_head; 1151591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head = newelem; 1161591693c7b415e9869157c711fe11263c95d74eDavid Li } else { 1171591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head = sdp_xml_data_alloc(); 1181591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->next = NULL; 1191591693c7b415e9869157c711fe11263c95d74eDavid Li } 1201591693c7b415e9869157c711fe11263c95d74eDavid Li 1211591693c7b415e9869157c711fe11263c95d74eDavid Li if (!strcmp(element_name, "sequence")) 1221591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->data = sdp_data_alloc(SDP_SEQ8, NULL); 1231591693c7b415e9869157c711fe11263c95d74eDavid Li else if (!strcmp(element_name, "alternate")) 1241591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->data = sdp_data_alloc(SDP_ALT8, NULL); 1251591693c7b415e9869157c711fe11263c95d74eDavid Li else { 1261591693c7b415e9869157c711fe11263c95d74eDavid Li int i; 1271591693c7b415e9869157c711fe11263c95d74eDavid Li /* Parse value, name, encoding */ 1281591693c7b415e9869157c711fe11263c95d74eDavid Li for (i = 0; attribute_names[i]; i++) { 1291591693c7b415e9869157c711fe11263c95d74eDavid Li if (!strcmp(attribute_names[i], "value")) { 1301591693c7b415e9869157c711fe11263c95d74eDavid Li int curlen = strlen(ctx_data->stack_head->text); 1311591693c7b415e9869157c711fe11263c95d74eDavid Li int attrlen = strlen(attribute_values[i]); 1321591693c7b415e9869157c711fe11263c95d74eDavid Li 1331591693c7b415e9869157c711fe11263c95d74eDavid Li /* Ensure we're big enough */ 1341591693c7b415e9869157c711fe11263c95d74eDavid Li while ((curlen + 1 + attrlen) > ctx_data->stack_head->size) { 1351591693c7b415e9869157c711fe11263c95d74eDavid Li sdp_xml_data_expand(ctx_data->stack_head); 1361591693c7b415e9869157c711fe11263c95d74eDavid Li } 1371591693c7b415e9869157c711fe11263c95d74eDavid Li 1381591693c7b415e9869157c711fe11263c95d74eDavid Li memcpy(ctx_data->stack_head->text + curlen, 1391591693c7b415e9869157c711fe11263c95d74eDavid Li attribute_values[i], attrlen); 1401591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->text[curlen + attrlen] = '\0'; 1411591693c7b415e9869157c711fe11263c95d74eDavid Li } 1421591693c7b415e9869157c711fe11263c95d74eDavid Li 1431591693c7b415e9869157c711fe11263c95d74eDavid Li if (!strcmp(attribute_names[i], "encoding")) { 1441591693c7b415e9869157c711fe11263c95d74eDavid Li if (!strcmp(attribute_values[i], "hex")) 1451591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->type = 1; 1461591693c7b415e9869157c711fe11263c95d74eDavid Li } 1471591693c7b415e9869157c711fe11263c95d74eDavid Li 1481591693c7b415e9869157c711fe11263c95d74eDavid Li if (!strcmp(attribute_names[i], "name")) { 1491591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->name = strdup(attribute_values[i]); 1501591693c7b415e9869157c711fe11263c95d74eDavid Li } 1511591693c7b415e9869157c711fe11263c95d74eDavid Li } 1521591693c7b415e9869157c711fe11263c95d74eDavid Li 1531591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->data = sdp_xml_parse_datatype(element_name, 1541591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head, ctx_data->record); 1551591693c7b415e9869157c711fe11263c95d74eDavid Li 1561591693c7b415e9869157c711fe11263c95d74eDavid Li if (ctx_data->stack_head->data == NULL) 1571591693c7b415e9869157c711fe11263c95d74eDavid Li error("Can't parse element %s", element_name); 1581591693c7b415e9869157c711fe11263c95d74eDavid Li } 1591591693c7b415e9869157c711fe11263c95d74eDavid Li} 1601591693c7b415e9869157c711fe11263c95d74eDavid Li 1611591693c7b415e9869157c711fe11263c95d74eDavid Listatic void element_end(GMarkupParseContext *context, 1621591693c7b415e9869157c711fe11263c95d74eDavid Li const gchar *element_name, gpointer user_data, GError **err) 1631591693c7b415e9869157c711fe11263c95d74eDavid Li{ 1641591693c7b415e9869157c711fe11263c95d74eDavid Li struct context_data *ctx_data = user_data; 1651591693c7b415e9869157c711fe11263c95d74eDavid Li struct sdp_xml_data *elem; 1661591693c7b415e9869157c711fe11263c95d74eDavid Li 1671591693c7b415e9869157c711fe11263c95d74eDavid Li if (!strcmp(element_name, "record")) 1681591693c7b415e9869157c711fe11263c95d74eDavid Li return; 1691591693c7b415e9869157c711fe11263c95d74eDavid Li 1701591693c7b415e9869157c711fe11263c95d74eDavid Li if (!strcmp(element_name, "attribute")) { 1711591693c7b415e9869157c711fe11263c95d74eDavid Li if (ctx_data->stack_head && ctx_data->stack_head->data) { 1721591693c7b415e9869157c711fe11263c95d74eDavid Li int ret = sdp_attr_add(ctx_data->record, ctx_data->attr_id, 1731591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->data); 1741591693c7b415e9869157c711fe11263c95d74eDavid Li if (ret == -1) 1751591693c7b415e9869157c711fe11263c95d74eDavid Li DBG("Trouble adding attribute\n"); 1761591693c7b415e9869157c711fe11263c95d74eDavid Li 1771591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->data = NULL; 1781591693c7b415e9869157c711fe11263c95d74eDavid Li sdp_xml_data_free(ctx_data->stack_head); 1791591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head = NULL; 1801591693c7b415e9869157c711fe11263c95d74eDavid Li } else { 181d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li DBG("No data for attribute 0x%04x\n", ctx_data->attr_id); 1821591693c7b415e9869157c711fe11263c95d74eDavid Li } 183d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li return; 1841591693c7b415e9869157c711fe11263c95d74eDavid Li } 1851591693c7b415e9869157c711fe11263c95d74eDavid Li 1861591693c7b415e9869157c711fe11263c95d74eDavid Li if (!strcmp(element_name, "sequence")) { 1871591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->data->unitSize = compute_seq_size(ctx_data->stack_head->data); 1881591693c7b415e9869157c711fe11263c95d74eDavid Li 1891591693c7b415e9869157c711fe11263c95d74eDavid Li if (ctx_data->stack_head->data->unitSize > USHRT_MAX) { 1901591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->data->unitSize += sizeof(uint32_t); 1911591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->data->dtd = SDP_SEQ32; 1921591693c7b415e9869157c711fe11263c95d74eDavid Li } else if (ctx_data->stack_head->data->unitSize > UCHAR_MAX) { 1931591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->data->unitSize += sizeof(uint16_t); 1941591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->data->dtd = SDP_SEQ16; 1951591693c7b415e9869157c711fe11263c95d74eDavid Li } else { 1961591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->data->unitSize += sizeof(uint8_t); 1971591693c7b415e9869157c711fe11263c95d74eDavid Li } 1981591693c7b415e9869157c711fe11263c95d74eDavid Li } else if (!strcmp(element_name, "alternate")) { 1991591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->data->unitSize = compute_seq_size(ctx_data->stack_head->data); 2001591693c7b415e9869157c711fe11263c95d74eDavid Li 2011591693c7b415e9869157c711fe11263c95d74eDavid Li if (ctx_data->stack_head->data->unitSize > USHRT_MAX) { 2021591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->data->unitSize += sizeof(uint32_t); 2031591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->data->dtd = SDP_ALT32; 2041591693c7b415e9869157c711fe11263c95d74eDavid Li } else if (ctx_data->stack_head->data->unitSize > UCHAR_MAX) { 2051591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->data->unitSize += sizeof(uint16_t); 2061591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->data->dtd = SDP_ALT16; 2071591693c7b415e9869157c711fe11263c95d74eDavid Li } else { 2081591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->data->unitSize += sizeof(uint8_t); 2091591693c7b415e9869157c711fe11263c95d74eDavid Li } 2101591693c7b415e9869157c711fe11263c95d74eDavid Li } 2111591693c7b415e9869157c711fe11263c95d74eDavid Li 2121591693c7b415e9869157c711fe11263c95d74eDavid Li if (ctx_data->stack_head->next && ctx_data->stack_head->data && 2131591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->next->data) { 2141591693c7b415e9869157c711fe11263c95d74eDavid Li switch (ctx_data->stack_head->next->data->dtd) { 2151591693c7b415e9869157c711fe11263c95d74eDavid Li case SDP_SEQ8: 2161591693c7b415e9869157c711fe11263c95d74eDavid Li case SDP_SEQ16: 2171591693c7b415e9869157c711fe11263c95d74eDavid Li case SDP_SEQ32: 2181591693c7b415e9869157c711fe11263c95d74eDavid Li case SDP_ALT8: 2191591693c7b415e9869157c711fe11263c95d74eDavid Li case SDP_ALT16: 2201591693c7b415e9869157c711fe11263c95d74eDavid Li case SDP_ALT32: 2211591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->next->data->val.dataseq = 2221591693c7b415e9869157c711fe11263c95d74eDavid Li sdp_seq_append(ctx_data->stack_head->next->data->val.dataseq, 2231591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->data); 2241591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head->data = NULL; 2251591693c7b415e9869157c711fe11263c95d74eDavid Li break; 2261591693c7b415e9869157c711fe11263c95d74eDavid Li } 2271591693c7b415e9869157c711fe11263c95d74eDavid Li 2281591693c7b415e9869157c711fe11263c95d74eDavid Li elem = ctx_data->stack_head; 2291591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->stack_head = ctx_data->stack_head->next; 2301591693c7b415e9869157c711fe11263c95d74eDavid Li 2311591693c7b415e9869157c711fe11263c95d74eDavid Li sdp_xml_data_free(elem); 2321591693c7b415e9869157c711fe11263c95d74eDavid Li } 2331591693c7b415e9869157c711fe11263c95d74eDavid Li} 2341591693c7b415e9869157c711fe11263c95d74eDavid Li 2351591693c7b415e9869157c711fe11263c95d74eDavid Listatic GMarkupParser parser = { 2361591693c7b415e9869157c711fe11263c95d74eDavid Li element_start, element_end, NULL, NULL, NULL 2371591693c7b415e9869157c711fe11263c95d74eDavid Li}; 2381591693c7b415e9869157c711fe11263c95d74eDavid Li 2391591693c7b415e9869157c711fe11263c95d74eDavid Listatic sdp_record_t *sdp_xml_parse_record(const char *data, int size) 2401591693c7b415e9869157c711fe11263c95d74eDavid Li{ 2411591693c7b415e9869157c711fe11263c95d74eDavid Li GMarkupParseContext *ctx; 2421591693c7b415e9869157c711fe11263c95d74eDavid Li struct context_data *ctx_data; 2431591693c7b415e9869157c711fe11263c95d74eDavid Li sdp_record_t *record; 2441591693c7b415e9869157c711fe11263c95d74eDavid Li 2451591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data = malloc(sizeof(*ctx_data)); 2461591693c7b415e9869157c711fe11263c95d74eDavid Li if (!ctx_data) 2471591693c7b415e9869157c711fe11263c95d74eDavid Li return NULL; 2481591693c7b415e9869157c711fe11263c95d74eDavid Li 2491591693c7b415e9869157c711fe11263c95d74eDavid Li record = sdp_record_alloc(); 2501591693c7b415e9869157c711fe11263c95d74eDavid Li if (!record) { 2511591693c7b415e9869157c711fe11263c95d74eDavid Li free(ctx_data); 2521591693c7b415e9869157c711fe11263c95d74eDavid Li return NULL; 2531591693c7b415e9869157c711fe11263c95d74eDavid Li } 2541591693c7b415e9869157c711fe11263c95d74eDavid Li 2551591693c7b415e9869157c711fe11263c95d74eDavid Li memset(ctx_data, 0, sizeof(*ctx_data)); 2561591693c7b415e9869157c711fe11263c95d74eDavid Li ctx_data->record = record; 2571591693c7b415e9869157c711fe11263c95d74eDavid Li 2581591693c7b415e9869157c711fe11263c95d74eDavid Li ctx = g_markup_parse_context_new(&parser, 0, ctx_data, NULL); 2591591693c7b415e9869157c711fe11263c95d74eDavid Li 2601591693c7b415e9869157c711fe11263c95d74eDavid Li if (g_markup_parse_context_parse(ctx, data, size, NULL) == FALSE) { 2611591693c7b415e9869157c711fe11263c95d74eDavid Li error("XML parsing error"); 2621591693c7b415e9869157c711fe11263c95d74eDavid Li g_markup_parse_context_free(ctx); 2631591693c7b415e9869157c711fe11263c95d74eDavid Li sdp_record_free(record); 2641591693c7b415e9869157c711fe11263c95d74eDavid Li free(ctx_data); 2651591693c7b415e9869157c711fe11263c95d74eDavid Li return NULL; 2661591693c7b415e9869157c711fe11263c95d74eDavid Li } 2671591693c7b415e9869157c711fe11263c95d74eDavid Li 2681591693c7b415e9869157c711fe11263c95d74eDavid Li g_markup_parse_context_free(ctx); 2691591693c7b415e9869157c711fe11263c95d74eDavid Li 2701591693c7b415e9869157c711fe11263c95d74eDavid Li free(ctx_data); 2711591693c7b415e9869157c711fe11263c95d74eDavid Li 2721591693c7b415e9869157c711fe11263c95d74eDavid Li return record; 2731591693c7b415e9869157c711fe11263c95d74eDavid Li} 2741591693c7b415e9869157c711fe11263c95d74eDavid Li 2751591693c7b415e9869157c711fe11263c95d74eDavid Listatic struct record_data *find_record(struct service_adapter *serv_adapter, 2761591693c7b415e9869157c711fe11263c95d74eDavid Li uint32_t handle, const char *sender) 2771591693c7b415e9869157c711fe11263c95d74eDavid Li{ 2781591693c7b415e9869157c711fe11263c95d74eDavid Li GSList *list; 2791591693c7b415e9869157c711fe11263c95d74eDavid Li 2801591693c7b415e9869157c711fe11263c95d74eDavid Li for (list = serv_adapter->records; list; list = list->next) { 2811591693c7b415e9869157c711fe11263c95d74eDavid Li struct record_data *data = list->data; 2821591693c7b415e9869157c711fe11263c95d74eDavid Li if (handle == data->handle && !strcmp(sender, data->sender)) 2831591693c7b415e9869157c711fe11263c95d74eDavid Li return data; 2841591693c7b415e9869157c711fe11263c95d74eDavid Li } 2851591693c7b415e9869157c711fe11263c95d74eDavid Li 2861591693c7b415e9869157c711fe11263c95d74eDavid Li return NULL; 2871591693c7b415e9869157c711fe11263c95d74eDavid Li} 2881591693c7b415e9869157c711fe11263c95d74eDavid Li 2891591693c7b415e9869157c711fe11263c95d74eDavid Listatic struct pending_auth *next_pending(struct service_adapter *serv_adapter) 2901591693c7b415e9869157c711fe11263c95d74eDavid Li{ 2911591693c7b415e9869157c711fe11263c95d74eDavid Li GSList *l = serv_adapter->pending_list; 2921591693c7b415e9869157c711fe11263c95d74eDavid Li 2931591693c7b415e9869157c711fe11263c95d74eDavid Li if (l) { 2941591693c7b415e9869157c711fe11263c95d74eDavid Li struct pending_auth *auth = l->data; 2951591693c7b415e9869157c711fe11263c95d74eDavid Li return auth; 2961591693c7b415e9869157c711fe11263c95d74eDavid Li } 2971591693c7b415e9869157c711fe11263c95d74eDavid Li 2981591693c7b415e9869157c711fe11263c95d74eDavid Li return NULL; 2991591693c7b415e9869157c711fe11263c95d74eDavid Li} 3001591693c7b415e9869157c711fe11263c95d74eDavid Li 3011591693c7b415e9869157c711fe11263c95d74eDavid Listatic struct pending_auth *find_pending_by_sender( 3021591693c7b415e9869157c711fe11263c95d74eDavid Li struct service_adapter *serv_adapter, 3031591693c7b415e9869157c711fe11263c95d74eDavid Li const char *sender) 3041591693c7b415e9869157c711fe11263c95d74eDavid Li{ 3051591693c7b415e9869157c711fe11263c95d74eDavid Li GSList *l = serv_adapter->pending_list; 3061591693c7b415e9869157c711fe11263c95d74eDavid Li 3071591693c7b415e9869157c711fe11263c95d74eDavid Li for (; l; l = l->next) { 3081591693c7b415e9869157c711fe11263c95d74eDavid Li struct pending_auth *auth = l->data; 3091591693c7b415e9869157c711fe11263c95d74eDavid Li if (g_str_equal(auth->sender, sender)) 3101591693c7b415e9869157c711fe11263c95d74eDavid Li return auth; 3111591693c7b415e9869157c711fe11263c95d74eDavid Li } 3121591693c7b415e9869157c711fe11263c95d74eDavid Li 3131591693c7b415e9869157c711fe11263c95d74eDavid Li return NULL; 3141591693c7b415e9869157c711fe11263c95d74eDavid Li} 3151591693c7b415e9869157c711fe11263c95d74eDavid Li 3161591693c7b415e9869157c711fe11263c95d74eDavid Listatic void exit_callback(DBusConnection *conn, void *user_data) 3171591693c7b415e9869157c711fe11263c95d74eDavid Li{ 3181591693c7b415e9869157c711fe11263c95d74eDavid Li struct record_data *user_record = user_data; 3191591693c7b415e9869157c711fe11263c95d74eDavid Li struct service_adapter *serv_adapter = user_record->serv_adapter; 3201591693c7b415e9869157c711fe11263c95d74eDavid Li struct pending_auth *auth; 3211591693c7b415e9869157c711fe11263c95d74eDavid Li 3221591693c7b415e9869157c711fe11263c95d74eDavid Li DBG("remove record"); 3231591693c7b415e9869157c711fe11263c95d74eDavid Li 3241591693c7b415e9869157c711fe11263c95d74eDavid Li serv_adapter->records = g_slist_remove(serv_adapter->records, 3251591693c7b415e9869157c711fe11263c95d74eDavid Li user_record); 3261591693c7b415e9869157c711fe11263c95d74eDavid Li 3271591693c7b415e9869157c711fe11263c95d74eDavid Li auth = find_pending_by_sender(serv_adapter, user_record->sender); 3283b02c91d7b1fcc777dbdafeb044e0df61e1ff0d8David Li if (auth) { 3291591693c7b415e9869157c711fe11263c95d74eDavid Li serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list, 3301591693c7b415e9869157c711fe11263c95d74eDavid Li auth); 3311591693c7b415e9869157c711fe11263c95d74eDavid Li g_free(auth); 3321591693c7b415e9869157c711fe11263c95d74eDavid Li } 3331591693c7b415e9869157c711fe11263c95d74eDavid Li 3341591693c7b415e9869157c711fe11263c95d74eDavid Li remove_record_from_server(user_record->handle); 3351591693c7b415e9869157c711fe11263c95d74eDavid Li 3361591693c7b415e9869157c711fe11263c95d74eDavid Li g_free(user_record->sender); 3371591693c7b415e9869157c711fe11263c95d74eDavid Li g_free(user_record); 3381591693c7b415e9869157c711fe11263c95d74eDavid Li} 3391591693c7b415e9869157c711fe11263c95d74eDavid Li 3401591693c7b415e9869157c711fe11263c95d74eDavid Listatic inline DBusMessage *invalid_arguments(DBusMessage *msg) 3411591693c7b415e9869157c711fe11263c95d74eDavid Li{ 3421591693c7b415e9869157c711fe11263c95d74eDavid Li return g_dbus_create_error(msg, ERROR_INTERFACE ".InvalidArguments", 3431591693c7b415e9869157c711fe11263c95d74eDavid Li "Invalid arguments in method call"); 3441591693c7b415e9869157c711fe11263c95d74eDavid Li} 3451591693c7b415e9869157c711fe11263c95d74eDavid Li 3461591693c7b415e9869157c711fe11263c95d74eDavid Listatic inline DBusMessage *not_available(DBusMessage *msg) 3471591693c7b415e9869157c711fe11263c95d74eDavid Li{ 3481591693c7b415e9869157c711fe11263c95d74eDavid Li return g_dbus_create_error(msg, ERROR_INTERFACE ".NotAvailable", 3491591693c7b415e9869157c711fe11263c95d74eDavid Li "Not Available"); 3501591693c7b415e9869157c711fe11263c95d74eDavid Li} 3511591693c7b415e9869157c711fe11263c95d74eDavid Li 3521591693c7b415e9869157c711fe11263c95d74eDavid Listatic inline DBusMessage *failed(DBusMessage *msg) 3531591693c7b415e9869157c711fe11263c95d74eDavid Li{ 3541591693c7b415e9869157c711fe11263c95d74eDavid Li return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", "Failed"); 3551591693c7b415e9869157c711fe11263c95d74eDavid Li} 3561591693c7b415e9869157c711fe11263c95d74eDavid Li 3571591693c7b415e9869157c711fe11263c95d74eDavid Listatic inline DBusMessage *failed_strerror(DBusMessage *msg, int err) 3581591693c7b415e9869157c711fe11263c95d74eDavid Li{ 3591591693c7b415e9869157c711fe11263c95d74eDavid Li return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", 3601591693c7b415e9869157c711fe11263c95d74eDavid Li "%s", strerror(err)); 3611591693c7b415e9869157c711fe11263c95d74eDavid Li} 3621591693c7b415e9869157c711fe11263c95d74eDavid Li 3631591693c7b415e9869157c711fe11263c95d74eDavid Listatic inline DBusMessage *not_authorized(DBusMessage *msg) 3641591693c7b415e9869157c711fe11263c95d74eDavid Li{ 3651591693c7b415e9869157c711fe11263c95d74eDavid Li return g_dbus_create_error(msg, ERROR_INTERFACE ".NotAuthorized", 3661591693c7b415e9869157c711fe11263c95d74eDavid Li "Not Authorized"); 3671591693c7b415e9869157c711fe11263c95d74eDavid Li} 3681591693c7b415e9869157c711fe11263c95d74eDavid Li 3691591693c7b415e9869157c711fe11263c95d74eDavid Listatic inline DBusMessage *does_not_exist(DBusMessage *msg) 3701591693c7b415e9869157c711fe11263c95d74eDavid Li{ 3711591693c7b415e9869157c711fe11263c95d74eDavid Li return g_dbus_create_error(msg, ERROR_INTERFACE ".DoesNotExist", 3721591693c7b415e9869157c711fe11263c95d74eDavid Li "Does Not Exist"); 3731591693c7b415e9869157c711fe11263c95d74eDavid Li} 3741591693c7b415e9869157c711fe11263c95d74eDavid Li 3751591693c7b415e9869157c711fe11263c95d74eDavid Listatic int add_xml_record(DBusConnection *conn, const char *sender, 3761591693c7b415e9869157c711fe11263c95d74eDavid Li struct service_adapter *serv_adapter, 3771591693c7b415e9869157c711fe11263c95d74eDavid Li const char *record, dbus_uint32_t *handle) 3781591693c7b415e9869157c711fe11263c95d74eDavid Li{ 3791591693c7b415e9869157c711fe11263c95d74eDavid Li struct record_data *user_record; 3801591693c7b415e9869157c711fe11263c95d74eDavid Li sdp_record_t *sdp_record; 3811591693c7b415e9869157c711fe11263c95d74eDavid Li bdaddr_t src; 3821591693c7b415e9869157c711fe11263c95d74eDavid Li 3831591693c7b415e9869157c711fe11263c95d74eDavid Li sdp_record = sdp_xml_parse_record(record, strlen(record)); 3841591693c7b415e9869157c711fe11263c95d74eDavid Li if (!sdp_record) { 3851591693c7b415e9869157c711fe11263c95d74eDavid Li error("Parsing of XML service record failed"); 3861591693c7b415e9869157c711fe11263c95d74eDavid Li return -EIO; 3871591693c7b415e9869157c711fe11263c95d74eDavid Li } 3881591693c7b415e9869157c711fe11263c95d74eDavid Li 3891591693c7b415e9869157c711fe11263c95d74eDavid Li if (serv_adapter->adapter) 3901591693c7b415e9869157c711fe11263c95d74eDavid Li adapter_get_address(serv_adapter->adapter, &src); 3911591693c7b415e9869157c711fe11263c95d74eDavid Li else 3921591693c7b415e9869157c711fe11263c95d74eDavid Li bacpy(&src, BDADDR_ANY); 3931591693c7b415e9869157c711fe11263c95d74eDavid Li 3941591693c7b415e9869157c711fe11263c95d74eDavid Li if (add_record_to_server(&src, sdp_record) < 0) { 3951591693c7b415e9869157c711fe11263c95d74eDavid Li error("Failed to register service record"); 3961591693c7b415e9869157c711fe11263c95d74eDavid Li sdp_record_free(sdp_record); 3971591693c7b415e9869157c711fe11263c95d74eDavid Li return -EIO; 3981591693c7b415e9869157c711fe11263c95d74eDavid Li } 3991591693c7b415e9869157c711fe11263c95d74eDavid Li 4001591693c7b415e9869157c711fe11263c95d74eDavid Li user_record = g_new0(struct record_data, 1); 4011591693c7b415e9869157c711fe11263c95d74eDavid Li user_record->handle = sdp_record->handle; 4021591693c7b415e9869157c711fe11263c95d74eDavid Li user_record->sender = g_strdup(sender); 4031591693c7b415e9869157c711fe11263c95d74eDavid Li user_record->serv_adapter = serv_adapter; 4041591693c7b415e9869157c711fe11263c95d74eDavid Li user_record->listener_id = g_dbus_add_disconnect_watch(conn, sender, 4051591693c7b415e9869157c711fe11263c95d74eDavid Li exit_callback, user_record, NULL); 4061591693c7b415e9869157c711fe11263c95d74eDavid Li 4071591693c7b415e9869157c711fe11263c95d74eDavid Li serv_adapter->records = g_slist_append(serv_adapter->records, 4081591693c7b415e9869157c711fe11263c95d74eDavid Li user_record); 4091591693c7b415e9869157c711fe11263c95d74eDavid Li 4101591693c7b415e9869157c711fe11263c95d74eDavid Li DBG("listener_id %d", user_record->listener_id); 4111591693c7b415e9869157c711fe11263c95d74eDavid Li 4121591693c7b415e9869157c711fe11263c95d74eDavid Li *handle = user_record->handle; 4131591693c7b415e9869157c711fe11263c95d74eDavid Li 4141591693c7b415e9869157c711fe11263c95d74eDavid Li return 0; 4151591693c7b415e9869157c711fe11263c95d74eDavid Li} 4161591693c7b415e9869157c711fe11263c95d74eDavid Li 4171591693c7b415e9869157c711fe11263c95d74eDavid Listatic DBusMessage *update_record(DBusConnection *conn, DBusMessage *msg, 418d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li struct service_adapter *serv_adapter, 4191591693c7b415e9869157c711fe11263c95d74eDavid Li dbus_uint32_t handle, sdp_record_t *sdp_record) 4201591693c7b415e9869157c711fe11263c95d74eDavid Li{ 4211591693c7b415e9869157c711fe11263c95d74eDavid Li bdaddr_t src; 4221591693c7b415e9869157c711fe11263c95d74eDavid Li int err; 4231591693c7b415e9869157c711fe11263c95d74eDavid Li 4241591693c7b415e9869157c711fe11263c95d74eDavid Li if (remove_record_from_server(handle) < 0) { 4251591693c7b415e9869157c711fe11263c95d74eDavid Li sdp_record_free(sdp_record); 4261591693c7b415e9869157c711fe11263c95d74eDavid Li return g_dbus_create_error(msg, 4271591693c7b415e9869157c711fe11263c95d74eDavid Li ERROR_INTERFACE ".NotAvailable", 4281591693c7b415e9869157c711fe11263c95d74eDavid Li "Not Available"); 4291591693c7b415e9869157c711fe11263c95d74eDavid Li } 4301591693c7b415e9869157c711fe11263c95d74eDavid Li 4311591693c7b415e9869157c711fe11263c95d74eDavid Li if (serv_adapter->adapter) 4321591693c7b415e9869157c711fe11263c95d74eDavid Li adapter_get_address(serv_adapter->adapter, &src); 4331591693c7b415e9869157c711fe11263c95d74eDavid Li else 4341591693c7b415e9869157c711fe11263c95d74eDavid Li bacpy(&src, BDADDR_ANY); 4351591693c7b415e9869157c711fe11263c95d74eDavid Li 4361591693c7b415e9869157c711fe11263c95d74eDavid Li sdp_record->handle = handle; 4371591693c7b415e9869157c711fe11263c95d74eDavid Li err = add_record_to_server(&src, sdp_record); 4381591693c7b415e9869157c711fe11263c95d74eDavid Li if (err < 0) { 4391591693c7b415e9869157c711fe11263c95d74eDavid Li sdp_record_free(sdp_record); 4401591693c7b415e9869157c711fe11263c95d74eDavid Li error("Failed to update the service record"); 4411591693c7b415e9869157c711fe11263c95d74eDavid Li return g_dbus_create_error(msg, 4421591693c7b415e9869157c711fe11263c95d74eDavid Li ERROR_INTERFACE ".Failed", 4431591693c7b415e9869157c711fe11263c95d74eDavid Li "%s", strerror(EIO)); 4441591693c7b415e9869157c711fe11263c95d74eDavid Li } 4451591693c7b415e9869157c711fe11263c95d74eDavid Li 4461591693c7b415e9869157c711fe11263c95d74eDavid Li return dbus_message_new_method_return(msg); 4471591693c7b415e9869157c711fe11263c95d74eDavid Li} 4481591693c7b415e9869157c711fe11263c95d74eDavid Li 4491591693c7b415e9869157c711fe11263c95d74eDavid Listatic DBusMessage *update_xml_record(DBusConnection *conn, 4501591693c7b415e9869157c711fe11263c95d74eDavid Li DBusMessage *msg, 4511591693c7b415e9869157c711fe11263c95d74eDavid Li struct service_adapter *serv_adapter) 4521591693c7b415e9869157c711fe11263c95d74eDavid Li{ 4531591693c7b415e9869157c711fe11263c95d74eDavid Li struct record_data *user_record; 4543b02c91d7b1fcc777dbdafeb044e0df61e1ff0d8David Li sdp_record_t *sdp_record; 4551591693c7b415e9869157c711fe11263c95d74eDavid Li const char *record; 4561591693c7b415e9869157c711fe11263c95d74eDavid Li dbus_uint32_t handle; 4571591693c7b415e9869157c711fe11263c95d74eDavid Li int len; 4581591693c7b415e9869157c711fe11263c95d74eDavid Li 4591591693c7b415e9869157c711fe11263c95d74eDavid Li if (dbus_message_get_args(msg, NULL, 4601591693c7b415e9869157c711fe11263c95d74eDavid Li DBUS_TYPE_UINT32, &handle, 4611591693c7b415e9869157c711fe11263c95d74eDavid Li DBUS_TYPE_STRING, &record, 4621591693c7b415e9869157c711fe11263c95d74eDavid Li DBUS_TYPE_INVALID) == FALSE) 4631591693c7b415e9869157c711fe11263c95d74eDavid Li return NULL; 4641591693c7b415e9869157c711fe11263c95d74eDavid Li 4651591693c7b415e9869157c711fe11263c95d74eDavid Li len = (record ? strlen(record) : 0); 4661591693c7b415e9869157c711fe11263c95d74eDavid Li if (len == 0) 4671591693c7b415e9869157c711fe11263c95d74eDavid Li return invalid_arguments(msg); 4681591693c7b415e9869157c711fe11263c95d74eDavid Li 4691591693c7b415e9869157c711fe11263c95d74eDavid Li user_record = find_record(serv_adapter, handle, 4701591693c7b415e9869157c711fe11263c95d74eDavid Li dbus_message_get_sender(msg)); 4711591693c7b415e9869157c711fe11263c95d74eDavid Li if (!user_record) 4721591693c7b415e9869157c711fe11263c95d74eDavid Li return g_dbus_create_error(msg, 4731591693c7b415e9869157c711fe11263c95d74eDavid Li ERROR_INTERFACE ".NotAvailable", 4741591693c7b415e9869157c711fe11263c95d74eDavid Li "Not Available"); 4751591693c7b415e9869157c711fe11263c95d74eDavid Li 4761591693c7b415e9869157c711fe11263c95d74eDavid Li sdp_record = sdp_xml_parse_record(record, len); 4771591693c7b415e9869157c711fe11263c95d74eDavid Li if (!sdp_record) { 4781591693c7b415e9869157c711fe11263c95d74eDavid Li error("Parsing of XML service record failed"); 4791591693c7b415e9869157c711fe11263c95d74eDavid Li sdp_record_free(sdp_record); 4801591693c7b415e9869157c711fe11263c95d74eDavid Li return g_dbus_create_error(msg, 4811591693c7b415e9869157c711fe11263c95d74eDavid Li ERROR_INTERFACE ".Failed", 4821591693c7b415e9869157c711fe11263c95d74eDavid Li "%s", strerror(EIO)); 4831591693c7b415e9869157c711fe11263c95d74eDavid Li } 4841591693c7b415e9869157c711fe11263c95d74eDavid Li 4851591693c7b415e9869157c711fe11263c95d74eDavid Li return update_record(conn, msg, serv_adapter, handle, sdp_record); 4861591693c7b415e9869157c711fe11263c95d74eDavid Li} 4871591693c7b415e9869157c711fe11263c95d74eDavid Li 4881591693c7b415e9869157c711fe11263c95d74eDavid Listatic int remove_record(DBusConnection *conn, const char *sender, 4891591693c7b415e9869157c711fe11263c95d74eDavid Li struct service_adapter *serv_adapter, 4901591693c7b415e9869157c711fe11263c95d74eDavid Li dbus_uint32_t handle) 4911591693c7b415e9869157c711fe11263c95d74eDavid Li{ 4921591693c7b415e9869157c711fe11263c95d74eDavid Li struct record_data *user_record; 4931591693c7b415e9869157c711fe11263c95d74eDavid Li 4941591693c7b415e9869157c711fe11263c95d74eDavid Li DBG("remove record 0x%x", handle); 4951591693c7b415e9869157c711fe11263c95d74eDavid Li 4961591693c7b415e9869157c711fe11263c95d74eDavid Li user_record = find_record(serv_adapter, handle, sender); 4971591693c7b415e9869157c711fe11263c95d74eDavid Li if (!user_record) 4981591693c7b415e9869157c711fe11263c95d74eDavid Li return -1; 4991591693c7b415e9869157c711fe11263c95d74eDavid Li 5001591693c7b415e9869157c711fe11263c95d74eDavid Li DBG("listner_id %d", user_record->listener_id); 5011591693c7b415e9869157c711fe11263c95d74eDavid Li 5021591693c7b415e9869157c711fe11263c95d74eDavid Li g_dbus_remove_watch(conn, user_record->listener_id); 5031591693c7b415e9869157c711fe11263c95d74eDavid Li 5041591693c7b415e9869157c711fe11263c95d74eDavid Li exit_callback(conn, user_record); 5051591693c7b415e9869157c711fe11263c95d74eDavid Li 5061591693c7b415e9869157c711fe11263c95d74eDavid Li return 0; 5071591693c7b415e9869157c711fe11263c95d74eDavid Li} 5081591693c7b415e9869157c711fe11263c95d74eDavid Li 5091591693c7b415e9869157c711fe11263c95d74eDavid Listatic DBusMessage *add_service_record(DBusConnection *conn, 5101591693c7b415e9869157c711fe11263c95d74eDavid Li DBusMessage *msg, void *data) 5111591693c7b415e9869157c711fe11263c95d74eDavid Li{ 5121591693c7b415e9869157c711fe11263c95d74eDavid Li struct service_adapter *serv_adapter = data; 5131591693c7b415e9869157c711fe11263c95d74eDavid Li DBusMessage *reply; 5141591693c7b415e9869157c711fe11263c95d74eDavid Li const char *sender, *record; 5151591693c7b415e9869157c711fe11263c95d74eDavid Li dbus_uint32_t handle; 5161591693c7b415e9869157c711fe11263c95d74eDavid Li int err; 5171591693c7b415e9869157c711fe11263c95d74eDavid Li 5181591693c7b415e9869157c711fe11263c95d74eDavid Li if (dbus_message_get_args(msg, NULL, 5191591693c7b415e9869157c711fe11263c95d74eDavid Li DBUS_TYPE_STRING, &record, DBUS_TYPE_INVALID) == FALSE) 5201591693c7b415e9869157c711fe11263c95d74eDavid Li return NULL; 5211591693c7b415e9869157c711fe11263c95d74eDavid Li 5221591693c7b415e9869157c711fe11263c95d74eDavid Li sender = dbus_message_get_sender(msg); 5231591693c7b415e9869157c711fe11263c95d74eDavid Li err = add_xml_record(conn, sender, serv_adapter, record, &handle); 5241591693c7b415e9869157c711fe11263c95d74eDavid Li if (err < 0) 5251591693c7b415e9869157c711fe11263c95d74eDavid Li return failed_strerror(msg, err); 5261591693c7b415e9869157c711fe11263c95d74eDavid Li 5271591693c7b415e9869157c711fe11263c95d74eDavid Li reply = dbus_message_new_method_return(msg); 5281591693c7b415e9869157c711fe11263c95d74eDavid Li if (!reply) 5291591693c7b415e9869157c711fe11263c95d74eDavid Li return NULL; 5301591693c7b415e9869157c711fe11263c95d74eDavid Li 5311591693c7b415e9869157c711fe11263c95d74eDavid Li dbus_message_append_args(reply, DBUS_TYPE_UINT32, &handle, 5321591693c7b415e9869157c711fe11263c95d74eDavid Li DBUS_TYPE_INVALID); 5331591693c7b415e9869157c711fe11263c95d74eDavid Li 5341591693c7b415e9869157c711fe11263c95d74eDavid Li return reply; 5351591693c7b415e9869157c711fe11263c95d74eDavid Li} 5361591693c7b415e9869157c711fe11263c95d74eDavid Li 5371591693c7b415e9869157c711fe11263c95d74eDavid Listatic DBusMessage *update_service_record(DBusConnection *conn, 5381591693c7b415e9869157c711fe11263c95d74eDavid Li DBusMessage *msg, void *data) 5391591693c7b415e9869157c711fe11263c95d74eDavid Li{ 5401591693c7b415e9869157c711fe11263c95d74eDavid Li struct service_adapter *serv_adapter = data; 5411591693c7b415e9869157c711fe11263c95d74eDavid Li 5421591693c7b415e9869157c711fe11263c95d74eDavid Li return update_xml_record(conn, msg, serv_adapter); 5431591693c7b415e9869157c711fe11263c95d74eDavid Li} 5441591693c7b415e9869157c711fe11263c95d74eDavid Li 5451591693c7b415e9869157c711fe11263c95d74eDavid Listatic DBusMessage *remove_service_record(DBusConnection *conn, 5461591693c7b415e9869157c711fe11263c95d74eDavid Li DBusMessage *msg, void *data) 5471591693c7b415e9869157c711fe11263c95d74eDavid Li{ 5481591693c7b415e9869157c711fe11263c95d74eDavid Li struct service_adapter *serv_adapter = data; 5491591693c7b415e9869157c711fe11263c95d74eDavid Li dbus_uint32_t handle; 5501591693c7b415e9869157c711fe11263c95d74eDavid Li const char *sender; 5511591693c7b415e9869157c711fe11263c95d74eDavid Li 5521591693c7b415e9869157c711fe11263c95d74eDavid Li if (dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle, 5531591693c7b415e9869157c711fe11263c95d74eDavid Li DBUS_TYPE_INVALID) == FALSE) 5541591693c7b415e9869157c711fe11263c95d74eDavid Li return NULL; 5551591693c7b415e9869157c711fe11263c95d74eDavid Li 5561591693c7b415e9869157c711fe11263c95d74eDavid Li sender = dbus_message_get_sender(msg); 5571591693c7b415e9869157c711fe11263c95d74eDavid Li 5581591693c7b415e9869157c711fe11263c95d74eDavid Li if (remove_record(conn, sender, serv_adapter, handle) < 0) 5591591693c7b415e9869157c711fe11263c95d74eDavid Li return not_available(msg); 5601591693c7b415e9869157c711fe11263c95d74eDavid Li 5611591693c7b415e9869157c711fe11263c95d74eDavid Li return dbus_message_new_method_return(msg); 5621591693c7b415e9869157c711fe11263c95d74eDavid Li} 5631591693c7b415e9869157c711fe11263c95d74eDavid Li 5641591693c7b415e9869157c711fe11263c95d74eDavid Listatic void auth_cb(DBusError *derr, void *user_data) 5651591693c7b415e9869157c711fe11263c95d74eDavid Li{ 5661591693c7b415e9869157c711fe11263c95d74eDavid Li struct service_adapter *serv_adapter = user_data; 5671591693c7b415e9869157c711fe11263c95d74eDavid Li DBusMessage *reply; 5681591693c7b415e9869157c711fe11263c95d74eDavid Li struct pending_auth *auth; 5691591693c7b415e9869157c711fe11263c95d74eDavid Li bdaddr_t src; 5701591693c7b415e9869157c711fe11263c95d74eDavid Li 5711591693c7b415e9869157c711fe11263c95d74eDavid Li auth = next_pending(serv_adapter); 5721591693c7b415e9869157c711fe11263c95d74eDavid Li if (auth == NULL) { 5731591693c7b415e9869157c711fe11263c95d74eDavid Li info("Authorization cancelled: Client exited"); 5741591693c7b415e9869157c711fe11263c95d74eDavid Li return; 5753b02c91d7b1fcc777dbdafeb044e0df61e1ff0d8David Li } 5761591693c7b415e9869157c711fe11263c95d74eDavid Li 5771591693c7b415e9869157c711fe11263c95d74eDavid Li if (derr) { 5781591693c7b415e9869157c711fe11263c95d74eDavid Li error("Access denied: %s", derr->message); 5791591693c7b415e9869157c711fe11263c95d74eDavid Li 5801591693c7b415e9869157c711fe11263c95d74eDavid Li reply = not_authorized(auth->msg); 5811591693c7b415e9869157c711fe11263c95d74eDavid Li dbus_message_unref(auth->msg); 5821591693c7b415e9869157c711fe11263c95d74eDavid Li g_dbus_send_message(auth->conn, reply); 5831591693c7b415e9869157c711fe11263c95d74eDavid Li goto done; 5841591693c7b415e9869157c711fe11263c95d74eDavid Li } 5851591693c7b415e9869157c711fe11263c95d74eDavid Li 5861591693c7b415e9869157c711fe11263c95d74eDavid Li g_dbus_send_reply(auth->conn, auth->msg, 5871591693c7b415e9869157c711fe11263c95d74eDavid Li DBUS_TYPE_INVALID); 5881591693c7b415e9869157c711fe11263c95d74eDavid Li 5891591693c7b415e9869157c711fe11263c95d74eDavid Lidone: 5901591693c7b415e9869157c711fe11263c95d74eDavid Li dbus_connection_unref(auth->conn); 5911591693c7b415e9869157c711fe11263c95d74eDavid Li 5921591693c7b415e9869157c711fe11263c95d74eDavid Li serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list, 5931591693c7b415e9869157c711fe11263c95d74eDavid Li auth); 5941591693c7b415e9869157c711fe11263c95d74eDavid Li g_free(auth); 5951591693c7b415e9869157c711fe11263c95d74eDavid Li 5961591693c7b415e9869157c711fe11263c95d74eDavid Li auth = next_pending(serv_adapter); 5971591693c7b415e9869157c711fe11263c95d74eDavid Li if (auth == NULL) 5981591693c7b415e9869157c711fe11263c95d74eDavid Li return; 5991591693c7b415e9869157c711fe11263c95d74eDavid Li 6001591693c7b415e9869157c711fe11263c95d74eDavid Li if (serv_adapter->adapter) 6011591693c7b415e9869157c711fe11263c95d74eDavid Li adapter_get_address(serv_adapter->adapter, &src); 6021591693c7b415e9869157c711fe11263c95d74eDavid Li else 6031591693c7b415e9869157c711fe11263c95d74eDavid Li bacpy(&src, BDADDR_ANY); 6041591693c7b415e9869157c711fe11263c95d74eDavid Li 6051591693c7b415e9869157c711fe11263c95d74eDavid Li btd_request_authorization(&src, &auth->dst, 6061591693c7b415e9869157c711fe11263c95d74eDavid Li auth->uuid, auth_cb, serv_adapter); 6071591693c7b415e9869157c711fe11263c95d74eDavid Li} 6081591693c7b415e9869157c711fe11263c95d74eDavid Li 6091591693c7b415e9869157c711fe11263c95d74eDavid Listatic DBusMessage *request_authorization(DBusConnection *conn, 6101591693c7b415e9869157c711fe11263c95d74eDavid Li DBusMessage *msg, void *data) 6111591693c7b415e9869157c711fe11263c95d74eDavid Li{ 6121591693c7b415e9869157c711fe11263c95d74eDavid Li struct record_data *user_record; 6131591693c7b415e9869157c711fe11263c95d74eDavid Li struct service_adapter *serv_adapter = data; 6141591693c7b415e9869157c711fe11263c95d74eDavid Li sdp_record_t *record; 6151591693c7b415e9869157c711fe11263c95d74eDavid Li sdp_list_t *services; 6161591693c7b415e9869157c711fe11263c95d74eDavid Li const char *sender; 6171591693c7b415e9869157c711fe11263c95d74eDavid Li dbus_uint32_t handle; 6181591693c7b415e9869157c711fe11263c95d74eDavid Li const char *address; 6191591693c7b415e9869157c711fe11263c95d74eDavid Li struct pending_auth *auth; 6201591693c7b415e9869157c711fe11263c95d74eDavid Li char uuid_str[MAX_LEN_UUID_STR]; 6211591693c7b415e9869157c711fe11263c95d74eDavid Li uuid_t *uuid, *uuid128; 6221591693c7b415e9869157c711fe11263c95d74eDavid Li bdaddr_t src; 6231591693c7b415e9869157c711fe11263c95d74eDavid Li 6241591693c7b415e9869157c711fe11263c95d74eDavid Li if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address, 6251591693c7b415e9869157c711fe11263c95d74eDavid Li DBUS_TYPE_UINT32, &handle, 6261591693c7b415e9869157c711fe11263c95d74eDavid Li DBUS_TYPE_INVALID) == FALSE) 6271591693c7b415e9869157c711fe11263c95d74eDavid Li return NULL; 6281591693c7b415e9869157c711fe11263c95d74eDavid Li 6291591693c7b415e9869157c711fe11263c95d74eDavid Li sender = dbus_message_get_sender(msg); 6301591693c7b415e9869157c711fe11263c95d74eDavid Li if (find_pending_by_sender(serv_adapter, sender)) 6311591693c7b415e9869157c711fe11263c95d74eDavid Li return failed(msg); 6321591693c7b415e9869157c711fe11263c95d74eDavid Li 6331591693c7b415e9869157c711fe11263c95d74eDavid Li user_record = find_record(serv_adapter, handle, sender); 6341591693c7b415e9869157c711fe11263c95d74eDavid Li if (!user_record) { 6351591693c7b415e9869157c711fe11263c95d74eDavid Li user_record = find_record(serv_adapter_any, handle, sender); 6361591693c7b415e9869157c711fe11263c95d74eDavid Li if (!user_record) 6371591693c7b415e9869157c711fe11263c95d74eDavid Li return not_authorized(msg); 6381591693c7b415e9869157c711fe11263c95d74eDavid Li } 6391591693c7b415e9869157c711fe11263c95d74eDavid Li 6401591693c7b415e9869157c711fe11263c95d74eDavid Li record = sdp_record_find(user_record->handle); 6411591693c7b415e9869157c711fe11263c95d74eDavid Li if (record == NULL) 6421591693c7b415e9869157c711fe11263c95d74eDavid Li return not_authorized(msg); 6431591693c7b415e9869157c711fe11263c95d74eDavid Li 6441591693c7b415e9869157c711fe11263c95d74eDavid Li if (sdp_get_service_classes(record, &services) < 0) { 6451591693c7b415e9869157c711fe11263c95d74eDavid Li sdp_record_free(record); 6461591693c7b415e9869157c711fe11263c95d74eDavid Li return not_authorized(msg); 6471591693c7b415e9869157c711fe11263c95d74eDavid Li } 6481591693c7b415e9869157c711fe11263c95d74eDavid Li 6491591693c7b415e9869157c711fe11263c95d74eDavid Li if (services == NULL) 6501591693c7b415e9869157c711fe11263c95d74eDavid Li return not_authorized(msg); 6511591693c7b415e9869157c711fe11263c95d74eDavid Li 6521591693c7b415e9869157c711fe11263c95d74eDavid Li uuid = services->data; 6531591693c7b415e9869157c711fe11263c95d74eDavid Li uuid128 = sdp_uuid_to_uuid128(uuid); 6541591693c7b415e9869157c711fe11263c95d74eDavid Li 6551591693c7b415e9869157c711fe11263c95d74eDavid Li sdp_list_free(services, bt_free); 6561591693c7b415e9869157c711fe11263c95d74eDavid Li 6571591693c7b415e9869157c711fe11263c95d74eDavid Li if (sdp_uuid2strn(uuid128, uuid_str, MAX_LEN_UUID_STR) < 0) { 6581591693c7b415e9869157c711fe11263c95d74eDavid Li bt_free(uuid128); 6591591693c7b415e9869157c711fe11263c95d74eDavid Li return not_authorized(msg); 6601591693c7b415e9869157c711fe11263c95d74eDavid Li } 6611591693c7b415e9869157c711fe11263c95d74eDavid Li bt_free(uuid128); 6621591693c7b415e9869157c711fe11263c95d74eDavid Li 6631591693c7b415e9869157c711fe11263c95d74eDavid Li auth = g_new0(struct pending_auth, 1); 6641591693c7b415e9869157c711fe11263c95d74eDavid Li auth->msg = dbus_message_ref(msg); 6651591693c7b415e9869157c711fe11263c95d74eDavid Li auth->conn = dbus_connection_ref(connection); 6661591693c7b415e9869157c711fe11263c95d74eDavid Li auth->sender = user_record->sender; 6671591693c7b415e9869157c711fe11263c95d74eDavid Li memcpy(auth->uuid, uuid_str, MAX_LEN_UUID_STR); 6681591693c7b415e9869157c711fe11263c95d74eDavid Li str2ba(address, &auth->dst); 6691591693c7b415e9869157c711fe11263c95d74eDavid Li 6701591693c7b415e9869157c711fe11263c95d74eDavid Li serv_adapter->pending_list = g_slist_append(serv_adapter->pending_list, 6711591693c7b415e9869157c711fe11263c95d74eDavid Li auth); 6721591693c7b415e9869157c711fe11263c95d74eDavid Li 6731591693c7b415e9869157c711fe11263c95d74eDavid Li auth = next_pending(serv_adapter); 6741591693c7b415e9869157c711fe11263c95d74eDavid Li if (auth == NULL) 6751591693c7b415e9869157c711fe11263c95d74eDavid Li return does_not_exist(msg); 6761591693c7b415e9869157c711fe11263c95d74eDavid Li 6771591693c7b415e9869157c711fe11263c95d74eDavid Li if (serv_adapter->adapter) 6781591693c7b415e9869157c711fe11263c95d74eDavid Li adapter_get_address(serv_adapter->adapter, &src); 6791591693c7b415e9869157c711fe11263c95d74eDavid Li else 6801591693c7b415e9869157c711fe11263c95d74eDavid Li bacpy(&src, BDADDR_ANY); 6811591693c7b415e9869157c711fe11263c95d74eDavid Li 6821591693c7b415e9869157c711fe11263c95d74eDavid Li if (btd_request_authorization(&src, &auth->dst, auth->uuid, auth_cb, 6831591693c7b415e9869157c711fe11263c95d74eDavid Li serv_adapter) < 0) { 6841591693c7b415e9869157c711fe11263c95d74eDavid Li serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list, 6851591693c7b415e9869157c711fe11263c95d74eDavid Li auth); 6861591693c7b415e9869157c711fe11263c95d74eDavid Li g_free(auth); 6871591693c7b415e9869157c711fe11263c95d74eDavid Li return not_authorized(msg); 6881591693c7b415e9869157c711fe11263c95d74eDavid Li } 6891591693c7b415e9869157c711fe11263c95d74eDavid Li 6901591693c7b415e9869157c711fe11263c95d74eDavid Li return NULL; 6911591693c7b415e9869157c711fe11263c95d74eDavid Li} 6921591693c7b415e9869157c711fe11263c95d74eDavid Li 6931591693c7b415e9869157c711fe11263c95d74eDavid Listatic DBusMessage *cancel_authorization(DBusConnection *conn, 6941591693c7b415e9869157c711fe11263c95d74eDavid Li DBusMessage *msg, void *data) 6951591693c7b415e9869157c711fe11263c95d74eDavid Li{ 6961591693c7b415e9869157c711fe11263c95d74eDavid Li DBusMessage *reply; 6971591693c7b415e9869157c711fe11263c95d74eDavid Li struct service_adapter *serv_adapter = data; 6981591693c7b415e9869157c711fe11263c95d74eDavid Li struct pending_auth *auth; 6991591693c7b415e9869157c711fe11263c95d74eDavid Li const gchar *sender; 7001591693c7b415e9869157c711fe11263c95d74eDavid Li bdaddr_t src; 7011591693c7b415e9869157c711fe11263c95d74eDavid Li 7021591693c7b415e9869157c711fe11263c95d74eDavid Li sender = dbus_message_get_sender(msg); 7031591693c7b415e9869157c711fe11263c95d74eDavid Li 7041591693c7b415e9869157c711fe11263c95d74eDavid Li auth = find_pending_by_sender(serv_adapter, sender); 7051591693c7b415e9869157c711fe11263c95d74eDavid Li if (auth == NULL) 7061591693c7b415e9869157c711fe11263c95d74eDavid Li return does_not_exist(msg); 7071591693c7b415e9869157c711fe11263c95d74eDavid Li 7081591693c7b415e9869157c711fe11263c95d74eDavid Li if (serv_adapter->adapter) 7091591693c7b415e9869157c711fe11263c95d74eDavid Li adapter_get_address(serv_adapter->adapter, &src); 7101591693c7b415e9869157c711fe11263c95d74eDavid Li else 7111591693c7b415e9869157c711fe11263c95d74eDavid Li bacpy(&src, BDADDR_ANY); 7121591693c7b415e9869157c711fe11263c95d74eDavid Li 7131591693c7b415e9869157c711fe11263c95d74eDavid Li btd_cancel_authorization(&src, &auth->dst); 7141591693c7b415e9869157c711fe11263c95d74eDavid Li 7151591693c7b415e9869157c711fe11263c95d74eDavid Li reply = not_authorized(auth->msg); 7161591693c7b415e9869157c711fe11263c95d74eDavid Li dbus_message_unref(auth->msg); 7171591693c7b415e9869157c711fe11263c95d74eDavid Li g_dbus_send_message(auth->conn, reply); 7181591693c7b415e9869157c711fe11263c95d74eDavid Li 7191591693c7b415e9869157c711fe11263c95d74eDavid Li dbus_connection_unref(auth->conn); 7201591693c7b415e9869157c711fe11263c95d74eDavid Li 7211591693c7b415e9869157c711fe11263c95d74eDavid Li serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list, 7221591693c7b415e9869157c711fe11263c95d74eDavid Li auth); 7231591693c7b415e9869157c711fe11263c95d74eDavid Li g_free(auth); 7241591693c7b415e9869157c711fe11263c95d74eDavid Li 7251591693c7b415e9869157c711fe11263c95d74eDavid Li auth = next_pending(serv_adapter); 7261591693c7b415e9869157c711fe11263c95d74eDavid Li if (auth == NULL) 7271591693c7b415e9869157c711fe11263c95d74eDavid Li goto done; 7281591693c7b415e9869157c711fe11263c95d74eDavid Li 7291591693c7b415e9869157c711fe11263c95d74eDavid Li if (serv_adapter->adapter) 7301591693c7b415e9869157c711fe11263c95d74eDavid Li adapter_get_address(serv_adapter->adapter, &src); 7311591693c7b415e9869157c711fe11263c95d74eDavid Li else 7321591693c7b415e9869157c711fe11263c95d74eDavid Li bacpy(&src, BDADDR_ANY); 7331591693c7b415e9869157c711fe11263c95d74eDavid Li 7341591693c7b415e9869157c711fe11263c95d74eDavid Li btd_request_authorization(&src, &auth->dst, 7351591693c7b415e9869157c711fe11263c95d74eDavid Li auth->uuid, auth_cb, serv_adapter); 7361591693c7b415e9869157c711fe11263c95d74eDavid Li 7371591693c7b415e9869157c711fe11263c95d74eDavid Lidone: 7381591693c7b415e9869157c711fe11263c95d74eDavid Li return dbus_message_new_method_return(msg); 7391591693c7b415e9869157c711fe11263c95d74eDavid Li} 7401591693c7b415e9869157c711fe11263c95d74eDavid Li 7411591693c7b415e9869157c711fe11263c95d74eDavid Listatic GDBusMethodTable service_methods[] = { 7421591693c7b415e9869157c711fe11263c95d74eDavid Li { "AddRecord", "s", "u", add_service_record }, 7431591693c7b415e9869157c711fe11263c95d74eDavid Li { "UpdateRecord", "us", "", update_service_record }, 7441591693c7b415e9869157c711fe11263c95d74eDavid Li { "RemoveRecord", "u", "", remove_service_record }, 7451591693c7b415e9869157c711fe11263c95d74eDavid Li { "RequestAuthorization","su", "", request_authorization, 7461591693c7b415e9869157c711fe11263c95d74eDavid Li G_DBUS_METHOD_FLAG_ASYNC}, 7471591693c7b415e9869157c711fe11263c95d74eDavid Li { "CancelAuthorization", "", "", cancel_authorization }, 7481591693c7b415e9869157c711fe11263c95d74eDavid Li { } 7491591693c7b415e9869157c711fe11263c95d74eDavid Li}; 7501591693c7b415e9869157c711fe11263c95d74eDavid Li 7511591693c7b415e9869157c711fe11263c95d74eDavid Listatic void path_unregister(void *data) 7521591693c7b415e9869157c711fe11263c95d74eDavid Li{ 7531591693c7b415e9869157c711fe11263c95d74eDavid Li struct service_adapter *serv_adapter = data; 7541591693c7b415e9869157c711fe11263c95d74eDavid Li GSList *l, *next = NULL; 7551591693c7b415e9869157c711fe11263c95d74eDavid Li 7561591693c7b415e9869157c711fe11263c95d74eDavid Li for (l = serv_adapter->records; l != NULL; l = next) { 7571591693c7b415e9869157c711fe11263c95d74eDavid Li struct record_data *user_record = l->data; 7581591693c7b415e9869157c711fe11263c95d74eDavid Li 7591591693c7b415e9869157c711fe11263c95d74eDavid Li next = l->next; 7601591693c7b415e9869157c711fe11263c95d74eDavid Li 7611591693c7b415e9869157c711fe11263c95d74eDavid Li g_dbus_remove_watch(connection, user_record->listener_id); 7621591693c7b415e9869157c711fe11263c95d74eDavid Li exit_callback(connection, user_record); 7631591693c7b415e9869157c711fe11263c95d74eDavid Li } 7641591693c7b415e9869157c711fe11263c95d74eDavid Li 7651591693c7b415e9869157c711fe11263c95d74eDavid Li g_free(serv_adapter); 7661591693c7b415e9869157c711fe11263c95d74eDavid Li} 7671591693c7b415e9869157c711fe11263c95d74eDavid Li 7681591693c7b415e9869157c711fe11263c95d74eDavid Listatic int register_interface(const char *path, struct btd_adapter *adapter) 7691591693c7b415e9869157c711fe11263c95d74eDavid Li{ 7701591693c7b415e9869157c711fe11263c95d74eDavid Li struct service_adapter *serv_adapter; 7711591693c7b415e9869157c711fe11263c95d74eDavid Li 7721591693c7b415e9869157c711fe11263c95d74eDavid Li DBG("path %s", path); 7731591693c7b415e9869157c711fe11263c95d74eDavid Li 7741591693c7b415e9869157c711fe11263c95d74eDavid Li serv_adapter = g_try_new0(struct service_adapter, 1); 7751591693c7b415e9869157c711fe11263c95d74eDavid Li if (serv_adapter == NULL) 7761591693c7b415e9869157c711fe11263c95d74eDavid Li return -ENOMEM; 7771591693c7b415e9869157c711fe11263c95d74eDavid Li 7781591693c7b415e9869157c711fe11263c95d74eDavid Li serv_adapter->adapter = adapter; 7791591693c7b415e9869157c711fe11263c95d74eDavid Li serv_adapter->pending_list = NULL; 7801591693c7b415e9869157c711fe11263c95d74eDavid Li 7811591693c7b415e9869157c711fe11263c95d74eDavid Li if (g_dbus_register_interface(connection, path, SERVICE_INTERFACE, 7821591693c7b415e9869157c711fe11263c95d74eDavid Li service_methods, NULL, NULL, serv_adapter, 7831591693c7b415e9869157c711fe11263c95d74eDavid Li path_unregister) == FALSE) { 7841591693c7b415e9869157c711fe11263c95d74eDavid Li error("D-Bus failed to register %s interface", 7851591693c7b415e9869157c711fe11263c95d74eDavid Li SERVICE_INTERFACE); 7861591693c7b415e9869157c711fe11263c95d74eDavid Li g_free(serv_adapter); 7871591693c7b415e9869157c711fe11263c95d74eDavid Li return -EIO; 7881591693c7b415e9869157c711fe11263c95d74eDavid Li } 7891591693c7b415e9869157c711fe11263c95d74eDavid Li 7901591693c7b415e9869157c711fe11263c95d74eDavid Li DBG("Registered interface %s on path %s", SERVICE_INTERFACE, path); 7911591693c7b415e9869157c711fe11263c95d74eDavid Li 7921591693c7b415e9869157c711fe11263c95d74eDavid Li if (serv_adapter->adapter == NULL) 7931591693c7b415e9869157c711fe11263c95d74eDavid Li serv_adapter_any = serv_adapter; 7941591693c7b415e9869157c711fe11263c95d74eDavid Li 7951591693c7b415e9869157c711fe11263c95d74eDavid Li return 0; 7961591693c7b415e9869157c711fe11263c95d74eDavid Li} 7971591693c7b415e9869157c711fe11263c95d74eDavid Li 7981591693c7b415e9869157c711fe11263c95d74eDavid Listatic void unregister_interface(const char *path) 7991591693c7b415e9869157c711fe11263c95d74eDavid Li{ 8001591693c7b415e9869157c711fe11263c95d74eDavid Li DBG("path %s", path); 8011591693c7b415e9869157c711fe11263c95d74eDavid Li 8021591693c7b415e9869157c711fe11263c95d74eDavid Li g_dbus_unregister_interface(connection, path, SERVICE_INTERFACE); 8031591693c7b415e9869157c711fe11263c95d74eDavid Li} 8041591693c7b415e9869157c711fe11263c95d74eDavid Li 8051591693c7b415e9869157c711fe11263c95d74eDavid Listatic int service_probe(struct btd_adapter *adapter) 8061591693c7b415e9869157c711fe11263c95d74eDavid Li{ 8071591693c7b415e9869157c711fe11263c95d74eDavid Li register_interface(adapter_get_path(adapter), adapter); 8081591693c7b415e9869157c711fe11263c95d74eDavid Li 8091591693c7b415e9869157c711fe11263c95d74eDavid Li return 0; 8101591693c7b415e9869157c711fe11263c95d74eDavid Li} 8111591693c7b415e9869157c711fe11263c95d74eDavid Li 8121591693c7b415e9869157c711fe11263c95d74eDavid Listatic void service_remove(struct btd_adapter *adapter) 8131591693c7b415e9869157c711fe11263c95d74eDavid Li{ 8141591693c7b415e9869157c711fe11263c95d74eDavid Li unregister_interface(adapter_get_path(adapter)); 8151591693c7b415e9869157c711fe11263c95d74eDavid Li} 8161591693c7b415e9869157c711fe11263c95d74eDavid Li 8171591693c7b415e9869157c711fe11263c95d74eDavid Listatic struct btd_adapter_driver service_driver = { 8181591693c7b415e9869157c711fe11263c95d74eDavid Li .name = "service", 8191591693c7b415e9869157c711fe11263c95d74eDavid Li .probe = service_probe, 8201591693c7b415e9869157c711fe11263c95d74eDavid Li .remove = service_remove, 8211591693c7b415e9869157c711fe11263c95d74eDavid Li}; 8221591693c7b415e9869157c711fe11263c95d74eDavid Li 8231591693c7b415e9869157c711fe11263c95d74eDavid Listatic const char *any_path; 8241591693c7b415e9869157c711fe11263c95d74eDavid Li 8251591693c7b415e9869157c711fe11263c95d74eDavid Listatic int service_init(void) 8261591693c7b415e9869157c711fe11263c95d74eDavid Li{ 8271591693c7b415e9869157c711fe11263c95d74eDavid Li int err; 8281591693c7b415e9869157c711fe11263c95d74eDavid Li 8291591693c7b415e9869157c711fe11263c95d74eDavid Li connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); 8301591693c7b415e9869157c711fe11263c95d74eDavid Li if (connection == NULL) 8311591693c7b415e9869157c711fe11263c95d74eDavid Li return -EIO; 8321591693c7b415e9869157c711fe11263c95d74eDavid Li 8331591693c7b415e9869157c711fe11263c95d74eDavid Li any_path = btd_adapter_any_request_path(); 8341591693c7b415e9869157c711fe11263c95d74eDavid Li if (any_path != NULL) { 8351591693c7b415e9869157c711fe11263c95d74eDavid Li if (register_interface(any_path, NULL) < 0) { 8361591693c7b415e9869157c711fe11263c95d74eDavid Li btd_adapter_any_release_path(); 8371591693c7b415e9869157c711fe11263c95d74eDavid Li any_path = NULL; 838d274f94df69a016386195efcf0640802c7d7d2dcDavid Li } 839d274f94df69a016386195efcf0640802c7d7d2dcDavid Li } 8401591693c7b415e9869157c711fe11263c95d74eDavid Li 8411591693c7b415e9869157c711fe11263c95d74eDavid Li err = btd_register_adapter_driver(&service_driver); 8421591693c7b415e9869157c711fe11263c95d74eDavid Li if (err < 0) { 8431591693c7b415e9869157c711fe11263c95d74eDavid Li dbus_connection_unref(connection); 8441591693c7b415e9869157c711fe11263c95d74eDavid Li return err; 8451591693c7b415e9869157c711fe11263c95d74eDavid Li } 8461591693c7b415e9869157c711fe11263c95d74eDavid Li 8471591693c7b415e9869157c711fe11263c95d74eDavid Li return 0; 8481591693c7b415e9869157c711fe11263c95d74eDavid Li} 8491591693c7b415e9869157c711fe11263c95d74eDavid Li 8501591693c7b415e9869157c711fe11263c95d74eDavid Listatic void service_exit(void) 8511591693c7b415e9869157c711fe11263c95d74eDavid Li{ 8521591693c7b415e9869157c711fe11263c95d74eDavid Li btd_unregister_adapter_driver(&service_driver); 8531591693c7b415e9869157c711fe11263c95d74eDavid Li 8541591693c7b415e9869157c711fe11263c95d74eDavid Li if (any_path != NULL) { 8551591693c7b415e9869157c711fe11263c95d74eDavid Li unregister_interface(any_path); 8561591693c7b415e9869157c711fe11263c95d74eDavid Li 8571591693c7b415e9869157c711fe11263c95d74eDavid Li btd_adapter_any_release_path(); 8581591693c7b415e9869157c711fe11263c95d74eDavid Li any_path = NULL; 8591591693c7b415e9869157c711fe11263c95d74eDavid Li } 8601591693c7b415e9869157c711fe11263c95d74eDavid Li 8611591693c7b415e9869157c711fe11263c95d74eDavid Li dbus_connection_unref(connection); 8621591693c7b415e9869157c711fe11263c95d74eDavid Li} 8631591693c7b415e9869157c711fe11263c95d74eDavid Li 8641591693c7b415e9869157c711fe11263c95d74eDavid LiBLUETOOTH_PLUGIN_DEFINE(service, VERSION, 8651591693c7b415e9869157c711fe11263c95d74eDavid Li BLUETOOTH_PLUGIN_PRIORITY_HIGH, service_init, service_exit) 8661591693c7b415e9869157c711fe11263c95d74eDavid Li