* [Bluez-devel] [PATCH] XML SDP Record Registration
@ 2006-11-21 5:04 Denis KENZIOR
2006-11-21 7:41 ` Marcel Holtmann
0 siblings, 1 reply; 7+ messages in thread
From: Denis KENZIOR @ 2006-11-21 5:04 UTC (permalink / raw)
To: bluez-devel
[-- Attachment #1: Type: text/plain, Size: 424 bytes --]
Marcel,
Attached is a patch that adds an expat based parser for parsing XML records.
I've also added a new API function AddServiceRecordAsXML (does the same thing
as AddServiceRecord, but in XML format) to the Manager hierarchy.
I've modified the service-agent example to take a new argument, --xmlfile,
which will attempt to register a record stored in an XML format.
Let me know what you think!
Regards,
-Denis
[-- Attachment #2: sdpregister.patch --]
[-- Type: text/x-diff, Size: 29366 bytes --]
Index: common/sdp-dummy.c
===================================================================
RCS file: /cvsroot/bluez/utils/common/sdp-dummy.c,v
retrieving revision 1.2
diff -u -5 -r1.2 sdp-dummy.c
--- common/sdp-dummy.c 13 Nov 2006 07:38:20 -0000 1.2
+++ common/sdp-dummy.c 21 Nov 2006 04:55:38 -0000
@@ -24,5 +24,28 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "sdp-xml.h"
+
+sdp_xml_context *sdp_xml_init_context()
+{
+ return NULL;
+}
+
+int sdp_xml_parse_chunk(sdp_xml_context * context, const char *data, int size,
+ int final)
+{
+ return -1;
+}
+
+
+
+sdp_record_t *sdp_xml_get_record(sdp_xml_context * context)
+{
+ return NULL;
+}
+
+void sdp_xml_free_context(sdp_xml_context * context)
+{
+
+}
Index: common/sdp-expat.c
===================================================================
RCS file: /cvsroot/bluez/utils/common/sdp-expat.c,v
retrieving revision 1.2
diff -u -5 -r1.2 sdp-expat.c
--- common/sdp-expat.c 13 Nov 2006 07:38:20 -0000 1.2
+++ common/sdp-expat.c 21 Nov 2006 04:55:38 -0000
@@ -29,5 +29,410 @@
#include <bluetooth/sdp_lib.h>
#include <expat.h>
#include "sdp-xml.h"
+#include "logging.h"
+
+/* Expat specific implementation of the context struct */
+
+typedef struct _sdp_xml_data sdp_xml_data_t;
+struct _sdp_xml_data
+{
+ char *text; /* Pointer to the current buffer */
+ int size; /* Size of the current buffer */
+ sdp_data_t *data; /* The current item being built */
+ sdp_xml_data_t *next; /* Next item on the stack */
+ char type; /* 0 = Text or Hexadecimal */
+ char *name; /* Name, optional in the dtd */
+ /* TODO: What is it used for? */
+};
+
+struct _sdp_xml_context
+{
+ XML_Parser parser; /* Parser object being used */
+ sdp_record_t *sdprec; /* SDP Record being built */
+ sdp_xml_data_t *stack_head; /* Top of the stack of attributes */
+ int attrId; /* Id of the most recently processed attribute */
+};
+
+#define DEFAULT_XML_DATA_SIZE 1024
+
+static sdp_xml_data_t *sdp_xml_data_alloc()
+{
+ sdp_xml_data_t *elem;
+
+ elem = (sdp_xml_data_t *) malloc(sizeof(sdp_xml_data_t));
+
+ /* Null terminate the text */
+ elem->size = DEFAULT_XML_DATA_SIZE;
+ elem->text = (char *) malloc(sizeof(char) * DEFAULT_XML_DATA_SIZE);
+ elem->text[0] = '\0';
+
+ elem->next = 0;
+ elem->data = 0;
+
+ elem->type = 0;
+ elem->name = 0;
+
+ return elem;
+}
+
+static void sdp_xml_data_free(sdp_xml_data_t * elem)
+{
+ if (elem->data)
+ sdp_data_free(elem->data);
+
+ if (elem->name)
+ free(elem->name);
+
+ free(elem->text);
+ free(elem);
+}
+
+static sdp_xml_data_t *sdp_xml_data_expand(sdp_xml_data_t * elem)
+{
+ char *newbuf;
+
+ newbuf = (char *) malloc(elem->size * 2);
+ if (!newbuf)
+ return NULL;
+
+ memcpy(newbuf, elem->text, elem->size);
+ elem->size *= 2;
+ free(elem->text);
+
+ elem->text = newbuf;
+
+ return elem;
+}
+
+static sdp_data_t * sdp_xml_parse_datatype(const char *el, sdp_xml_context *context)
+{
+ sdp_data_t *ret = NULL;
+ const char *data = context->stack_head->text;
+
+ if (!strcmp(el, "bool")) {
+ ret = sdp_xml_parse_int(data, SDP_BOOL);
+ }
+
+ else if (!strcmp(el, "uint8")) {
+ ret = sdp_xml_parse_int(data, SDP_UINT8);
+ }
+
+ else if (!strcmp(el, "uint16")) {
+ ret = sdp_xml_parse_int(data, SDP_UINT16);
+ }
+
+ else if (!strcmp(el, "uint32")) {
+ ret = sdp_xml_parse_int(data, SDP_UINT32);
+ }
+
+ else if (!strcmp(el, "uint64")) {
+ ret = sdp_xml_parse_int(data, SDP_UINT64);
+ }
+
+ else if (!strcmp(el, "uint128")) {
+ ret = sdp_xml_parse_int(data, SDP_UINT128);
+ }
+
+ else if (!strcmp(el, "int8")) {
+ ret = sdp_xml_parse_int(data, SDP_INT8);
+ }
+
+ else if (!strcmp(el, "int16")) {
+ ret = sdp_xml_parse_int(data, SDP_INT16);
+ }
+
+ else if (!strcmp(el, "int32")) {
+ ret = sdp_xml_parse_int(data, SDP_INT32);
+ }
+
+ else if (!strcmp(el, "int64")) {
+ ret = sdp_xml_parse_int(data, SDP_INT64);
+ }
+
+ else if (!strcmp(el, "int128")) {
+ ret = sdp_xml_parse_int(data, SDP_INT128);
+ }
+
+ else if (!strcmp(el, "uuid")) {
+ ret = sdp_xml_parse_uuid(data);
+ }
+
+ else if (!strcmp(el, "url")) {
+ ret = sdp_xml_parse_url(data);
+ }
+
+ else if (!strcmp(el, "text")) {
+ ret = sdp_xml_parse_text(data, context->stack_head->type);
+ }
+
+ else if (!strcmp(el, "nil")) {
+ ret = sdp_xml_parse_nil(data);
+ }
+
+ return ret;
+}
+
+static void convert_xml_to_sdp_start(void *data, const char *el,
+ const char **attr)
+{
+ int i;
+ sdp_xml_context *context = (sdp_xml_context *) data;
+
+ if (!strcmp(el, "record"))
+ return;
+
+ if (!strcmp(el, "attribute")) {
+ /* Get the ID */
+ for (i = 0; attr[i]; i += 1) {
+ if (!strcmp(attr[i], "id")) {
+ context->attrId = strtol(attr[i + 1], 0, 0);
+ break;
+ }
+ }
+
+ return;
+ }
+
+ /* Assume every other tag is an element of some sort */
+ if (context->stack_head) {
+ sdp_xml_data_t *newelem = sdp_xml_data_alloc();
+ newelem->next = context->stack_head;
+ context->stack_head = newelem;
+ }
+ else {
+ context->stack_head = sdp_xml_data_alloc();
+ context->stack_head->next = 0;
+ }
+
+ if (!strcmp(el, "sequence")) {
+ context->stack_head->data = sdp_data_alloc(SDP_SEQ8, NULL);
+ }
+
+ else if (!strcmp(el, "alternate")) {
+ context->stack_head->data = sdp_data_alloc(SDP_ALT8, NULL);
+ }
+
+ else {
+ const char *type = el;
+ /* Parse value, name, encoding */
+ for (i = 0; attr[i]; i += 2) {
+ if (!strcmp(attr[i], "value")) {
+ int curlen = strlen(context->stack_head->text);
+ int attrlen = strlen(attr[i+1]);
+
+ /* Ensure we're big enough */
+ while ((curlen + 1 + attrlen) >
+ context->stack_head->size) {
+ sdp_xml_data_expand(context->stack_head);
+ }
+
+ memcpy(&context->stack_head->text[curlen],
+ attr[i+1], attrlen);
+ context->stack_head->text[curlen + attrlen] = '\0';
+ }
+
+ if (!strcmp(attr[i], "encoding")) {
+ if (!strcmp(attr[i+1], "hex"))
+ context->stack_head->type = 1;
+ }
+
+ if (!strcmp(attr[i], "name")) {
+ context->stack_head->name = strdup(attr[i+1]);
+ }
+ }
+
+ context->stack_head->data = sdp_xml_parse_datatype(type, context);
+
+ /* Could not parse an entry */
+ if (context->stack_head->data == NULL)
+ XML_StopParser(context->parser, 0);
+ }
+}
+
+static int compute_seq_size(sdp_data_t *data)
+{
+ int unit_size = data->unitSize;
+ sdp_data_t *seq = data->val.dataseq;
+
+ for (; seq; seq = seq->next)
+ unit_size += seq->unitSize;
+
+ return unit_size;
+}
+
+static void convert_xml_to_sdp_end(void *data, const char *el)
+{
+ sdp_xml_context *context = (sdp_xml_context *) data;
+ sdp_xml_data_t *elem;
+
+ if (!strcmp(el, "record"))
+ return;
+
+ if (!strcmp(el, "attribute")) {
+ if (context->stack_head && context->stack_head->data) {
+ int ret = sdp_attr_add(context->sdprec,
+ context->attrId,
+ context->stack_head->data);
+ if (ret == -1)
+ debug("Trouble adding attribute\n");
+
+ context->stack_head->data = 0;
+ sdp_xml_data_free(context->stack_head);
+ context->stack_head = 0;
+ }
+ else {
+ debug("No Data for attribute: %d\n",
+ context->attrId);
+ }
+
+ return;
+ }
+ else if (!strcmp(el, "sequence")) {
+ context->stack_head->data->unitSize =
+ compute_seq_size(context->stack_head->data);
+
+ if (context->stack_head->data->unitSize > USHRT_MAX) {
+ context->stack_head->data->unitSize +=
+ sizeof(uint32_t);
+ context->stack_head->data->dtd = SDP_SEQ32;
+ }
+ else if (context->stack_head->data->unitSize > UCHAR_MAX) {
+ context->stack_head->data->unitSize +=
+ sizeof(uint16_t);
+ context->stack_head->data->dtd = SDP_SEQ16;
+ }
+ else {
+ context->stack_head->data->unitSize += sizeof(uint8_t);
+ }
+ }
+
+ else if (!strcmp(el, "alternate")) {
+ context->stack_head->data->unitSize =
+ compute_seq_size(context->stack_head->data);
+
+ if (context->stack_head->data->unitSize > USHRT_MAX) {
+ context->stack_head->data->unitSize +=
+ sizeof(uint32_t);
+ context->stack_head->data->dtd = SDP_ALT32;
+ }
+ else if (context->stack_head->data->unitSize > UCHAR_MAX) {
+ context->stack_head->data->unitSize +=
+ sizeof(uint16_t);
+ context->stack_head->data->dtd = SDP_ALT16;
+ }
+ else {
+ context->stack_head->data->unitSize += sizeof(uint8_t);
+ }
+ }
+
+ /* If we're not inside a seq or alt, then we're inside an attribute
+ which will be taken care of later
+ */
+ if (context->stack_head->next &&
+ context->stack_head->data && context->stack_head->next->data) {
+ switch (context->stack_head->next->data->dtd) {
+ case SDP_SEQ8:
+ case SDP_SEQ16:
+ case SDP_SEQ32:
+ case SDP_ALT8:
+ case SDP_ALT16:
+ case SDP_ALT32:
+ context->stack_head->next->data->val.
+ dataseq =
+ sdp_seq_append(context->
+ stack_head->
+ next->data->
+ val.dataseq,
+ context->stack_head->data);
+ context->stack_head->data = 0;
+ break;
+ }
+
+ elem = context->stack_head;
+ context->stack_head = context->stack_head->next;
+
+ sdp_xml_data_free(elem);
+ }
+}
+
+sdp_xml_context *sdp_xml_init_context()
+{
+ sdp_xml_context *context = 0;
+
+ context = (sdp_xml_context *) malloc(sizeof(sdp_xml_context));
+
+ if (!context)
+ return NULL;
+
+ context->parser = 0;
+ context->sdprec = 0;
+ context->stack_head = 0;
+
+ context->parser = XML_ParserCreate(NULL);
+ XML_SetElementHandler(context->parser, convert_xml_to_sdp_start,
+ convert_xml_to_sdp_end);
+ XML_SetUserData(context->parser, context);
+
+ if (!context->parser)
+ goto fail;
+
+ context->sdprec = sdp_record_alloc();
+
+ if (!context->sdprec)
+ goto fail;
+
+ return context;
+
+fail:
+ if (context->parser)
+ free(context->parser);
+
+ if (context->sdprec)
+ sdp_record_free(context->sdprec);
+
+ if (context)
+ free(context);
+
+ return NULL;
+}
+
+sdp_record_t *sdp_xml_get_record(sdp_xml_context * context)
+{
+ sdp_record_t *rec = context->sdprec;
+
+ context->sdprec = 0;
+
+ return rec;
+}
+
+void sdp_xml_free_context(sdp_xml_context * context)
+{
+ sdp_xml_data_t *elem;
+
+ /* Free the stack */
+ while (context->stack_head) {
+ elem = context->stack_head;
+ context->stack_head = elem->next;
+ sdp_xml_data_free(elem);
+ }
+
+ if (context->sdprec)
+ sdp_record_free(context->sdprec);
+ XML_ParserFree(context->parser);
+ free(context);
+}
+
+int sdp_xml_parse_chunk(sdp_xml_context * context, const char *data, int size,
+ int final)
+{
+ if (!XML_Parse(context->parser, data, size, final)) {
+ debug("Parse error at line %d:\n%s\n",
+ XML_GetCurrentLineNumber(context->parser),
+ XML_ErrorString(XML_GetErrorCode(context->parser)));
+ return -1;
+ }
+
+ return 0;
+}
Index: common/sdp-xml.c
===================================================================
RCS file: /cvsroot/bluez/utils/common/sdp-xml.c,v
retrieving revision 1.2
diff -u -5 -r1.2 sdp-xml.c
--- common/sdp-xml.c 13 Nov 2006 07:38:20 -0000 1.2
+++ common/sdp-xml.c 21 Nov 2006 04:55:38 -0000
@@ -29,17 +29,20 @@
#include <errno.h>
#include <ctype.h>
#include <malloc.h>
#include <string.h>
#include <limits.h>
+#include <stdlib.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
#include "sdp-xml.h"
-#define STRBUFSIZE 256
+#undef SDP_XML_DEBUG
+
+#define STRBUFSIZE 1024
#define MAXINDENT 64
static void convert_raw_data_to_xml(sdp_data_t *value, int indent_level,
void *data, void (*appender) (void *, const char *))
{
@@ -397,5 +400,346 @@
sdp_list_foreach(rec->attrlist,
convert_raw_attr_to_xml_func, &cd);
appender(data, "</record>\n");
}
}
+
+sdp_data_t * sdp_xml_parse_uuid16(const char *data)
+{
+ uint16_t val;
+ char *endptr;
+
+ val = strtol(data, &endptr, 16);
+
+ /* Failed to parse */
+ if (*endptr != '\0')
+ return NULL;
+
+ return sdp_data_alloc(SDP_UUID16, &val);
+}
+
+sdp_data_t * sdp_xml_parse_uuid32(const char *data)
+{
+ uint32_t val;
+ char *endptr;
+
+ val = strtoll(data, &endptr, 16);
+
+ /* Failed to parse */
+ if (*endptr != '\0')
+ return NULL;
+
+ return sdp_data_alloc(SDP_UUID32, &val);
+}
+
+sdp_data_t * sdp_xml_parse_uuid128(const char *data)
+{
+ uint128_t val;
+ int i;
+ int j;
+
+ char buf[3];
+
+ memset(&val, 0, sizeof(val));
+
+ buf[2] = '\0';
+
+ for (j = 0, i = 0; i < strlen(data);) {
+ if (data[i] == '-') {
+ i++;
+ continue;
+ }
+
+ buf[0] = data[i];
+ buf[1] = data[i + 1];
+
+ val.data[j++] = strtoul(buf, 0, 16);
+ i += 2;
+ }
+
+ return sdp_data_alloc(SDP_UUID128, &val);
+}
+
+sdp_data_t * sdp_xml_parse_uuid(const char *data)
+{
+ int len;
+ char *endptr;
+
+ len = strlen(data);
+
+ if (len == 36) {
+ return sdp_xml_parse_uuid128(data);
+ }
+ else {
+ uint32_t val;
+
+ val = strtoll(data, &endptr, 16);
+
+ /* Couldn't parse */
+ if (*endptr != '\0')
+ return NULL;
+
+ if (val > USHRT_MAX) {
+ return sdp_data_alloc(SDP_UUID32, &val);
+ }
+ else {
+ uint16_t val2 = val;
+ return sdp_data_alloc(SDP_UUID16, &val2);
+ }
+ }
+
+ /* Should never get here */
+ return NULL;
+}
+
+sdp_data_t * sdp_xml_parse_int(const char * data, uint8_t dtd)
+{
+ char *endptr;
+ sdp_data_t *ret = NULL;
+
+ switch (dtd) {
+ case SDP_BOOL:
+ {
+ uint8_t val = 0;
+
+ if (!strcmp("true", data)) {
+ val = 1;
+ }
+
+ else if (!strcmp("false", data)) {
+ val = 0;
+ }
+ else {
+ return NULL;
+ }
+
+ ret = sdp_data_alloc(dtd, &val);
+ break;
+ }
+
+ case SDP_INT8:
+ {
+ int8_t val = strtoul(data, &endptr, 0);
+
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
+
+ ret = sdp_data_alloc(dtd, &val);
+ break;
+ }
+
+ case SDP_UINT8:
+ {
+ uint8_t val = strtoul(data, &endptr, 0);
+
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
+
+ ret = sdp_data_alloc(dtd, &val);
+ break;
+ }
+
+ case SDP_INT16:
+ {
+ int16_t val = strtoul(data, &endptr, 0);
+
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
+
+ ret = sdp_data_alloc(dtd, &val);
+ break;
+ }
+
+ case SDP_UINT16:
+ {
+ uint16_t val = strtoul(data, &endptr, 0);
+
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
+
+ ret = sdp_data_alloc(dtd, &val);
+ break;
+ }
+
+ case SDP_INT32:
+ {
+ int32_t val = strtoul(data, &endptr, 0);
+
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
+
+ ret = sdp_data_alloc(dtd, &val);
+ break;
+ }
+
+ case SDP_UINT32:
+ {
+ uint32_t val = strtoul(data, &endptr, 0);
+
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
+
+ ret = sdp_data_alloc(dtd, &val);
+ break;
+ }
+
+ case SDP_INT64:
+ {
+ int64_t val = strtoull(data, &endptr, 0);
+
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
+
+ ret = sdp_data_alloc(dtd, &val);
+ break;
+ }
+
+ case SDP_UINT64:
+ {
+ uint64_t val = strtoull(data, &endptr, 0);
+
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
+
+ ret = sdp_data_alloc(dtd, &val);
+ break;
+ }
+
+ case SDP_INT128:
+ case SDP_UINT128:
+ {
+ uint128_t val;
+ int i = 0;
+ char buf[3];
+
+ buf[2] = '\0';
+
+ for (; i < 32; i += 2) {
+ buf[0] = data[i];
+ buf[1] = data[i + 1];
+
+ val.data[i] = strtoul(buf, 0, 16);
+ }
+
+ ret = sdp_data_alloc(dtd, &val);
+ break;
+ }
+
+ };
+
+ return ret;
+}
+
+sdp_data_t * sdp_xml_parse_url_with_size(const char * data, uint8_t dtd)
+{
+ return sdp_data_alloc(dtd, data);
+}
+
+sdp_data_t * sdp_xml_parse_url(const char * data)
+{
+ uint8_t dtd = SDP_URL_STR8;
+
+ if (strlen(data) > UCHAR_MAX) {
+ dtd = SDP_URL_STR16;
+ }
+
+ return sdp_xml_parse_url_with_size(data, dtd);
+}
+
+static const char * sdp_xml_parse_text_decode(const char *data, char encoding,
+ char *should_free, uint32_t *length)
+{
+ const char *text;
+
+ if (encoding == SDP_XML_NORMAL_ENCODING) {
+ text = data;
+ *length = strlen(text);
+ }
+ else {
+ int len = strlen(data);
+ char buf[3];
+ int i;
+ char *decoded =
+ (char *) malloc(sizeof(char) * ((len >> 1) + 1));
+
+ /* Ensure the string is a power of 2 */
+ len = (len >> 1) << 1;
+
+ buf[2] = '\0';
+
+ for (i = 0; i < len; i += 2) {
+ buf[0] = data[i];
+ buf[1] = data[i + 1];
+
+ decoded[i >> 1] = strtoul(buf, 0, 16);
+ }
+
+ decoded[len >> 1] = '\0';
+ text = decoded;
+ *should_free = 1;
+ *length = len >> 1;
+ }
+
+ return text;
+}
+
+sdp_data_t * sdp_xml_parse_text_with_size(const char * data, char encoding, uint8_t dtd)
+{
+ char should_free = 0;
+ const char *text;
+ uint32_t length;
+ sdp_data_t *ret;
+
+ text = sdp_xml_parse_text_decode(data, encoding, &should_free, &length);
+ ret = sdp_data_alloc_with_length(dtd, text, length);
+
+#ifdef SDP_XML_DEBUG
+ debug("Got text of length %d: -->%s<--\n", length, text);
+ debug("Unit size was: %d\n", ret->unitSize);
+#endif
+
+ if (should_free)
+ free((char *)text);
+
+ return ret;
+}
+
+sdp_data_t * sdp_xml_parse_text(const char *data, char encoding)
+{
+ uint8_t dtd = SDP_TEXT_STR8;
+ char should_free = 0;
+ const char *text;
+ uint32_t length;
+ sdp_data_t *ret;
+
+ text = sdp_xml_parse_text_decode(data, encoding, &should_free, &length);
+
+ if (length > UCHAR_MAX) {
+ dtd = SDP_TEXT_STR16;
+ }
+
+ ret = sdp_data_alloc_with_length(dtd, text, length);
+
+#ifdef SDP_XML_DEBUG
+ debug("Got text of length %d: -->%s<--\n", length, text);
+ debug("Unit size was: %d\n", ret->unitSize);
+#endif
+
+ if (should_free)
+ free((char *)text);
+
+ return ret;
+}
+
+sdp_data_t * sdp_xml_parse_nil(const char * data)
+{
+ return sdp_data_alloc(SDP_DATA_NIL, 0);
+}
+
Index: common/sdp-xml.h
===================================================================
RCS file: /cvsroot/bluez/utils/common/sdp-xml.h,v
retrieving revision 1.2
diff -u -5 -r1.2 sdp-xml.h
--- common/sdp-xml.h 13 Nov 2006 07:38:20 -0000 1.2
+++ common/sdp-xml.h 21 Nov 2006 04:55:38 -0000
@@ -25,9 +25,50 @@
#ifndef __SDP_XML_H
#define __SDP_XML_H
#include <bluetooth/sdp.h>
+#define SDP_XML_NORMAL_ENCODING 0
+#define SDP_XML_HEX_ENCODING 1
+
void convert_sdp_record_to_xml(sdp_record_t *rec,
void *user_data, void (*append_func) (void *, const char *));
+sdp_data_t * sdp_xml_parse_nil(const char * data);
+sdp_data_t * sdp_xml_parse_text(const char *data, char encoding);
+sdp_data_t * sdp_xml_parse_text_with_size(const char * data, char encoding, uint8_t dtd);
+sdp_data_t * sdp_xml_parse_url(const char * data);
+sdp_data_t * sdp_xml_parse_url_with_size(const char * data, uint8_t dtd);
+sdp_data_t * sdp_xml_parse_int(const char * data, uint8_t dtd);
+sdp_data_t * sdp_xml_parse_uuid(const char *data);
+sdp_data_t * sdp_xml_parse_uuid128(const char *data);
+sdp_data_t * sdp_xml_parse_uuid32(const char *data);
+sdp_data_t * sdp_xml_parse_uuid16(const char *data);
+
+typedef struct _sdp_xml_context sdp_xml_context;
+
+sdp_xml_context *sdp_xml_init_context();
+
+/*
+ parses an XML chunk. Returns -1 if a parse error occured, and 0
+ if successful. Pass final as 1 if the chunk is the final chunk,
+ and 0 otherwise.
+*/
+int sdp_xml_parse_chunk(sdp_xml_context * context, const char *data, int size,
+ int final);
+
+/*
+ Should be called after sdp_xml_parse_chunk has been called with the
+ final flag set
+
+ Returns the resulting sdp_record_t. The returned value will need to
+ be freed by the caller by usig sdp_record_free.
+*/
+sdp_record_t *sdp_xml_get_record(sdp_xml_context * context);
+
+/*
+ Frees all data except the sdp_record if the sdp_xml_get_record
+ was called. Otherwise everything is freed.
+*/
+void sdp_xml_free_context(sdp_xml_context * context);
+
#endif /* __SDP_XML_H */
Index: hcid/dbus-api.txt
===================================================================
RCS file: /cvsroot/bluez/utils/hcid/dbus-api.txt,v
retrieving revision 1.84
diff -u -5 -r1.84 dbus-api.txt
--- hcid/dbus-api.txt 14 Nov 2006 19:54:04 -0000 1.84
+++ hcid/dbus-api.txt 21 Nov 2006 04:55:38 -0000
@@ -189,10 +189,21 @@
representation of a service record. If the service
agent is running the service record will be automatically
registered, otherwise the record will be available
when the service agent Start method is called.
+ uint32 AddServiceRecordAsXML(string path, string record)
+
+ Add a new service record to the service agent
+ and returns the assigned handle.
+
+ The path parameter is the object path of the
+ service agent. The record parameter is the XML
+ representation of a service record. If the service
+ agent is running the service record will be automatically
+ registered, otherwise the record will be available
+ when the service agent Start method is called.
void RemoveServiceRecord(string path, uint32 handle)
Remove a service record from the service agent
records list.
Index: hcid/dbus-manager.c
===================================================================
RCS file: /cvsroot/bluez/utils/hcid/dbus-manager.c,v
retrieving revision 1.44
diff -u -5 -r1.44 dbus-manager.c
--- hcid/dbus-manager.c 17 Nov 2006 22:36:47 -0000 1.44
+++ hcid/dbus-manager.c 21 Nov 2006 04:55:39 -0000
@@ -43,10 +43,11 @@
#include "dbus-common.h"
#include "dbus-error.h"
#include "dbus-security.h"
#include "dbus-service.h"
#include "dbus-manager.h"
+#include "sdp-xml.h"
static int default_adapter_id = -1;
static int autostart = 1;
static uint32_t next_handle = 0x10000;
@@ -471,10 +472,126 @@
dbus_message_unref(reply);
return error_failed(conn, msg, err);
}
+static DBusHandlerResult add_service_record_xml(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ struct service_agent *agent;
+ DBusMessage *reply;
+ struct binary_record *rec = 0;
+ sdp_record_t *sdp_rec = 0;
+ const char *path;
+ const char *record;
+ sdp_xml_context *xml_context = 0;
+ int err;
+
+ if (!dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_STRING, &path,
+ DBUS_TYPE_STRING, &record,
+ DBUS_TYPE_INVALID))
+ return error_invalid_arguments(conn, msg);
+
+ if (!dbus_connection_get_object_path_data(conn, path,
+ (void *) &agent)) {
+ /* If failed the path is invalid! */
+ return error_invalid_arguments(conn, msg);
+ }
+
+ if (!agent || strcmp(dbus_message_get_sender(msg), agent->id))
+ return error_not_authorized(conn, msg);
+
+ reply = dbus_message_new_method_return(msg);
+ if (!reply)
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+ xml_context = sdp_xml_init_context();
+ if (!xml_context) {
+ dbus_message_unref(reply);
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+ }
+
+ if (sdp_xml_parse_chunk(xml_context, record, strlen(record), 1)) {
+ debug("Parsing failed...");
+ sdp_xml_free_context(xml_context);
+ dbus_message_unref(reply);
+ return error_invalid_arguments(conn, msg);
+ }
+
+ sdp_rec = sdp_xml_get_record(xml_context);
+
+ sdp_xml_free_context(xml_context);
+
+ /* TODO: Is this correct? We remove the record handle attribute
+ (if it exists) so SDP server assigns a new one */
+ sdp_attr_remove(sdp_rec, 0x0);
+
+ /* TODO: How to handle RFCOMM / L2CAP PSMs? */
+
+ if (!sdp_rec) {
+ dbus_message_unref(reply);
+ return error_invalid_arguments(conn, msg);
+ }
+
+ rec = binary_record_new();
+ if (!rec) {
+ sdp_record_free(sdp_rec);
+ dbus_message_unref(reply);
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+ }
+
+ rec->buf = (sdp_buf_t *) malloc(sizeof(sdp_buf_t));
+
+ if (!rec->buf) {
+ sdp_record_free(sdp_rec);
+ binary_record_free(rec);
+ dbus_message_unref(reply);
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+ }
+
+ /* Generate binary record */
+ if (sdp_gen_record_pdu(sdp_rec, rec->buf) != 0) {
+ sdp_record_free(sdp_rec);
+ binary_record_free(rec);
+ dbus_message_unref(reply);
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+ }
+
+ sdp_record_free(sdp_rec);
+
+ /* Assign a new handle */
+ rec->ext_handle = next_handle++;
+
+ if (agent->running) {
+ uint32_t handle = 0;
+
+ if (register_sdp_record(rec->buf->data, rec->buf->data_size, &handle) < 0) {
+ err = errno;
+ error("Service record registration failed: %s (%d)",
+ strerror(err), err);
+ goto fail;
+ }
+
+ rec->handle = handle;
+ }
+
+ agent->records = slist_append(agent->records, rec);
+
+ dbus_message_append_args(reply,
+ DBUS_TYPE_UINT32, &rec->ext_handle,
+ DBUS_TYPE_INVALID);
+
+ return send_message_and_unref(conn, reply);
+
+fail:
+ binary_record_free(rec);
+ dbus_message_unref(reply);
+
+ return error_failed(conn, msg, err);
+}
+
static DBusHandlerResult remove_service_record(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct service_agent *agent;
struct binary_record *rec;
@@ -530,10 +647,11 @@
{ "ListAdapters", list_adapters },
{ "ListServices", list_services },
{ "RegisterService", register_service },
{ "UnregisterService", unregister_service },
{ "AddServiceRecord", add_service_record },
+ { "AddServiceRecordAsXML", add_service_record_xml },
{ "RemoveServiceRecord", remove_service_record },
{ NULL, NULL }
};
DBusHandlerResult handle_manager_method(DBusConnection *conn,
Index: hcid/service-agent.c
===================================================================
RCS file: /cvsroot/bluez/utils/hcid/service-agent.c,v
retrieving revision 1.11
diff -u -5 -r1.11 service-agent.c
--- hcid/service-agent.c 8 Nov 2006 18:28:52 -0000 1.11
+++ hcid/service-agent.c 21 Nov 2006 04:55:39 -0000
@@ -30,17 +30,21 @@
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <getopt.h>
#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#include <dbus/dbus.h>
#define INTERFACE "org.bluez.Manager"
static char *name = NULL;
static char *description = NULL;
+static char *xml_record = NULL;
static volatile sig_atomic_t __io_canceled = 0;
static volatile sig_atomic_t __io_terminated = 0;
static void sig_term(int sig)
@@ -242,10 +246,49 @@
dbus_connection_flush(conn);
return 0;
}
+static int add_record_xml(DBusConnection *conn, const char *service_path)
+{
+ DBusMessage *msg, *reply;
+ DBusError err;
+
+ msg = dbus_message_new_method_call("org.bluez", "/org/bluez",
+ INTERFACE, "AddServiceRecordAsXML");
+ if (!msg) {
+ fprintf(stderr, "Can't allocate new method call\n");
+ return -1;
+ }
+
+ dbus_message_append_args(msg, DBUS_TYPE_STRING, &service_path,
+ DBUS_TYPE_INVALID);
+ dbus_message_append_args(msg, DBUS_TYPE_STRING, &xml_record,
+ DBUS_TYPE_INVALID);
+
+ dbus_error_init(&err);
+
+ reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err);
+
+ dbus_message_unref(msg);
+
+ if (!reply) {
+ fprintf(stderr, "Can't register service record\n");
+ if (dbus_error_is_set(&err)) {
+ fprintf(stderr, "%s\n", err.message);
+ dbus_error_free(&err);
+ }
+ return -1;
+ }
+
+ dbus_message_unref(reply);
+
+ dbus_connection_flush(conn);
+
+ return 0;
+}
+
static int register_service(DBusConnection *conn, const char *service_path)
{
DBusMessage *msg, *reply;
DBusError err;
@@ -284,11 +327,14 @@
dbus_message_unref(reply);
dbus_connection_flush(conn);
- return add_record(conn, service_path);
+ if (xml_record)
+ return add_record_xml(conn, service_path);
+ else
+ return add_record(conn, service_path);
}
static int unregister_service(DBusConnection *conn, const char *service_path)
{
DBusMessage *msg, *reply;
@@ -335,27 +381,30 @@
printf("Usage:\n"
"\tservice-agent [--name service-name]"
" [--description service-description]"
" [--path service-path]\n"
+ " [--xmlfile xmlfile]\n"
"\n");
}
static struct option main_options[] = {
{ "name", 1, 0, 'n' },
{ "description", 1, 0, 'd' },
{ "path", 1, 0, 'p' },
+ { "xmlfile", 1, 0, 'x' },
{ "help", 0, 0, 'h' },
{ 0, 0, 0, 0 }
};
int main(int argc, char *argv[])
{
struct sigaction sa;
DBusConnection *conn;
char match_string[128], default_path[128], *service_path = NULL;
int opt;
+ char *xmlfile = NULL;
snprintf(default_path, sizeof(default_path),
"/org/bluez/service_agent_%d", getpid());
while ((opt = getopt_long(argc, argv, "+n:d:p:h", main_options, NULL)) != EOF) {
@@ -364,10 +413,13 @@
name = strdup(optarg);
break;
case 'd':
description = strdup(optarg);
break;
+ case 'x':
+ xmlfile = strdup(optarg);
+ break;
case 'p':
if (optarg[0] != '/') {
fprintf(stderr, "Invalid path\n");
exit(1);
}
@@ -386,10 +438,37 @@
optind = 0;
if (!service_path)
service_path = strdup(default_path);
+ if (xmlfile) {
+ struct stat buf;
+ int fd;
+
+ if (stat(xmlfile, &buf)) {
+ perror("Couldn't open xml file\n");
+ exit(1);
+ }
+
+ xml_record = (char *) malloc(buf.st_size);
+ if (!xml_record) {
+ fprintf(stderr, "Couldn't allocate XML Record\n");
+ exit(1);
+ }
+
+ fd = open(xmlfile, 0);
+
+ if (fd == -1) {
+ free(xml_record);
+ perror("Couldn't open XML file\n");
+ exit(1);
+ }
+
+ read(fd, xml_record,buf.st_size);
+ close(fd);
+ }
+
conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
if (!conn) {
fprintf(stderr, "Can't get on system bus");
exit(1);
}
@@ -432,9 +511,15 @@
free(name);
if (description)
free(description);
+ if (xmlfile)
+ free(xmlfile);
+
+ if (xml_record)
+ free(xml_record);
+
dbus_connection_unref(conn);
return 0;
}
[-- Attachment #3: Type: text/plain, Size: 347 bytes --]
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
[-- Attachment #4: Type: text/plain, Size: 164 bytes --]
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Bluez-devel] [PATCH] XML SDP Record Registration
2006-11-21 5:04 [Bluez-devel] [PATCH] XML SDP Record Registration Denis KENZIOR
@ 2006-11-21 7:41 ` Marcel Holtmann
2006-11-21 11:47 ` Marcel Holtmann
2006-11-21 23:59 ` Denis KENZIOR
0 siblings, 2 replies; 7+ messages in thread
From: Marcel Holtmann @ 2006-11-21 7:41 UTC (permalink / raw)
To: BlueZ development
Hi Denis,
> Attached is a patch that adds an expat based parser for parsing XML records.
> I've also added a new API function AddServiceRecordAsXML (does the same thing
> as AddServiceRecord, but in XML format) to the Manager hierarchy.
looks good to me, but please follow the coding style of BlueZ. In your
you have way to many whitespace between function names and pointers etc.
> I've modified the service-agent example to take a new argument, --xmlfile,
> which will attempt to register a record stored in an XML format.
Nice idea. I like that. The dbus_message_append_args() can actually add
more then one argument at a time, this is why it is called "args". And
please use mmap() for reading the XML file.
Regards
Marcel
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Bluez-devel] [PATCH] XML SDP Record Registration
2006-11-21 7:41 ` Marcel Holtmann
@ 2006-11-21 11:47 ` Marcel Holtmann
2006-11-21 23:59 ` Denis KENZIOR
1 sibling, 0 replies; 7+ messages in thread
From: Marcel Holtmann @ 2006-11-21 11:47 UTC (permalink / raw)
To: BlueZ development
Hi Denis,
> > I've modified the service-agent example to take a new argument, --xmlfile,
> > which will attempt to register a record stored in an XML format.
>
> Nice idea. I like that. The dbus_message_append_args() can actually add
> more then one argument at a time, this is why it is called "args". And
> please use mmap() for reading the XML file.
the code is untested, but I committed a version to the CVS that actually
implements your idea.
Regards
Marcel
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Bluez-devel] [PATCH] XML SDP Record Registration
2006-11-21 7:41 ` Marcel Holtmann
2006-11-21 11:47 ` Marcel Holtmann
@ 2006-11-21 23:59 ` Denis KENZIOR
2006-11-22 6:24 ` Marcel Holtmann
1 sibling, 1 reply; 7+ messages in thread
From: Denis KENZIOR @ 2006-11-21 23:59 UTC (permalink / raw)
To: BlueZ development
[-- Attachment #1: Type: text/plain, Size: 1686 bytes --]
Marcel,
Here's a fixed up version of the patch.
Your changes to service-agent seem to be working OK.
I've made a script that dumps all profiles that sdptool supports and registers
them back using XML and compares the results. It seems to work for all of
them, but further testing would be appreciated.
-Denis
On Tuesday 21 November 2006 17:41, Marcel Holtmann wrote:
> Hi Denis,
>
> > Attached is a patch that adds an expat based parser for parsing XML
> > records. I've also added a new API function AddServiceRecordAsXML (does
> > the same thing as AddServiceRecord, but in XML format) to the Manager
> > hierarchy.
>
> looks good to me, but please follow the coding style of BlueZ. In your
> you have way to many whitespace between function names and pointers etc.
>
> > I've modified the service-agent example to take a new argument,
> > --xmlfile, which will attempt to register a record stored in an XML
> > format.
>
> Nice idea. I like that. The dbus_message_append_args() can actually add
> more then one argument at a time, this is why it is called "args". And
> please use mmap() for reading the XML file.
>
> Regards
>
> Marcel
>
>
>
> -------------------------------------------------------------------------
> Take Surveys. Earn Cash. Influence the Future of IT
> Join SourceForge.net's Techsay panel and you'll get the chance to share
> your opinions on IT & business topics through brief surveys - and earn cash
> http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
> _______________________________________________
> Bluez-devel mailing list
> Bluez-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/bluez-devel
[-- Attachment #2: sdpregister.patch --]
[-- Type: text/x-diff, Size: 26487 bytes --]
Index: common/sdp-dummy.c
===================================================================
RCS file: /cvsroot/bluez/utils/common/sdp-dummy.c,v
retrieving revision 1.2
diff -u -5 -r1.2 sdp-dummy.c
--- common/sdp-dummy.c 13 Nov 2006 07:38:20 -0000 1.2
+++ common/sdp-dummy.c 21 Nov 2006 23:51:26 -0000
@@ -24,5 +24,28 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "sdp-xml.h"
+
+sdp_xml_context *sdp_xml_init_context()
+{
+ return NULL;
+}
+
+int sdp_xml_parse_chunk(sdp_xml_context *context, const char *data, int size,
+ int final)
+{
+ return -1;
+}
+
+
+
+sdp_record_t *sdp_xml_get_record(sdp_xml_context *context)
+{
+ return NULL;
+}
+
+void sdp_xml_free_context(sdp_xml_context *context)
+{
+
+}
Index: common/sdp-expat.c
===================================================================
RCS file: /cvsroot/bluez/utils/common/sdp-expat.c,v
retrieving revision 1.2
diff -u -5 -r1.2 sdp-expat.c
--- common/sdp-expat.c 13 Nov 2006 07:38:20 -0000 1.2
+++ common/sdp-expat.c 21 Nov 2006 23:51:26 -0000
@@ -29,5 +29,410 @@
#include <bluetooth/sdp_lib.h>
#include <expat.h>
#include "sdp-xml.h"
+#include "logging.h"
+
+/* Expat specific implementation of the context struct */
+
+typedef struct _sdp_xml_data sdp_xml_data_t;
+struct _sdp_xml_data {
+ char *text; /* Pointer to the current buffer */
+ int size; /* Size of the current buffer */
+ sdp_data_t *data; /* The current item being built */
+ sdp_xml_data_t *next; /* Next item on the stack */
+ char type; /* 0 = Text or Hexadecimal */
+ char *name; /* Name, optional in the dtd */
+ /* TODO: What is it used for? */
+};
+
+struct _sdp_xml_context {
+ XML_Parser parser; /* Parser object being used */
+ sdp_record_t *sdprec; /* SDP Record being built */
+ sdp_xml_data_t *stack_head; /* Top of the stack of attributes */
+ int attrId; /* Id of the most recently processed attribute */
+};
+
+#define DEFAULT_XML_DATA_SIZE 1024
+
+static sdp_xml_data_t *sdp_xml_data_alloc()
+{
+ sdp_xml_data_t *elem;
+
+ elem = (sdp_xml_data_t *) malloc(sizeof(sdp_xml_data_t));
+
+ /* Null terminate the text */
+ elem->size = DEFAULT_XML_DATA_SIZE;
+ elem->text = (char *) malloc(sizeof(char) * DEFAULT_XML_DATA_SIZE);
+ elem->text[0] = '\0';
+
+ elem->next = 0;
+ elem->data = 0;
+
+ elem->type = 0;
+ elem->name = 0;
+
+ return elem;
+}
+
+static void sdp_xml_data_free(sdp_xml_data_t *elem)
+{
+ if (elem->data)
+ sdp_data_free(elem->data);
+
+ if (elem->name)
+ free(elem->name);
+
+ free(elem->text);
+ free(elem);
+}
+
+static sdp_xml_data_t *sdp_xml_data_expand(sdp_xml_data_t *elem)
+{
+ char *newbuf;
+
+ newbuf = (char *) malloc(elem->size * 2);
+ if (!newbuf)
+ return NULL;
+
+ memcpy(newbuf, elem->text, elem->size);
+ elem->size *= 2;
+ free(elem->text);
+
+ elem->text = newbuf;
+
+ return elem;
+}
+
+static sdp_data_t *sdp_xml_parse_datatype(const char *el,
+ sdp_xml_context *context)
+{
+ sdp_data_t *ret = NULL;
+ const char *data = context->stack_head->text;
+
+ if (!strcmp(el, "bool")) {
+ ret = sdp_xml_parse_int(data, SDP_BOOL);
+ }
+
+ else if (!strcmp(el, "uint8")) {
+ ret = sdp_xml_parse_int(data, SDP_UINT8);
+ }
+
+ else if (!strcmp(el, "uint16")) {
+ ret = sdp_xml_parse_int(data, SDP_UINT16);
+ }
+
+ else if (!strcmp(el, "uint32")) {
+ ret = sdp_xml_parse_int(data, SDP_UINT32);
+ }
+
+ else if (!strcmp(el, "uint64")) {
+ ret = sdp_xml_parse_int(data, SDP_UINT64);
+ }
+
+ else if (!strcmp(el, "uint128")) {
+ ret = sdp_xml_parse_int(data, SDP_UINT128);
+ }
+
+ else if (!strcmp(el, "int8")) {
+ ret = sdp_xml_parse_int(data, SDP_INT8);
+ }
+
+ else if (!strcmp(el, "int16")) {
+ ret = sdp_xml_parse_int(data, SDP_INT16);
+ }
+
+ else if (!strcmp(el, "int32")) {
+ ret = sdp_xml_parse_int(data, SDP_INT32);
+ }
+
+ else if (!strcmp(el, "int64")) {
+ ret = sdp_xml_parse_int(data, SDP_INT64);
+ }
+
+ else if (!strcmp(el, "int128")) {
+ ret = sdp_xml_parse_int(data, SDP_INT128);
+ }
+
+ else if (!strcmp(el, "uuid")) {
+ ret = sdp_xml_parse_uuid(data);
+ }
+
+ else if (!strcmp(el, "url")) {
+ ret = sdp_xml_parse_url(data);
+ }
+
+ else if (!strcmp(el, "text")) {
+ ret = sdp_xml_parse_text(data, context->stack_head->type);
+ }
+
+ else if (!strcmp(el, "nil")) {
+ ret = sdp_xml_parse_nil(data);
+ }
+
+ return ret;
+}
+
+static void convert_xml_to_sdp_start(void *data, const char *el,
+ const char **attr)
+{
+ int i;
+ sdp_xml_context *context = (sdp_xml_context *) data;
+
+ if (!strcmp(el, "record"))
+ return;
+
+ if (!strcmp(el, "attribute")) {
+ /* Get the ID */
+ for (i = 0; attr[i]; i += 1) {
+ if (!strcmp(attr[i], "id")) {
+ context->attrId =
+ strtol(attr[i + 1], 0, 0);
+ break;
+ }
+ }
+
+ return;
+ }
+
+ /* Assume every other tag is an element of some sort */
+ if (context->stack_head) {
+ sdp_xml_data_t *newelem = sdp_xml_data_alloc();
+ newelem->next = context->stack_head;
+ context->stack_head = newelem;
+ } else {
+ context->stack_head = sdp_xml_data_alloc();
+ context->stack_head->next = 0;
+ }
+
+ if (!strcmp(el, "sequence")) {
+ context->stack_head->data = sdp_data_alloc(SDP_SEQ8, NULL);
+ }
+
+ else if (!strcmp(el, "alternate")) {
+ context->stack_head->data = sdp_data_alloc(SDP_ALT8, NULL);
+ }
+
+ else {
+ const char *type = el;
+ /* Parse value, name, encoding */
+ for (i = 0; attr[i]; i += 2) {
+ if (!strcmp(attr[i], "value")) {
+ int curlen =
+ strlen(context->stack_head->text);
+ int attrlen = strlen(attr[i + 1]);
+
+ /* Ensure we're big enough */
+ while ((curlen + 1 + attrlen) >
+ context->stack_head->size) {
+ sdp_xml_data_expand(context->
+ stack_head);
+ }
+
+ memcpy(&context->stack_head->text[curlen],
+ attr[i + 1], attrlen);
+ context->stack_head->text[curlen +
+ attrlen] = '\0';
+ }
+
+ if (!strcmp(attr[i], "encoding")) {
+ if (!strcmp(attr[i + 1], "hex"))
+ context->stack_head->type = 1;
+ }
+
+ if (!strcmp(attr[i], "name")) {
+ context->stack_head->name =
+ strdup(attr[i + 1]);
+ }
+ }
+
+ context->stack_head->data =
+ sdp_xml_parse_datatype(type, context);
+
+ /* Could not parse an entry */
+ if (context->stack_head->data == NULL)
+ XML_StopParser(context->parser, 0);
+ }
+}
+
+static int compute_seq_size(sdp_data_t *data)
+{
+ int unit_size = data->unitSize;
+ sdp_data_t *seq = data->val.dataseq;
+
+ for (; seq; seq = seq->next)
+ unit_size += seq->unitSize;
+
+ return unit_size;
+}
+
+static void convert_xml_to_sdp_end(void *data, const char *el)
+{
+ sdp_xml_context *context = (sdp_xml_context *) data;
+ sdp_xml_data_t *elem;
+
+ if (!strcmp(el, "record"))
+ return;
+
+ if (!strcmp(el, "attribute")) {
+ if (context->stack_head && context->stack_head->data) {
+ int ret = sdp_attr_add(context->sdprec,
+ context->attrId,
+ context->stack_head->data);
+ if (ret == -1)
+ debug("Trouble adding attribute\n");
+
+ context->stack_head->data = 0;
+ sdp_xml_data_free(context->stack_head);
+ context->stack_head = 0;
+ } else {
+ debug("No Data for attribute: %d\n",
+ context->attrId);
+ }
+
+ return;
+ } else if (!strcmp(el, "sequence")) {
+ context->stack_head->data->unitSize =
+ compute_seq_size(context->stack_head->data);
+
+ if (context->stack_head->data->unitSize > USHRT_MAX) {
+ context->stack_head->data->unitSize +=
+ sizeof(uint32_t);
+ context->stack_head->data->dtd = SDP_SEQ32;
+ } else if (context->stack_head->data->unitSize > UCHAR_MAX) {
+ context->stack_head->data->unitSize +=
+ sizeof(uint16_t);
+ context->stack_head->data->dtd = SDP_SEQ16;
+ } else {
+ context->stack_head->data->unitSize +=
+ sizeof(uint8_t);
+ }
+ }
+
+ else if (!strcmp(el, "alternate")) {
+ context->stack_head->data->unitSize =
+ compute_seq_size(context->stack_head->data);
+
+ if (context->stack_head->data->unitSize > USHRT_MAX) {
+ context->stack_head->data->unitSize +=
+ sizeof(uint32_t);
+ context->stack_head->data->dtd = SDP_ALT32;
+ } else if (context->stack_head->data->unitSize > UCHAR_MAX) {
+ context->stack_head->data->unitSize +=
+ sizeof(uint16_t);
+ context->stack_head->data->dtd = SDP_ALT16;
+ } else {
+ context->stack_head->data->unitSize +=
+ sizeof(uint8_t);
+ }
+ }
+
+ /* If we're not inside a seq or alt, then we're inside an attribute
+ which will be taken care of later
+ */
+ if (context->stack_head->next &&
+ context->stack_head->data && context->stack_head->next->data) {
+ switch (context->stack_head->next->data->dtd) {
+ case SDP_SEQ8:
+ case SDP_SEQ16:
+ case SDP_SEQ32:
+ case SDP_ALT8:
+ case SDP_ALT16:
+ case SDP_ALT32:
+ context->stack_head->next->data->val.
+ dataseq =
+ sdp_seq_append(context->
+ stack_head->
+ next->data->
+ val.dataseq,
+ context->stack_head->data);
+ context->stack_head->data = 0;
+ break;
+ }
+
+ elem = context->stack_head;
+ context->stack_head = context->stack_head->next;
+
+ sdp_xml_data_free(elem);
+ }
+}
+
+sdp_xml_context *sdp_xml_init_context()
+{
+ sdp_xml_context *context = 0;
+
+ context = (sdp_xml_context *) malloc(sizeof(sdp_xml_context));
+
+ if (!context)
+ return NULL;
+
+ context->parser = 0;
+ context->sdprec = 0;
+ context->stack_head = 0;
+
+ context->parser = XML_ParserCreate(NULL);
+ XML_SetElementHandler(context->parser, convert_xml_to_sdp_start,
+ convert_xml_to_sdp_end);
+ XML_SetUserData(context->parser, context);
+
+ if (!context->parser)
+ goto fail;
+
+ context->sdprec = sdp_record_alloc();
+
+ if (!context->sdprec)
+ goto fail;
+
+ return context;
+
+ fail:
+ if (context->parser)
+ free(context->parser);
+
+ if (context->sdprec)
+ sdp_record_free(context->sdprec);
+
+ if (context)
+ free(context);
+
+ return NULL;
+}
+
+sdp_record_t *sdp_xml_get_record(sdp_xml_context *context)
+{
+ sdp_record_t *rec = context->sdprec;
+
+ context->sdprec = 0;
+
+ return rec;
+}
+
+void sdp_xml_free_context(sdp_xml_context *context)
+{
+ sdp_xml_data_t *elem;
+
+ /* Free the stack */
+ while (context->stack_head) {
+ elem = context->stack_head;
+ context->stack_head = elem->next;
+ sdp_xml_data_free(elem);
+ }
+
+ if (context->sdprec)
+ sdp_record_free(context->sdprec);
+ XML_ParserFree(context->parser);
+ free(context);
+}
+
+int sdp_xml_parse_chunk(sdp_xml_context *context, const char *data,
+ int size, int final)
+{
+ if (!XML_Parse(context->parser, data, size, final)) {
+ debug("Parse error at line %d:\n%s\n",
+ XML_GetCurrentLineNumber(context->parser),
+ XML_ErrorString(XML_GetErrorCode(context->parser)));
+ return -1;
+ }
+
+ return 0;
+}
Index: common/sdp-xml.c
===================================================================
RCS file: /cvsroot/bluez/utils/common/sdp-xml.c,v
retrieving revision 1.2
diff -u -5 -r1.2 sdp-xml.c
--- common/sdp-xml.c 13 Nov 2006 07:38:20 -0000 1.2
+++ common/sdp-xml.c 21 Nov 2006 23:51:26 -0000
@@ -29,21 +29,24 @@
#include <errno.h>
#include <ctype.h>
#include <malloc.h>
#include <string.h>
#include <limits.h>
+#include <stdlib.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
#include "sdp-xml.h"
-#define STRBUFSIZE 256
+#undef SDP_XML_DEBUG
+
+#define STRBUFSIZE 1024
#define MAXINDENT 64
static void convert_raw_data_to_xml(sdp_data_t *value, int indent_level,
- void *data, void (*appender) (void *, const char *))
+ void *data, void (*appender)(void *, const char *))
{
int i, hex;
char buf[STRBUFSIZE];
char indent[MAXINDENT];
char next_indent[MAXINDENT];
@@ -254,11 +257,11 @@
/* Unit Size seems to include the size for dtd
It is thus off by 1
This is safe for Normal strings, but not
hex encoded data */
for (i = 0; i < (value->unitSize-1); i++)
- sprintf(&strBuf[i * sizeof (char) * 2],
+ sprintf(&strBuf[i*sizeof(char)*2],
"%02x",
(unsigned char) value->val.str[i]);
strBuf[value->unitSize * 2] = '\0';
}
@@ -349,14 +352,13 @@
convert_raw_data_to_xml(value->next, indent_level, data,
appender);
}
-struct conversion_data
-{
+struct conversion_data {
void *data;
- void (*appender) (void *data, const char *);
+ void (*appender)(void *data, const char *);
};
static void convert_raw_attr_to_xml_func(void *val, void *data)
{
struct conversion_data *cd = (struct conversion_data *) data;
@@ -382,11 +384,11 @@
to control where to output the record (e.g. file or a data buffer). The
appender will be called repeatedly with data and the character buffer
(containing parts of the generated XML) to append.
*/
void convert_sdp_record_to_xml(sdp_record_t *rec,
- void *data, void (*appender) (void *, const char *))
+ void *data, void (*appender)(void *, const char *))
{
struct conversion_data cd;
cd.data = data;
cd.appender = appender;
@@ -397,5 +399,346 @@
sdp_list_foreach(rec->attrlist,
convert_raw_attr_to_xml_func, &cd);
appender(data, "</record>\n");
}
}
+
+sdp_data_t *sdp_xml_parse_uuid16(const char *data)
+{
+ uint16_t val;
+ char *endptr;
+
+ val = strtol(data, &endptr, 16);
+
+ /* Failed to parse */
+ if (*endptr != '\0')
+ return NULL;
+
+ return sdp_data_alloc(SDP_UUID16, &val);
+}
+
+sdp_data_t *sdp_xml_parse_uuid32(const char *data)
+{
+ uint32_t val;
+ char *endptr;
+
+ val = strtoll(data, &endptr, 16);
+
+ /* Failed to parse */
+ if (*endptr != '\0')
+ return NULL;
+
+ return sdp_data_alloc(SDP_UUID32, &val);
+}
+
+sdp_data_t *sdp_xml_parse_uuid128(const char *data)
+{
+ uint128_t val;
+ int i;
+ int j;
+
+ char buf[3];
+
+ memset(&val, 0, sizeof(val));
+
+ buf[2] = '\0';
+
+ for (j = 0, i = 0; i < strlen(data);) {
+ if (data[i] == '-') {
+ i++;
+ continue;
+ }
+
+ buf[0] = data[i];
+ buf[1] = data[i + 1];
+
+ val.data[j++] = strtoul(buf, 0, 16);
+ i += 2;
+ }
+
+ return sdp_data_alloc(SDP_UUID128, &val);
+}
+
+sdp_data_t *sdp_xml_parse_uuid(const char *data)
+{
+ int len;
+ char *endptr;
+
+ len = strlen(data);
+
+ if (len == 36) {
+ return sdp_xml_parse_uuid128(data);
+ }
+ else {
+ uint32_t val;
+
+ val = strtoll(data, &endptr, 16);
+
+ /* Couldn't parse */
+ if (*endptr != '\0')
+ return NULL;
+
+ if (val > USHRT_MAX) {
+ return sdp_data_alloc(SDP_UUID32, &val);
+ }
+ else {
+ uint16_t val2 = val;
+ return sdp_data_alloc(SDP_UUID16, &val2);
+ }
+ }
+
+ /* Should never get here */
+ return NULL;
+}
+
+sdp_data_t *sdp_xml_parse_int(const char * data, uint8_t dtd)
+{
+ char *endptr;
+ sdp_data_t *ret = NULL;
+
+ switch (dtd) {
+ case SDP_BOOL:
+ {
+ uint8_t val = 0;
+
+ if (!strcmp("true", data)) {
+ val = 1;
+ }
+
+ else if (!strcmp("false", data)) {
+ val = 0;
+ }
+ else {
+ return NULL;
+ }
+
+ ret = sdp_data_alloc(dtd, &val);
+ break;
+ }
+
+ case SDP_INT8:
+ {
+ int8_t val = strtoul(data, &endptr, 0);
+
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
+
+ ret = sdp_data_alloc(dtd, &val);
+ break;
+ }
+
+ case SDP_UINT8:
+ {
+ uint8_t val = strtoul(data, &endptr, 0);
+
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
+
+ ret = sdp_data_alloc(dtd, &val);
+ break;
+ }
+
+ case SDP_INT16:
+ {
+ int16_t val = strtoul(data, &endptr, 0);
+
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
+
+ ret = sdp_data_alloc(dtd, &val);
+ break;
+ }
+
+ case SDP_UINT16:
+ {
+ uint16_t val = strtoul(data, &endptr, 0);
+
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
+
+ ret = sdp_data_alloc(dtd, &val);
+ break;
+ }
+
+ case SDP_INT32:
+ {
+ int32_t val = strtoul(data, &endptr, 0);
+
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
+
+ ret = sdp_data_alloc(dtd, &val);
+ break;
+ }
+
+ case SDP_UINT32:
+ {
+ uint32_t val = strtoul(data, &endptr, 0);
+
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
+
+ ret = sdp_data_alloc(dtd, &val);
+ break;
+ }
+
+ case SDP_INT64:
+ {
+ int64_t val = strtoull(data, &endptr, 0);
+
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
+
+ ret = sdp_data_alloc(dtd, &val);
+ break;
+ }
+
+ case SDP_UINT64:
+ {
+ uint64_t val = strtoull(data, &endptr, 0);
+
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
+
+ ret = sdp_data_alloc(dtd, &val);
+ break;
+ }
+
+ case SDP_INT128:
+ case SDP_UINT128:
+ {
+ uint128_t val;
+ int i = 0;
+ char buf[3];
+
+ buf[2] = '\0';
+
+ for (; i < 32; i += 2) {
+ buf[0] = data[i];
+ buf[1] = data[i + 1];
+
+ val.data[i] = strtoul(buf, 0, 16);
+ }
+
+ ret = sdp_data_alloc(dtd, &val);
+ break;
+ }
+
+ };
+
+ return ret;
+}
+
+sdp_data_t *sdp_xml_parse_url_with_size(const char *data, uint8_t dtd)
+{
+ return sdp_data_alloc(dtd, data);
+}
+
+sdp_data_t *sdp_xml_parse_url(const char *data)
+{
+ uint8_t dtd = SDP_URL_STR8;
+
+ if (strlen(data) > UCHAR_MAX) {
+ dtd = SDP_URL_STR16;
+ }
+
+ return sdp_xml_parse_url_with_size(data, dtd);
+}
+
+static const char *sdp_xml_parse_text_decode(const char *data, char encoding,
+ char *should_free, uint32_t *length)
+{
+ const char *text;
+
+ if (encoding == SDP_XML_NORMAL_ENCODING) {
+ text = data;
+ *length = strlen(text);
+ }
+ else {
+ int len = strlen(data);
+ char buf[3];
+ int i;
+ char *decoded =
+ (char *) malloc(sizeof(char) * ((len >> 1) + 1));
+
+ /* Ensure the string is a power of 2 */
+ len = (len >> 1) << 1;
+
+ buf[2] = '\0';
+
+ for (i = 0; i < len; i += 2) {
+ buf[0] = data[i];
+ buf[1] = data[i + 1];
+
+ decoded[i >> 1] = strtoul(buf, 0, 16);
+ }
+
+ decoded[len >> 1] = '\0';
+ text = decoded;
+ *should_free = 1;
+ *length = len >> 1;
+ }
+
+ return text;
+}
+
+sdp_data_t *sdp_xml_parse_text_with_size(const char *data, char encoding, uint8_t dtd)
+{
+ char should_free = 0;
+ const char *text;
+ uint32_t length;
+ sdp_data_t *ret;
+
+ text = sdp_xml_parse_text_decode(data, encoding, &should_free, &length);
+ ret = sdp_data_alloc_with_length(dtd, text, length);
+
+#ifdef SDP_XML_DEBUG
+ debug("Got text of length %d: -->%s<--\n", length, text);
+ debug("Unit size was: %d\n", ret->unitSize);
+#endif
+
+ if (should_free)
+ free((char *)text);
+
+ return ret;
+}
+
+sdp_data_t *sdp_xml_parse_text(const char *data, char encoding)
+{
+ uint8_t dtd = SDP_TEXT_STR8;
+ char should_free = 0;
+ const char *text;
+ uint32_t length;
+ sdp_data_t *ret;
+
+ text = sdp_xml_parse_text_decode(data, encoding, &should_free, &length);
+
+ if (length > UCHAR_MAX) {
+ dtd = SDP_TEXT_STR16;
+ }
+
+ ret = sdp_data_alloc_with_length(dtd, text, length);
+
+#ifdef SDP_XML_DEBUG
+ debug("Got text of length %d: -->%s<--\n", length, text);
+ debug("Unit size was: %d\n", ret->unitSize);
+#endif
+
+ if (should_free)
+ free((char *)text);
+
+ return ret;
+}
+
+sdp_data_t *sdp_xml_parse_nil(const char * data)
+{
+ return sdp_data_alloc(SDP_DATA_NIL, 0);
+}
+
Index: common/sdp-xml.h
===================================================================
RCS file: /cvsroot/bluez/utils/common/sdp-xml.h,v
retrieving revision 1.2
diff -u -5 -r1.2 sdp-xml.h
--- common/sdp-xml.h 13 Nov 2006 07:38:20 -0000 1.2
+++ common/sdp-xml.h 21 Nov 2006 23:51:26 -0000
@@ -25,9 +25,50 @@
#ifndef __SDP_XML_H
#define __SDP_XML_H
#include <bluetooth/sdp.h>
+#define SDP_XML_NORMAL_ENCODING 0
+#define SDP_XML_HEX_ENCODING 1
+
void convert_sdp_record_to_xml(sdp_record_t *rec,
void *user_data, void (*append_func) (void *, const char *));
+sdp_data_t * sdp_xml_parse_nil(const char * data);
+sdp_data_t * sdp_xml_parse_text(const char *data, char encoding);
+sdp_data_t * sdp_xml_parse_text_with_size(const char * data, char encoding, uint8_t dtd);
+sdp_data_t * sdp_xml_parse_url(const char * data);
+sdp_data_t * sdp_xml_parse_url_with_size(const char * data, uint8_t dtd);
+sdp_data_t * sdp_xml_parse_int(const char * data, uint8_t dtd);
+sdp_data_t * sdp_xml_parse_uuid(const char *data);
+sdp_data_t * sdp_xml_parse_uuid128(const char *data);
+sdp_data_t * sdp_xml_parse_uuid32(const char *data);
+sdp_data_t * sdp_xml_parse_uuid16(const char *data);
+
+typedef struct _sdp_xml_context sdp_xml_context;
+
+sdp_xml_context *sdp_xml_init_context();
+
+/*
+ parses an XML chunk. Returns -1 if a parse error occured, and 0
+ if successful. Pass final as 1 if the chunk is the final chunk,
+ and 0 otherwise.
+*/
+int sdp_xml_parse_chunk(sdp_xml_context * context, const char *data, int size,
+ int final);
+
+/*
+ Should be called after sdp_xml_parse_chunk has been called with the
+ final flag set
+
+ Returns the resulting sdp_record_t. The returned value will need to
+ be freed by the caller by usig sdp_record_free.
+*/
+sdp_record_t *sdp_xml_get_record(sdp_xml_context * context);
+
+/*
+ Frees all data except the sdp_record if the sdp_xml_get_record
+ was called. Otherwise everything is freed.
+*/
+void sdp_xml_free_context(sdp_xml_context * context);
+
#endif /* __SDP_XML_H */
Index: hcid/dbus-api.txt
===================================================================
RCS file: /cvsroot/bluez/utils/hcid/dbus-api.txt,v
retrieving revision 1.84
diff -u -5 -r1.84 dbus-api.txt
--- hcid/dbus-api.txt 14 Nov 2006 19:54:04 -0000 1.84
+++ hcid/dbus-api.txt 21 Nov 2006 23:51:26 -0000
@@ -189,10 +189,21 @@
representation of a service record. If the service
agent is running the service record will be automatically
registered, otherwise the record will be available
when the service agent Start method is called.
+ uint32 AddServiceRecordAsXML(string path, string record)
+
+ Add a new service record to the service agent
+ and returns the assigned handle.
+
+ The path parameter is the object path of the
+ service agent. The record parameter is the XML
+ representation of a service record. If the service
+ agent is running the service record will be automatically
+ registered, otherwise the record will be available
+ when the service agent Start method is called.
void RemoveServiceRecord(string path, uint32 handle)
Remove a service record from the service agent
records list.
Index: hcid/dbus-manager.c
===================================================================
RCS file: /cvsroot/bluez/utils/hcid/dbus-manager.c,v
retrieving revision 1.44
diff -u -5 -r1.44 dbus-manager.c
--- hcid/dbus-manager.c 17 Nov 2006 22:36:47 -0000 1.44
+++ hcid/dbus-manager.c 21 Nov 2006 23:51:27 -0000
@@ -43,10 +43,11 @@
#include "dbus-common.h"
#include "dbus-error.h"
#include "dbus-security.h"
#include "dbus-service.h"
#include "dbus-manager.h"
+#include "sdp-xml.h"
static int default_adapter_id = -1;
static int autostart = 1;
static uint32_t next_handle = 0x10000;
@@ -471,10 +472,126 @@
dbus_message_unref(reply);
return error_failed(conn, msg, err);
}
+static DBusHandlerResult add_service_record_xml(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ struct service_agent *agent;
+ DBusMessage *reply;
+ struct binary_record *rec = 0;
+ sdp_record_t *sdp_rec = 0;
+ const char *path;
+ const char *record;
+ sdp_xml_context *xml_context = 0;
+ int err;
+
+ if (!dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_STRING, &path,
+ DBUS_TYPE_STRING, &record,
+ DBUS_TYPE_INVALID))
+ return error_invalid_arguments(conn, msg);
+
+ if (!dbus_connection_get_object_path_data(conn, path,
+ (void *) &agent)) {
+ /* If failed the path is invalid! */
+ return error_invalid_arguments(conn, msg);
+ }
+
+ if (!agent || strcmp(dbus_message_get_sender(msg), agent->id))
+ return error_not_authorized(conn, msg);
+
+ reply = dbus_message_new_method_return(msg);
+ if (!reply)
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+ xml_context = sdp_xml_init_context();
+ if (!xml_context) {
+ dbus_message_unref(reply);
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+ }
+
+ if (sdp_xml_parse_chunk(xml_context, record, strlen(record), 1)) {
+ debug("Parsing failed...");
+ sdp_xml_free_context(xml_context);
+ dbus_message_unref(reply);
+ return error_invalid_arguments(conn, msg);
+ }
+
+ sdp_rec = sdp_xml_get_record(xml_context);
+
+ sdp_xml_free_context(xml_context);
+
+ /* TODO: Is this correct? We remove the record handle attribute
+ (if it exists) so SDP server assigns a new one */
+ sdp_attr_remove(sdp_rec, 0x0);
+
+ /* TODO: How to handle RFCOMM / L2CAP PSMs? */
+
+ if (!sdp_rec) {
+ dbus_message_unref(reply);
+ return error_invalid_arguments(conn, msg);
+ }
+
+ rec = binary_record_new();
+ if (!rec) {
+ sdp_record_free(sdp_rec);
+ dbus_message_unref(reply);
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+ }
+
+ rec->buf = (sdp_buf_t *) malloc(sizeof(sdp_buf_t));
+
+ if (!rec->buf) {
+ sdp_record_free(sdp_rec);
+ binary_record_free(rec);
+ dbus_message_unref(reply);
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+ }
+
+ /* Generate binary record */
+ if (sdp_gen_record_pdu(sdp_rec, rec->buf) != 0) {
+ sdp_record_free(sdp_rec);
+ binary_record_free(rec);
+ dbus_message_unref(reply);
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+ }
+
+ sdp_record_free(sdp_rec);
+
+ /* Assign a new handle */
+ rec->ext_handle = next_handle++;
+
+ if (agent->running) {
+ uint32_t handle = 0;
+
+ if (register_sdp_record(rec->buf->data, rec->buf->data_size, &handle) < 0) {
+ err = errno;
+ error("Service record registration failed: %s (%d)",
+ strerror(err), err);
+ goto fail;
+ }
+
+ rec->handle = handle;
+ }
+
+ agent->records = slist_append(agent->records, rec);
+
+ dbus_message_append_args(reply,
+ DBUS_TYPE_UINT32, &rec->ext_handle,
+ DBUS_TYPE_INVALID);
+
+ return send_message_and_unref(conn, reply);
+
+fail:
+ binary_record_free(rec);
+ dbus_message_unref(reply);
+
+ return error_failed(conn, msg, err);
+}
+
static DBusHandlerResult remove_service_record(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct service_agent *agent;
struct binary_record *rec;
@@ -530,10 +647,11 @@
{ "ListAdapters", list_adapters },
{ "ListServices", list_services },
{ "RegisterService", register_service },
{ "UnregisterService", unregister_service },
{ "AddServiceRecord", add_service_record },
+ { "AddServiceRecordAsXML", add_service_record_xml },
{ "RemoveServiceRecord", remove_service_record },
{ NULL, NULL }
};
DBusHandlerResult handle_manager_method(DBusConnection *conn,
[-- Attachment #3: Type: text/plain, Size: 347 bytes --]
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
[-- Attachment #4: Type: text/plain, Size: 164 bytes --]
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Bluez-devel] [PATCH] XML SDP Record Registration
2006-11-21 23:59 ` Denis KENZIOR
@ 2006-11-22 6:24 ` Marcel Holtmann
2006-11-23 0:51 ` Denis KENZIOR
0 siblings, 1 reply; 7+ messages in thread
From: Marcel Holtmann @ 2006-11-22 6:24 UTC (permalink / raw)
To: BlueZ development
Hi Denis,
> Here's a fixed up version of the patch.
not it is not. I spent the last hours to fix your coding style mistakes.
I really like the stuff you do, but the more time I have to spent to fix
your code, the unlikelier I might include it. Here are some tips:
You are doing way too much casts. Especially all casts for malloc() and
free() are totally unneeded. Make sure you include malloc.h and
everything will be fine. Check the manual pages for needed includes if
you are unsure. Every cast has a potential to hide an error. Please do
only casts if you really have to and you are 100% sure it is the only
way to make this code working.
Pointer are never initialized with "= 0". Never. If you have to, then
it is "= NULL". The same applies to any comparison and I prefer doing
this with "!" as NULL check.
In general, the assigned of a variable when declaring it will only hide
programming mistakes that a compiler warning might have found. This
applies to any compiler warning you see. Don't try to hide. Understand
the real cause for it and fix that.
No public function when they are not needed. I prefer you declare
everything as static first and then non-static if needed. In this case
the compiler also warns you about unused code.
Keep the API simple. All of this is internal stuff and we can change it
without breaking any other applications. Having only one function for
the XML parsing makes it really simple and you don't have to play any
nasty typedef tricks. Speaking of which, typedefs should be avoided
whenever possible. Our SDP API is not a good example for that, I know
that, but it is too late to change it.
> I've made a script that dumps all profiles that sdptool supports and registers
> them back using XML and compares the results. It seems to work for all of
> them, but further testing would be appreciated.
Care to send a patch for sdptool that retrieves SDP records in XML
format.
Regards
Marcel
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Bluez-devel] [PATCH] XML SDP Record Registration
2006-11-22 6:24 ` Marcel Holtmann
@ 2006-11-23 0:51 ` Denis KENZIOR
2006-11-23 4:46 ` Marcel Holtmann
0 siblings, 1 reply; 7+ messages in thread
From: Denis KENZIOR @ 2006-11-23 0:51 UTC (permalink / raw)
To: bluez-devel
Marcel,
Oof, ouch.
In my defense, I followed the advice given in Linux CodingStyle document.
Most of the indentation issues you had a problem with was due to me using
'indent' with the suggested options.
In the future I will happily follow the code style conventions you outline.
However, given that this is my first serious submission I cannot be expected
to 'guess' the conventions if they are not written down, especially since
these are not outlined in the Linux CodingStyle document.
Since it seems that BlueZ has further conventions that developers should be
following, which are not outlined in the Linux Coding Style documents, I
suggest that you include them on the Coding Style section of the Development
page of bluez.org to avoid such problems in the future :)
Regards,
-Denis
> You are doing way too much casts. Especially all casts for malloc() and
> free() are totally unneeded. Make sure you include malloc.h and
> everything will be fine. Check the manual pages for needed includes if
> you are unsure. Every cast has a potential to hide an error. Please do
> only casts if you really have to and you are 100% sure it is the only
> way to make this code working.
>
> Pointer are never initialized with "= 0". Never. If you have to, then
> it is "= NULL". The same applies to any comparison and I prefer doing
> this with "!" as NULL check.
>
> In general, the assigned of a variable when declaring it will only hide
> programming mistakes that a compiler warning might have found. This
> applies to any compiler warning you see. Don't try to hide. Understand
> the real cause for it and fix that.
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Bluez-devel] [PATCH] XML SDP Record Registration
2006-11-23 0:51 ` Denis KENZIOR
@ 2006-11-23 4:46 ` Marcel Holtmann
0 siblings, 0 replies; 7+ messages in thread
From: Marcel Holtmann @ 2006-11-23 4:46 UTC (permalink / raw)
To: BlueZ development
Hi Denis,
> Oof, ouch.
>
> In my defense, I followed the advice given in Linux CodingStyle document.
> Most of the indentation issues you had a problem with was due to me using
> 'indent' with the suggested options.
>
> In the future I will happily follow the code style conventions you outline.
> However, given that this is my first serious submission I cannot be expected
> to 'guess' the conventions if they are not written down, especially since
> these are not outlined in the Linux CodingStyle document.
I simply have to keep the coding style unique for the whole project,
because otherwise patching will become a nightmare. We actually follow
the Linux kernel coding style and the best documentation is the paper
from Greg KH a couple of years ago. I linked the paper and his talk from
this page:
http://www.bluez.org/development.html
And one small piece of advise. Don't use indent. Nothing good comes out
of it. Following the kernel coding style also implies to rethink the
usage of goto and some other constructs where universities tried to tell
you that these are bad. However this is a learning process and when you
submit more and more patch you will definitely get a feel for it.
> Since it seems that BlueZ has further conventions that developers should be
> following, which are not outlined in the Linux Coding Style documents, I
> suggest that you include them on the Coding Style section of the Development
> page of bluez.org to avoid such problems in the future :)
I should write something about the extra conventions, but to my shame, I
am too lazy.
Regards
Marcel
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2006-11-23 4:46 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-11-21 5:04 [Bluez-devel] [PATCH] XML SDP Record Registration Denis KENZIOR
2006-11-21 7:41 ` Marcel Holtmann
2006-11-21 11:47 ` Marcel Holtmann
2006-11-21 23:59 ` Denis KENZIOR
2006-11-22 6:24 ` Marcel Holtmann
2006-11-23 0:51 ` Denis KENZIOR
2006-11-23 4:46 ` Marcel Holtmann
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.