From a66a22cd29417810d91c057c6febe817f3d7b26a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 22 Apr 2005 12:15:36 +0000 Subject: Add the textfile library for ASCII based file access --- common/Makefile.am | 9 +++++ common/textfile.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++ common/textfile.h | 29 ++++++++++++++++ 3 files changed, 138 insertions(+) create mode 100644 common/Makefile.am create mode 100644 common/textfile.c create mode 100644 common/textfile.h (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am new file mode 100644 index 00000000..ffcddf6e --- /dev/null +++ b/common/Makefile.am @@ -0,0 +1,9 @@ +# +# $Id$ +# + +noinst_LIBRARIES = libtextfile.a + +libtextfile_a_SOURCES = textfile.h textfile.c + +MAINTAINERCLEANFILES = Makefile.in diff --git a/common/textfile.c b/common/textfile.c new file mode 100644 index 00000000..6f84cfa9 --- /dev/null +++ b/common/textfile.c @@ -0,0 +1,100 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2005 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + * CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + * SOFTWARE IS DISCLAIMED. + * + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char *textfile_get(const char *pathname, const char *key) +{ + struct stat st; + char *map, *off, *end, *str = NULL; + off_t size; size_t len; + int fd; + + fd = open(pathname, O_RDONLY); + if (fd < 0) + return NULL; + + if (flock(fd, LOCK_SH) < 0) + goto close; + + if (fstat(fd, &st) < 0) + goto unlock; + + size = st.st_size; + + map = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0); + if (map == MAP_FAILED) + goto close; + + off = strstr(map, key); + if (!off) + goto unmap; + + if (off > map) { + while (*(off - 1) != '\r' && *(off - 1) != '\n') { + off = strstr(map, key); + if (!off) + goto unmap; + } + } + + end = strpbrk(off, "\r\n"); + if (!end) + goto unmap; + + len = strlen(key); + str = malloc(end - off - len); + memset(str, 0, end - off - len); + if (!str) + goto unmap; + + strncpy(str, off + len + 1, end - off - len - 1); + +unmap: + munmap(map, size); + +unlock: + flock(fd, LOCK_UN); + +close: + close(fd); + + return str; +} diff --git a/common/textfile.h b/common/textfile.h new file mode 100644 index 00000000..56a0bc10 --- /dev/null +++ b/common/textfile.h @@ -0,0 +1,29 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2005 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + * CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + * SOFTWARE IS DISCLAIMED. + * + * + * $Id$ + */ + +char *textfile_get(const char *pathname, const char *key); -- cgit From c6f99123f1269ad3742100eec084902a31e774bd Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 6 May 2005 19:56:46 +0000 Subject: Implement textfile writing support --- common/textfile.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++---- common/textfile.h | 1 + 2 files changed, 149 insertions(+), 12 deletions(-) (limited to 'common') diff --git a/common/textfile.c b/common/textfile.c index 6f84cfa9..0bda2a94 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -40,51 +40,186 @@ #include #include +static int write_key_value(const int fd, const char *key, const char *value) +{ + char *str; + int size, err = 0; + + size = strlen(key) + strlen(value) + 2; + + str = malloc(size); + if (!str) + return ENOMEM; + + sprintf(str, "%s %s\n", key, value); + + if (write(fd, str, size) < 0) + err = errno; + + free(str); + + return err; +} + +int textfile_put(const char *pathname, const char *key, const char *value) +{ + struct stat st; + char *map, *off, *end, *str; + off_t size, pos; size_t base, len; + int fd, err = 0; + + fd = open(pathname, O_RDWR); + if (fd < 0) + return -errno; + + if (flock(fd, LOCK_EX) < 0) { + err = errno; + goto close; + } + + if (fstat(fd, &st) < 0) { + err = errno; + goto unlock; + } + + size = st.st_size; + + if (!size) { + pos = lseek(fd, size, SEEK_SET); + err = write_key_value(fd, key, value); + goto unlock; + } + + map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (map == MAP_FAILED) { + err = errno; + goto unlock; + } + + off = strstr(map, key); + if (!off) { + munmap(map, size); + pos = lseek(fd, size, SEEK_SET); + err = write_key_value(fd, key, value); + goto unlock; + } + + if (off > map) { + while (*(off - 1) != '\r' && *(off - 1) != '\n') { + off = strstr(off, key); + if (!off) { + munmap(map, size); + pos = lseek(fd, size, SEEK_SET); + err = write_key_value(fd, key, value); + goto unlock; + } + } + } + + base = off - map; + + end = strpbrk(off, "\r\n"); + if (!end) { + err = EILSEQ; + goto unmap; + } + + len = strspn(end, "\r\n"); + end += len; + + len = size - (end - map); + + str = malloc(len); + if (!str) { + err = errno; + goto unmap; + } + + memcpy(str, end, len); + munmap(map, size); + + ftruncate(fd, base); + pos = lseek(fd, base, SEEK_SET); + + write_key_value(fd, key, value); + write(fd, str, len); + + free(str); + + goto unlock; + +unmap: + munmap(map, size); + +unlock: + flock(fd, LOCK_UN); + +close: + close(fd); + errno = err; + + return -err; +} + char *textfile_get(const char *pathname, const char *key) { struct stat st; char *map, *off, *end, *str = NULL; off_t size; size_t len; - int fd; + int fd, err = 0; fd = open(pathname, O_RDONLY); if (fd < 0) return NULL; - if (flock(fd, LOCK_SH) < 0) + if (flock(fd, LOCK_SH) < 0) { + err = errno; goto close; + } - if (fstat(fd, &st) < 0) + if (fstat(fd, &st) < 0) { + err = errno; goto unlock; + } size = st.st_size; - map = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0); - if (map == MAP_FAILED) - goto close; + map = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (map == MAP_FAILED) { + err = errno; + goto unlock; + } off = strstr(map, key); - if (!off) + if (!off) { + err = EILSEQ; goto unmap; + } if (off > map) { while (*(off - 1) != '\r' && *(off - 1) != '\n') { - off = strstr(map, key); - if (!off) + off = strstr(off, key); + if (!off) { + err = EILSEQ; goto unmap; + } } } end = strpbrk(off, "\r\n"); - if (!end) + if (!end) { + err = EILSEQ; goto unmap; + } len = strlen(key); str = malloc(end - off - len); - memset(str, 0, end - off - len); - if (!str) + if (!str) { + err = EILSEQ; goto unmap; + } + memset(str, 0, end - off - len); strncpy(str, off + len + 1, end - off - len - 1); unmap: @@ -95,6 +230,7 @@ unlock: close: close(fd); + errno = err; return str; } diff --git a/common/textfile.h b/common/textfile.h index 56a0bc10..8871f53c 100644 --- a/common/textfile.h +++ b/common/textfile.h @@ -26,4 +26,5 @@ * $Id$ */ +int textfile_put(const char *pathname, const char *key, const char *value); char *textfile_get(const char *pathname, const char *key); -- cgit From 1b67c5337c0704d147ed5e2ce143e553a79a43c5 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 5 Aug 2005 08:43:42 +0000 Subject: Update the textfile library --- common/textfile.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++---- common/textfile.h | 4 ++-- 2 files changed, 50 insertions(+), 6 deletions(-) (limited to 'common') diff --git a/common/textfile.c b/common/textfile.c index 0bda2a94..ca6f08f3 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -39,12 +39,51 @@ #include #include #include +#include -static int write_key_value(const int fd, const char *key, const char *value) +static int create_dirs(char *filename, mode_t mode) +{ + struct stat st; + char dir[PATH_MAX + 1], *prev, *next; + int err; + + err = stat(filename, &st); + if (!err && S_ISREG(st.st_mode)) + return 0; + + memset(dir, 0, PATH_MAX + 1); + strcat(dir, "/"); + + prev = strchr(filename, '/'); + + while (prev) { + next = strchr(prev + 1, '/'); + if (!next) + break; + + if (next - prev == 1) { + prev = next; + continue; + } + + strncat(dir, prev + 1, next - prev); + mkdir(dir, mode); + + prev = next; + } + + return 0; +} + +static int write_key_value(int fd, char *key, char *value) { char *str; int size, err = 0; + /* This check is needed, because other it will segfault */ + if (strlen(value) == 9) + return -EIO; + size = strlen(key) + strlen(value) + 2; str = malloc(size); @@ -61,7 +100,7 @@ static int write_key_value(const int fd, const char *key, const char *value) return err; } -int textfile_put(const char *pathname, const char *key, const char *value) +int textfile_put(char *pathname, char *key, char *value) { struct stat st; char *map, *off, *end, *str; @@ -90,7 +129,7 @@ int textfile_put(const char *pathname, const char *key, const char *value) goto unlock; } - map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, fd, 0); if (map == MAP_FAILED) { err = errno; goto unlock; @@ -129,6 +168,11 @@ int textfile_put(const char *pathname, const char *key, const char *value) len = size - (end - map); + if (len <= 0 || len > size) { + err = EILSEQ; + goto unmap; + } + str = malloc(len); if (!str) { err = errno; @@ -161,7 +205,7 @@ close: return -err; } -char *textfile_get(const char *pathname, const char *key) +char *textfile_get(char *pathname, char *key) { struct stat st; char *map, *off, *end, *str = NULL; diff --git a/common/textfile.h b/common/textfile.h index 8871f53c..4f3cf3d4 100644 --- a/common/textfile.h +++ b/common/textfile.h @@ -26,5 +26,5 @@ * $Id$ */ -int textfile_put(const char *pathname, const char *key, const char *value); -char *textfile_get(const char *pathname, const char *key); +int textfile_put(char *pathname, char *key, char *value); +char *textfile_get(char *pathname, char *key); -- cgit From 6419dcad3732c1be03bbe570c6c64c82b33ad599 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 5 Aug 2005 11:07:34 +0000 Subject: Add textfile regression test --- common/Makefile.am | 4 +++ common/test_textfile.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 common/test_textfile.c (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index ffcddf6e..3cc9318d 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -6,4 +6,8 @@ noinst_LIBRARIES = libtextfile.a libtextfile_a_SOURCES = textfile.h textfile.c +noinst_PROGRAMS = test_textfile + +test_textfile_LDADD = libtextfile.a + MAINTAINERCLEANFILES = Makefile.in diff --git a/common/test_textfile.c b/common/test_textfile.c new file mode 100644 index 00000000..88579296 --- /dev/null +++ b/common/test_textfile.c @@ -0,0 +1,66 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2005 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + * CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + * SOFTWARE IS DISCLAIMED. + * + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include "textfile.h" + +int main(int argc, char *argv[]) +{ + char filename[] = "/tmp/textfile"; + char key[18], value[512]; + int i, j, fd; + + fd = creat(filename, 0644); + close(fd); + + for (i = 1; i < 101; i++) { + sprintf(key, "00:00:00:00:00:%02X", i); + + memset(value, 0, sizeof(value)); + for (j = 0; j < i; j++) + value[j] = 'x'; + + printf("%s %s\n", key, value); + + if (textfile_put(filename, key, value) < 0) { + fprintf(stderr, "%s (%d)\n", strerror(errno), errno); + break; + } + } + + return 0; +} -- cgit From 7d19ed074bfea793e960c4f86af8085251ba613a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 6 Aug 2005 06:27:05 +0000 Subject: Fix off by one memory allocation error --- common/textfile.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'common') diff --git a/common/textfile.c b/common/textfile.c index ca6f08f3..08cd5a9f 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -75,18 +75,15 @@ static int create_dirs(char *filename, mode_t mode) return 0; } -static int write_key_value(int fd, char *key, char *value) +static inline int write_key_value(int fd, char *key, char *value) { char *str; - int size, err = 0; - - /* This check is needed, because other it will segfault */ - if (strlen(value) == 9) - return -EIO; + size_t size; + int err = 0; size = strlen(key) + strlen(value) + 2; - str = malloc(size); + str = malloc(size + 1); if (!str) return ENOMEM; -- cgit From 3e6da0a081eef2c4498ee045b30392e39a92dc5a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 6 Aug 2005 06:27:40 +0000 Subject: Add test for reading values --- common/test_textfile.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'common') diff --git a/common/test_textfile.c b/common/test_textfile.c index 88579296..54202d2c 100644 --- a/common/test_textfile.c +++ b/common/test_textfile.c @@ -41,7 +41,7 @@ int main(int argc, char *argv[]) { char filename[] = "/tmp/textfile"; - char key[18], value[512]; + char key[18], value[512], *str; int i, j, fd; fd = creat(filename, 0644); @@ -60,6 +60,10 @@ int main(int argc, char *argv[]) fprintf(stderr, "%s (%d)\n", strerror(errno), errno); break; } + + str = textfile_get(filename, key); + if (!str) + fprintf(stderr, "No value for %s\n", key); } return 0; -- cgit From 81b4c05b47e57505f56742b9349bee21116ba704 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 6 Aug 2005 07:00:03 +0000 Subject: Remove the create_dirs() function --- common/textfile.c | 34 ---------------------------------- 1 file changed, 34 deletions(-) (limited to 'common') diff --git a/common/textfile.c b/common/textfile.c index 08cd5a9f..a5d0a58b 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -41,40 +41,6 @@ #include #include -static int create_dirs(char *filename, mode_t mode) -{ - struct stat st; - char dir[PATH_MAX + 1], *prev, *next; - int err; - - err = stat(filename, &st); - if (!err && S_ISREG(st.st_mode)) - return 0; - - memset(dir, 0, PATH_MAX + 1); - strcat(dir, "/"); - - prev = strchr(filename, '/'); - - while (prev) { - next = strchr(prev + 1, '/'); - if (!next) - break; - - if (next - prev == 1) { - prev = next; - continue; - } - - strncat(dir, prev + 1, next - prev); - mkdir(dir, mode); - - prev = next; - } - - return 0; -} - static inline int write_key_value(int fd, char *key, char *value) { char *str; -- cgit From 44385c0baa98b0e27dad39cb8bd0e33ce5a027f6 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 30 Aug 2005 00:35:39 +0000 Subject: Move create_dirs() and create_file() into the textfile library --- common/textfile.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ common/textfile.h | 3 +++ 2 files changed, 53 insertions(+) (limited to 'common') diff --git a/common/textfile.c b/common/textfile.c index a5d0a58b..26cbbea7 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -41,6 +41,56 @@ #include #include +int create_dirs(char *filename, mode_t mode) +{ + struct stat st; + char dir[PATH_MAX + 1], *prev, *next; + int err; + + err = stat(filename, &st); + if (!err && S_ISREG(st.st_mode)) + return 0; + + memset(dir, 0, PATH_MAX + 1); + strcat(dir, "/"); + + prev = strchr(filename, '/'); + + while (prev) { + next = strchr(prev + 1, '/'); + if (!next) + break; + + if (next - prev == 1) { + prev = next; + continue; + } + + strncat(dir, prev + 1, next - prev); + mkdir(dir, mode); + + prev = next; + } + + return 0; +} + +int create_file(char *filename, mode_t mode) +{ + int fd; + + umask(S_IWGRP | S_IWOTH); + create_dirs(filename, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + + fd = open(filename, O_RDWR | O_CREAT, mode); + if (fd < 0) + return fd; + + close(fd); + + return 0; +} + static inline int write_key_value(int fd, char *key, char *value) { char *str; diff --git a/common/textfile.h b/common/textfile.h index 4f3cf3d4..bd7c7470 100644 --- a/common/textfile.h +++ b/common/textfile.h @@ -26,5 +26,8 @@ * $Id$ */ +int create_dirs(char *filename, mode_t mode); +int create_file(char *filename, mode_t mode); + int textfile_put(char *pathname, char *key, char *value); char *textfile_get(char *pathname, char *key); -- cgit From a8b5fad54044c7b5e7c6aa30ad24e5a86fc51daf Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 7 Sep 2005 17:23:00 +0000 Subject: Fix memory leaks with textfile_get() usage --- common/test_textfile.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'common') diff --git a/common/test_textfile.c b/common/test_textfile.c index 54202d2c..5a783d20 100644 --- a/common/test_textfile.c +++ b/common/test_textfile.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include "textfile.h" @@ -64,6 +65,8 @@ int main(int argc, char *argv[]) str = textfile_get(filename, key); if (!str) fprintf(stderr, "No value for %s\n", key); + else + free(str); } return 0; -- cgit From 50195243cfcac56a039480c3506acd0f5c5f80e0 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 7 Sep 2005 17:31:56 +0000 Subject: Let textfile_put() also replace the last key value pair --- common/textfile.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'common') diff --git a/common/textfile.c b/common/textfile.c index 26cbbea7..095e0355 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -180,8 +180,15 @@ int textfile_put(char *pathname, char *key, char *value) end += len; len = size - (end - map); + if (!len) { + munmap(map, size); + ftruncate(fd, base); + pos = lseek(fd, base, SEEK_SET); + err = write_key_value(fd, key, value); + goto unlock; + } - if (len <= 0 || len > size) { + if (len < 0 || len > size) { err = EILSEQ; goto unmap; } @@ -193,12 +200,12 @@ int textfile_put(char *pathname, char *key, char *value) } memcpy(str, end, len); - munmap(map, size); + munmap(map, size); ftruncate(fd, base); pos = lseek(fd, base, SEEK_SET); + err = write_key_value(fd, key, value); - write_key_value(fd, key, value); write(fd, str, len); free(str); -- cgit From b4b75b29434226f97505afa14a9b8838d9b93f61 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 10 Sep 2005 09:44:19 +0000 Subject: Fix infinite loops and false positive matches --- common/textfile.c | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) (limited to 'common') diff --git a/common/textfile.c b/common/textfile.c index 095e0355..f15d439c 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -113,6 +113,17 @@ static inline int write_key_value(int fd, char *key, char *value) return err; } +static inline char *find_key(char *map, char *key, size_t len) +{ + char *off = strstr(map, key); + + while (off && ((off > map && *(off - 1) != '\r' && + *(off - 1) != '\n') || *(off + len) != ' ')) + off = strstr(off + len, key); + + return off; +} + int textfile_put(char *pathname, char *key, char *value) { struct stat st; @@ -148,7 +159,7 @@ int textfile_put(char *pathname, char *key, char *value) goto unlock; } - off = strstr(map, key); + off = find_key(map, key, strlen(key)); if (!off) { munmap(map, size); pos = lseek(fd, size, SEEK_SET); @@ -156,18 +167,6 @@ int textfile_put(char *pathname, char *key, char *value) goto unlock; } - if (off > map) { - while (*(off - 1) != '\r' && *(off - 1) != '\n') { - off = strstr(off, key); - if (!off) { - munmap(map, size); - pos = lseek(fd, size, SEEK_SET); - err = write_key_value(fd, key, value); - goto unlock; - } - } - } - base = off - map; end = strpbrk(off, "\r\n"); @@ -254,29 +253,19 @@ char *textfile_get(char *pathname, char *key) goto unlock; } - off = strstr(map, key); + len = strlen(key); + off = find_key(map, key, len); if (!off) { err = EILSEQ; goto unmap; } - if (off > map) { - while (*(off - 1) != '\r' && *(off - 1) != '\n') { - off = strstr(off, key); - if (!off) { - err = EILSEQ; - goto unmap; - } - } - } - end = strpbrk(off, "\r\n"); if (!end) { err = EILSEQ; goto unmap; } - len = strlen(key); str = malloc(end - off - len); if (!str) { err = EILSEQ; -- cgit From 632a9432774ff3a0c6e556e8f32a565b38890767 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 29 Oct 2005 22:36:31 +0000 Subject: Big cleanup of CVS relics --- common/Makefile.am | 3 --- common/test_textfile.c | 25 ++++++++++--------------- common/textfile.c | 25 ++++++++++--------------- common/textfile.h | 25 ++++++++++--------------- 4 files changed, 30 insertions(+), 48 deletions(-) (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index 3cc9318d..71592813 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -1,6 +1,3 @@ -# -# $Id$ -# noinst_LIBRARIES = libtextfile.a diff --git a/common/test_textfile.c b/common/test_textfile.c index 5a783d20..1c6be660 100644 --- a/common/test_textfile.c +++ b/common/test_textfile.c @@ -6,24 +6,19 @@ * * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY - * CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, - * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS - * SOFTWARE IS DISCLAIMED. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * - * - * $Id$ */ #ifdef HAVE_CONFIG_H diff --git a/common/textfile.c b/common/textfile.c index f15d439c..dd77980c 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -6,24 +6,19 @@ * * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY - * CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, - * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS - * SOFTWARE IS DISCLAIMED. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * - * - * $Id$ */ #ifdef HAVE_CONFIG_H diff --git a/common/textfile.h b/common/textfile.h index bd7c7470..4f428ad0 100644 --- a/common/textfile.h +++ b/common/textfile.h @@ -6,24 +6,19 @@ * * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY - * CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, - * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS - * SOFTWARE IS DISCLAIMED. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * - * - * $Id$ */ int create_dirs(char *filename, mode_t mode); -- cgit From fe8f6f45a86efb2d356c3084b7991b90d8f319ea Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 1 Nov 2005 16:56:45 +0000 Subject: Move glib-ectomy.[ch] into the common directory --- common/Makefile.am | 4 +- common/glib-ectomy.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++++++ common/glib-ectomy.h | 92 +++++++++++++++++++++++++ 3 files changed, 280 insertions(+), 1 deletion(-) create mode 100644 common/glib-ectomy.c create mode 100644 common/glib-ectomy.h (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index 71592813..5a5a4702 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -1,8 +1,10 @@ -noinst_LIBRARIES = libtextfile.a +noinst_LIBRARIES = libtextfile.a libglib-ectomy.a libtextfile_a_SOURCES = textfile.h textfile.c +libglib_ectomy_a_SOURCES = glib-ectomy.h glib-ectomy.c + noinst_PROGRAMS = test_textfile test_textfile_LDADD = libtextfile.a diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c new file mode 100644 index 00000000..bea7f47c --- /dev/null +++ b/common/glib-ectomy.c @@ -0,0 +1,185 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "glib-ectomy.h" + +GIOError g_io_channel_read(GIOChannel *channel, gchar *buf, gsize count, gsize *bytes_read) +{ + int fd = channel->fd; + gssize result; + + /* At least according to the Debian manpage for read */ + if (count > SSIZE_MAX) + count = SSIZE_MAX; + +retry: + result = read (fd, buf, count); + + if (result < 0) { + *bytes_read = 0; + + switch (errno) { +#ifdef EINTR + case EINTR: + goto retry; +#endif +#ifdef EAGAIN + case EAGAIN: + return G_IO_STATUS_AGAIN; +#endif + default: + return G_IO_STATUS_ERROR; + } + } + + *bytes_read = result; + + return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF; +} + +void g_io_channel_close(GIOChannel *channel) +{ + if (!channel) + return; + + close(channel->fd); + + memset(channel, 0, sizeof(channel)); + free(channel); +} + +GIOChannel *g_io_channel_unix_new(int fd) +{ + GIOChannel *channel; + + channel = malloc(sizeof(GIOChannel)); + if (!channel) + return NULL; + + channel->fd = fd; + + return channel; +} + +gint g_io_channel_unix_get_fd(GIOChannel *channel) +{ + return channel->fd; +} + +struct watch { + guint id; + GIOChannel *channel; + GIOCondition condition; + GIOFunc func; + gpointer user_data; + + struct watch *next; +}; + +static struct watch watch_head = { .id = 0, .next = 0 }; + +void g_io_remove_watch(guint id) +{ + struct watch *w, *p; + + for (p = &watch_head, w = watch_head.next; w; w = w->next) + if (w->id == id) { + p->next = w->next; + free (w); + return; + } +} + +guint g_io_add_watch(GIOChannel *channel, GIOCondition condition, GIOFunc func, gpointer user_data) +{ + struct watch *watch = malloc(sizeof(struct watch)); + + watch->id = ++watch_head.id; + watch->channel = channel; + watch->condition = condition; + watch->func = func; + watch->user_data = user_data; + + watch->next = watch_head.next; + watch_head.next = watch; + + return watch->id; +} + +GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running) +{ + GMainLoop *ml; + + ml = malloc(sizeof(GMainLoop)); + if (!ml) + return NULL; + + ml->bail = 0; + + return ml; +} + +void g_main_loop_run(GMainLoop *loop) +{ + int open_max = sysconf(_SC_OPEN_MAX); + struct pollfd *ufds; + + ufds = malloc(open_max * sizeof(struct pollfd)); + if (!ufds) + return; + + while (!loop->bail) { + int nfds, rc, i; + struct watch *p, *w; + + nfds = 0; + for (w = watch_head.next; w != NULL; w = w->next) { + ufds[nfds].fd = w->channel->fd; + ufds[nfds].events = w->condition; + ufds[nfds].revents = 0; + nfds++; + } + + rc = poll(ufds, nfds, -1); + if (rc < 0) + continue; + + p = &watch_head; + w = watch_head.next; + i = 0; + + while (w) { + if (ufds[i].revents) { + gboolean keep = w->func(w->channel, ufds[i].revents, w->user_data); + if (!keep) { + p->next = w->next; + memset(w, 0, sizeof(*w)); + w = p->next; + i++; + continue; + } + } + + p = w; + w = w->next; + i++; + } + } + + free(ufds); +} + +void g_main_loop_quit(GMainLoop *loop) +{ + loop->bail = 1; +} diff --git a/common/glib-ectomy.h b/common/glib-ectomy.h new file mode 100644 index 00000000..c507e3c7 --- /dev/null +++ b/common/glib-ectomy.h @@ -0,0 +1,92 @@ +#ifndef __GLIB_ECTOMY_H +#define __GLIB_ECTOMY_H + +#include +#include + +typedef char gchar; +typedef short gshort; +typedef long glong; +typedef int gint; +typedef gint gboolean; + +typedef unsigned char guchar; +typedef unsigned short gushort; +typedef unsigned long gulong; +typedef unsigned int guint; + +typedef float gfloat; +typedef double gdouble; + +typedef void * gpointer; +typedef const void * gconstpointer; + +typedef size_t gsize; +typedef ssize_t gssize; + +#ifndef SSIZE_MAX +#define SSIZE_MAX INT_MAX +#endif + +typedef struct _GIOChannel { + int fd; +} GIOChannel; + +typedef struct _GMainContext { + int dummy; +} GMainContext; + +typedef struct _GMainLoop { + int bail; +} GMainLoop; + +typedef enum { + G_IO_ERROR_NONE, + G_IO_ERROR_AGAIN, + G_IO_ERROR_INVAL, + G_IO_ERROR_UNKNOWN +} GIOError; + +typedef enum { + G_IO_STATUS_ERROR = -1, + G_IO_STATUS_NORMAL = 0, + G_IO_STATUS_EOF = 1, + G_IO_STATUS_AGAIN = 2 +} GIOStatus; + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +typedef enum { + G_IO_IN = POLLIN, + G_IO_OUT = POLLOUT, + G_IO_PRI = POLLPRI, + G_IO_ERR = POLLERR, + G_IO_HUP = POLLHUP, + G_IO_NVAL = POLLNVAL +} GIOCondition; + +typedef gboolean (*GIOFunc) (GIOChannel *source, GIOCondition condition, gpointer data); + +GIOError g_io_channel_read(GIOChannel *channel, gchar *buf, gsize count, gsize *bytes_read); +void g_io_channel_close(GIOChannel *channel); + +GIOChannel *g_io_channel_unix_new(int fd); +gint g_io_channel_unix_get_fd(GIOChannel *channel); +guint g_io_add_watch(GIOChannel *channel, GIOCondition condition, GIOFunc func, gpointer user_data); +void g_io_remove_watch(guint id); + +GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running); +void g_main_loop_run(GMainLoop *loop); +void g_main_loop_quit(GMainLoop *loop); + +#define g_main_new(is_running) g_main_loop_new(NULL, is_running); +#define g_main_run(loop) g_main_loop_run(loop) +#define g_main_quit(loop) g_main_loop_quit(loop) + +#endif /* __GLIB_ECTOMY_H */ -- cgit From db176529529c142333f668f2c1334753f7f406bf Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 9 Nov 2005 00:04:15 +0000 Subject: Include checks for mmap() returning NULL --- common/textfile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'common') diff --git a/common/textfile.c b/common/textfile.c index dd77980c..b2134562 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -149,7 +149,7 @@ int textfile_put(char *pathname, char *key, char *value) } map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, fd, 0); - if (map == MAP_FAILED) { + if (!map || map == MAP_FAILED) { err = errno; goto unlock; } @@ -243,7 +243,7 @@ char *textfile_get(char *pathname, char *key) size = st.st_size; map = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); - if (map == MAP_FAILED) { + if (!map || map == MAP_FAILED) { err = errno; goto unlock; } -- cgit From f2e48c44a7e4c9ee31b8ce2e302186f6047cfeab Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 3 Jan 2006 13:28:56 +0000 Subject: Update copyright information --- common/test_textfile.c | 2 +- common/textfile.c | 2 +- common/textfile.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'common') diff --git a/common/test_textfile.c b/common/test_textfile.c index 1c6be660..80761526 100644 --- a/common/test_textfile.c +++ b/common/test_textfile.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2005 Marcel Holtmann + * Copyright (C) 2004-2006 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/textfile.c b/common/textfile.c index b2134562..906c230d 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2005 Marcel Holtmann + * Copyright (C) 2004-2006 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/textfile.h b/common/textfile.h index 4f428ad0..803fc231 100644 --- a/common/textfile.h +++ b/common/textfile.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2005 Marcel Holtmann + * Copyright (C) 2004-2006 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify -- cgit From 454c7500c64ab132f44aebbd7086a9748e5c4436 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 17 Jan 2006 10:52:35 +0000 Subject: Use MAP_PRIVATE instead of MAP_SHARED for textfile_put() --- common/textfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common') diff --git a/common/textfile.c b/common/textfile.c index 906c230d..ec445b1a 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -148,7 +148,7 @@ int textfile_put(char *pathname, char *key, char *value) goto unlock; } - map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, fd, 0); + map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_LOCKED, fd, 0); if (!map || map == MAP_FAILED) { err = errno; goto unlock; -- cgit From 71dc4067220c5b994885f63127b4b7eb947002fd Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 7 Feb 2006 09:10:07 +0000 Subject: Add support for deleting keys --- common/test_textfile.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++-- common/textfile.c | 48 ++++++++++++++++++---------- common/textfile.h | 1 + 3 files changed, 116 insertions(+), 19 deletions(-) (limited to 'common') diff --git a/common/test_textfile.c b/common/test_textfile.c index 80761526..c2b2c993 100644 --- a/common/test_textfile.c +++ b/common/test_textfile.c @@ -38,12 +38,13 @@ int main(int argc, char *argv[]) { char filename[] = "/tmp/textfile"; char key[18], value[512], *str; - int i, j, fd; + int i, j, fd, max = 10; fd = creat(filename, 0644); close(fd); - for (i = 1; i < 101; i++) { + + for (i = 1; i < max + 1; i++) { sprintf(key, "00:00:00:00:00:%02X", i); memset(value, 0, sizeof(value)); @@ -64,5 +65,86 @@ int main(int argc, char *argv[]) free(str); } + + sprintf(key, "00:00:00:00:00:%02X", max); + + memset(value, 0, sizeof(value)); + for (j = 0; j < max; j++) + value[j] = 'y'; + + if (textfile_put(filename, key, value) < 0) + fprintf(stderr, "%s (%d)\n", strerror(errno), errno); + + sprintf(key, "00:00:00:00:00:%02X", 1); + + memset(value, 0, sizeof(value)); + for (j = 0; j < max; j++) + value[j] = 'z'; + + if (textfile_put(filename, key, value) < 0) + fprintf(stderr, "%s (%d)\n", strerror(errno), errno); + + printf("\n"); + + for (i = 1; i < max + 1; i++) { + sprintf(key, "00:00:00:00:00:%02X", i); + + str = textfile_get(filename, key); + if (str) { + printf("%s %s\n", key, str); + free(str); + } + } + + + sprintf(key, "00:00:00:00:00:%02X", 2); + + if (textfile_del(filename, key) < 0) + fprintf(stderr, "%s (%d)\n", strerror(errno), errno); + + sprintf(key, "00:00:00:00:00:%02X", max - 3); + + if (textfile_del(filename, key) < 0) + fprintf(stderr, "%s (%d)\n", strerror(errno), errno); + + printf("\n"); + + for (i = 1; i < max + 1; i++) { + sprintf(key, "00:00:00:00:00:%02X", i); + + str = textfile_get(filename, key); + if (str) { + printf("%s %s\n", key, str); + free(str); + } + } + + sprintf(key, "00:00:00:00:00:%02X", 1); + + if (textfile_del(filename, key) < 0) + fprintf(stderr, "%s (%d)\n", strerror(errno), errno); + + sprintf(key, "00:00:00:00:00:%02X", max); + + if (textfile_del(filename, key) < 0) + fprintf(stderr, "%s (%d)\n", strerror(errno), errno); + + sprintf(key, "00:00:00:00:00:%02X", max + 1); + + if (textfile_del(filename, key) < 0) + fprintf(stderr, "%s (%d)\n", strerror(errno), errno); + + printf("\n"); + + for (i = 1; i < max + 1; i++) { + sprintf(key, "00:00:00:00:00:%02X", i); + + str = textfile_get(filename, key); + if (str) { + printf("%s %s\n", key, str); + free(str); + } + } + return 0; } diff --git a/common/textfile.c b/common/textfile.c index ec445b1a..3aa74d9a 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -86,6 +86,17 @@ int create_file(char *filename, mode_t mode) return 0; } +static inline char *find_key(char *map, char *key, size_t len) +{ + char *off = strstr(map, key); + + while (off && ((off > map && *(off - 1) != '\r' && + *(off - 1) != '\n') || *(off + len) != ' ')) + off = strstr(off + len, key); + + return off; +} + static inline int write_key_value(int fd, char *key, char *value) { char *str; @@ -108,18 +119,7 @@ static inline int write_key_value(int fd, char *key, char *value) return err; } -static inline char *find_key(char *map, char *key, size_t len) -{ - char *off = strstr(map, key); - - while (off && ((off > map && *(off - 1) != '\r' && - *(off - 1) != '\n') || *(off + len) != ' ')) - off = strstr(off + len, key); - - return off; -} - -int textfile_put(char *pathname, char *key, char *value) +static int write_key(char *pathname, char *key, char *value) { struct stat st; char *map, *off, *end, *str; @@ -156,9 +156,11 @@ int textfile_put(char *pathname, char *key, char *value) off = find_key(map, key, strlen(key)); if (!off) { - munmap(map, size); - pos = lseek(fd, size, SEEK_SET); - err = write_key_value(fd, key, value); + if (value) { + munmap(map, size); + pos = lseek(fd, size, SEEK_SET); + err = write_key_value(fd, key, value); + } goto unlock; } @@ -178,7 +180,8 @@ int textfile_put(char *pathname, char *key, char *value) munmap(map, size); ftruncate(fd, base); pos = lseek(fd, base, SEEK_SET); - err = write_key_value(fd, key, value); + if (value) + err = write_key_value(fd, key, value); goto unlock; } @@ -198,7 +201,8 @@ int textfile_put(char *pathname, char *key, char *value) munmap(map, size); ftruncate(fd, base); pos = lseek(fd, base, SEEK_SET); - err = write_key_value(fd, key, value); + if (value) + err = write_key_value(fd, key, value); write(fd, str, len); @@ -219,6 +223,16 @@ close: return -err; } +int textfile_put(char *pathname, char *key, char *value) +{ + return write_key(pathname, key, value); +} + +int textfile_del(char *pathname, char *key) +{ + return write_key(pathname, key, NULL); +} + char *textfile_get(char *pathname, char *key) { struct stat st; diff --git a/common/textfile.h b/common/textfile.h index 803fc231..62ad4b80 100644 --- a/common/textfile.h +++ b/common/textfile.h @@ -25,4 +25,5 @@ int create_dirs(char *filename, mode_t mode); int create_file(char *filename, mode_t mode); int textfile_put(char *pathname, char *key, char *value); +int textfile_del(char *pathname, char *key); char *textfile_get(char *pathname, char *key); -- cgit From 85cc0c57e4fd0e44c3b270aba4f87eb28151b1a2 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 8 Feb 2006 05:38:38 +0000 Subject: Add textfile_foreach() function --- common/test_textfile.c | 24 ++++---------- common/textfile.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++ common/textfile.h | 3 ++ 3 files changed, 99 insertions(+), 17 deletions(-) (limited to 'common') diff --git a/common/test_textfile.c b/common/test_textfile.c index c2b2c993..5a5b22c5 100644 --- a/common/test_textfile.c +++ b/common/test_textfile.c @@ -34,6 +34,11 @@ #include "textfile.h" +static void print_entry(char *key, char *value, void *data) +{ + printf("%s %s\n", key, value); +} + int main(int argc, char *argv[]) { char filename[] = "/tmp/textfile"; @@ -109,15 +114,8 @@ int main(int argc, char *argv[]) printf("\n"); - for (i = 1; i < max + 1; i++) { - sprintf(key, "00:00:00:00:00:%02X", i); + textfile_foreach(filename, print_entry, NULL); - str = textfile_get(filename, key); - if (str) { - printf("%s %s\n", key, str); - free(str); - } - } sprintf(key, "00:00:00:00:00:%02X", 1); @@ -136,15 +134,7 @@ int main(int argc, char *argv[]) printf("\n"); - for (i = 1; i < max + 1; i++) { - sprintf(key, "00:00:00:00:00:%02X", i); - - str = textfile_get(filename, key); - if (str) { - printf("%s %s\n", key, str); - free(str); - } - } + textfile_foreach(filename, print_entry, NULL); return 0; } diff --git a/common/textfile.c b/common/textfile.c index 3aa74d9a..2ed929a3 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -296,3 +296,92 @@ close: return str; } + +int textfile_foreach(char *pathname, + void (*func)(char *key, char *value, void *data), void *data) +{ + struct stat st; + char *map, *off, *end, *key, *value; + off_t size; size_t len; + int fd, err = 0; + + fd = open(pathname, O_RDONLY); + if (fd < 0) + return -errno; + + if (flock(fd, LOCK_SH) < 0) { + err = errno; + goto close; + } + + if (fstat(fd, &st) < 0) { + err = errno; + goto unlock; + } + + size = st.st_size; + + map = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (!map || map == MAP_FAILED) { + err = errno; + goto unlock; + } + + off = map; + + while (1) { + end = strpbrk(off, " "); + if (!end) { + err = EILSEQ; + break; + } + + len = end - off; + + key = malloc(len + 1); + if (!key) { + err = errno; + break; + } + + memset(key, 0, len + 1); + memcpy(key, off, len); + + off = end + 1; + + end = strpbrk(off, "\r\n"); + if (!end) { + err = EILSEQ; + break; + } + + len = end - off; + + value = malloc(len + 1); + if (!value) { + err = errno; + break; + } + + memset(value, 0, len + 1); + memcpy(value, off, len); + + func(key, value, data); + + free(key); + free(value); + + off = end + 1; + } + + munmap(map, size); + +unlock: + flock(fd, LOCK_UN); + +close: + close(fd); + errno = err; + + return 0; +} diff --git a/common/textfile.h b/common/textfile.h index 62ad4b80..3c8b6841 100644 --- a/common/textfile.h +++ b/common/textfile.h @@ -27,3 +27,6 @@ int create_file(char *filename, mode_t mode); int textfile_put(char *pathname, char *key, char *value); int textfile_del(char *pathname, char *key); char *textfile_get(char *pathname, char *key); + +int textfile_foreach(char *pathname, + void (*func)(char *key, char *value, void *data), void *data); -- cgit From 2fa395ac7d4bd9d0108194c375bf69839f4d62ec Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 11 Feb 2006 12:12:27 +0000 Subject: Use const qualifier for textfile library --- common/textfile.c | 18 +++++++++--------- common/textfile.h | 12 ++++++------ 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'common') diff --git a/common/textfile.c b/common/textfile.c index 2ed929a3..bb55109c 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -36,7 +36,7 @@ #include #include -int create_dirs(char *filename, mode_t mode) +int create_dirs(const char *filename, const mode_t mode) { struct stat st; char dir[PATH_MAX + 1], *prev, *next; @@ -70,7 +70,7 @@ int create_dirs(char *filename, mode_t mode) return 0; } -int create_file(char *filename, mode_t mode) +int create_file(const char *filename, const mode_t mode) { int fd; @@ -86,7 +86,7 @@ int create_file(char *filename, mode_t mode) return 0; } -static inline char *find_key(char *map, char *key, size_t len) +static inline char *find_key(char *map, const char *key, size_t len) { char *off = strstr(map, key); @@ -97,7 +97,7 @@ static inline char *find_key(char *map, char *key, size_t len) return off; } -static inline int write_key_value(int fd, char *key, char *value) +static inline int write_key_value(int fd, const char *key, const char *value) { char *str; size_t size; @@ -119,7 +119,7 @@ static inline int write_key_value(int fd, char *key, char *value) return err; } -static int write_key(char *pathname, char *key, char *value) +static int write_key(const char *pathname, const char *key, const char *value) { struct stat st; char *map, *off, *end, *str; @@ -223,17 +223,17 @@ close: return -err; } -int textfile_put(char *pathname, char *key, char *value) +int textfile_put(const char *pathname, const char *key, const char *value) { return write_key(pathname, key, value); } -int textfile_del(char *pathname, char *key) +int textfile_del(const char *pathname, const char *key) { return write_key(pathname, key, NULL); } -char *textfile_get(char *pathname, char *key) +char *textfile_get(const char *pathname, const char *key) { struct stat st; char *map, *off, *end, *str = NULL; @@ -297,7 +297,7 @@ close: return str; } -int textfile_foreach(char *pathname, +int textfile_foreach(const char *pathname, void (*func)(char *key, char *value, void *data), void *data) { struct stat st; diff --git a/common/textfile.h b/common/textfile.h index 3c8b6841..2e6d57b2 100644 --- a/common/textfile.h +++ b/common/textfile.h @@ -21,12 +21,12 @@ * */ -int create_dirs(char *filename, mode_t mode); -int create_file(char *filename, mode_t mode); +int create_dirs(const char *filename, const mode_t mode); +int create_file(const char *filename, const mode_t mode); -int textfile_put(char *pathname, char *key, char *value); -int textfile_del(char *pathname, char *key); -char *textfile_get(char *pathname, char *key); +int textfile_put(const char *pathname, const char *key, const char *value); +int textfile_del(const char *pathname, const char *key); +char *textfile_get(const char *pathname, const char *key); -int textfile_foreach(char *pathname, +int textfile_foreach(const char *pathname, void (*func)(char *key, char *value, void *data), void *data); -- cgit From ea6e51d583bde53514e7589267ba55f55b8a23e6 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 17 Feb 2006 15:20:51 +0000 Subject: Fix handling of D-Bus disconnect signal --- common/glib-ectomy.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index bea7f47c..7c1f9d9f 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -92,7 +92,7 @@ void g_io_remove_watch(guint id) { struct watch *w, *p; - for (p = &watch_head, w = watch_head.next; w; w = w->next) + for (p = &watch_head, w = watch_head.next; w; p = w, w = w->next) if (w->id == id) { p->next = w->next; free (w); @@ -181,5 +181,12 @@ void g_main_loop_run(GMainLoop *loop) void g_main_loop_quit(GMainLoop *loop) { + struct watch *w; + loop->bail = 1; + + for (w = watch_head.next; w; w = w->next) { + watch_head.next = w->next; + free (w); + } } -- cgit From d6c6e3c549fc59e25dd0869495e7b2f8c1ef999f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 24 Feb 2006 20:52:07 +0000 Subject: Add support for destroy notification function --- common/glib-ectomy.c | 19 +++++++++++++++++-- common/glib-ectomy.h | 7 ++++++- 2 files changed, 23 insertions(+), 3 deletions(-) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index 7c1f9d9f..c8e9bd44 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -79,9 +79,11 @@ gint g_io_channel_unix_get_fd(GIOChannel *channel) struct watch { guint id; GIOChannel *channel; + gint priority; GIOCondition condition; GIOFunc func; gpointer user_data; + GDestroyNotify destroy; struct watch *next; }; @@ -100,15 +102,19 @@ void g_io_remove_watch(guint id) } } -guint g_io_add_watch(GIOChannel *channel, GIOCondition condition, GIOFunc func, gpointer user_data) +guint g_io_add_watch_full(GIOChannel *channel, gint priority, + GIOCondition condition, GIOFunc func, + gpointer user_data, GDestroyNotify notify) { struct watch *watch = malloc(sizeof(struct watch)); watch->id = ++watch_head.id; watch->channel = channel; + watch->priority = priority; watch->condition = condition; watch->func = func; watch->user_data = user_data; + watch->destroy = notify; watch->next = watch_head.next; watch_head.next = watch; @@ -116,6 +122,13 @@ guint g_io_add_watch(GIOChannel *channel, GIOCondition condition, GIOFunc func, return watch->id; } +guint g_io_add_watch(GIOChannel *channel, GIOCondition condition, + GIOFunc func, gpointer user_data) +{ + return g_io_add_watch_full(channel, 0, condition, + func, user_data, NULL); +} + GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running) { GMainLoop *ml; @@ -162,6 +175,8 @@ void g_main_loop_run(GMainLoop *loop) if (ufds[i].revents) { gboolean keep = w->func(w->channel, ufds[i].revents, w->user_data); if (!keep) { + if (w->destroy) + w->destroy(w->user_data); p->next = w->next; memset(w, 0, sizeof(*w)); w = p->next; @@ -187,6 +202,6 @@ void g_main_loop_quit(GMainLoop *loop) for (w = watch_head.next; w; w = w->next) { watch_head.next = w->next; - free (w); + free(w); } } diff --git a/common/glib-ectomy.h b/common/glib-ectomy.h index c507e3c7..e921b40d 100644 --- a/common/glib-ectomy.h +++ b/common/glib-ectomy.h @@ -71,6 +71,7 @@ typedef enum { G_IO_NVAL = POLLNVAL } GIOCondition; +typedef void (*GDestroyNotify) (gpointer data); typedef gboolean (*GIOFunc) (GIOChannel *source, GIOCondition condition, gpointer data); GIOError g_io_channel_read(GIOChannel *channel, gchar *buf, gsize count, gsize *bytes_read); @@ -78,7 +79,11 @@ void g_io_channel_close(GIOChannel *channel); GIOChannel *g_io_channel_unix_new(int fd); gint g_io_channel_unix_get_fd(GIOChannel *channel); -guint g_io_add_watch(GIOChannel *channel, GIOCondition condition, GIOFunc func, gpointer user_data); +guint g_io_add_watch(GIOChannel *channel, GIOCondition condition, + GIOFunc func, gpointer user_data); +guint g_io_add_watch_full(GIOChannel *channel, gint priority, + GIOCondition condition, GIOFunc func, + gpointer user_data, GDestroyNotify notify); void g_io_remove_watch(guint id); GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running); -- cgit From 3467d91677938f2c16ccc9886b9c48bf144b407d Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 24 Feb 2006 21:28:29 +0000 Subject: Call destroy function also on cleanup --- common/glib-ectomy.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index c8e9bd44..efc9e20d 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -201,6 +201,8 @@ void g_main_loop_quit(GMainLoop *loop) loop->bail = 1; for (w = watch_head.next; w; w = w->next) { + if (w->destroy) + w->destroy(w->user_data); watch_head.next = w->next; free(w); } -- cgit From 148aa53876853a637e5b94f3c6aae5fb2d788c90 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 9 Mar 2006 17:57:03 +0000 Subject: Generic singly linked list functionality --- common/Makefile.am | 4 ++- common/list.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ common/list.h | 38 ++++++++++++++++++++++ 3 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 common/list.c create mode 100644 common/list.h (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index 5a5a4702..d2233f94 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -1,5 +1,7 @@ -noinst_LIBRARIES = libtextfile.a libglib-ectomy.a +noinst_LIBRARIES = libtextfile.a libglib-ectomy.a liblist.a + +liblist_a_SOURCES = list.h list.c libtextfile_a_SOURCES = textfile.h textfile.c diff --git a/common/list.c b/common/list.c new file mode 100644 index 00000000..cb160501 --- /dev/null +++ b/common/list.c @@ -0,0 +1,94 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2006 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "list.h" + +struct slist *slist_append(struct slist *list, void *data) +{ + struct slist *entry, *tail; + + entry = malloc(sizeof(struct slist)); + /* FIXME: this currently just silently fails */ + if (!entry) + return list; + + entry->data = data; + entry->next = NULL; + + if (!list) + return entry; + + /* Find the end of the list */ + for (tail = list; tail->next; tail = tail->next); + + tail->next = entry; + + return list; +} + +struct slist *slist_remove(struct slist *list, void *data) +{ + struct slist *l, *next, *prev = NULL, *match = NULL; + + if (!list) + return NULL; + + for (l = list; l != NULL; l = l->next) { + if (l->data == data) { + match = l; + break; + } + prev = l; + } + + if (!match) + return list; + + next = match->next; + match->next = NULL; + + /* If the head was removed, return the next element */ + if (!prev) + return next; + + prev->next = match->next; + + return list; +} + +void slist_free(struct slist *list) +{ + struct slist *l, *next; + + for (l = list; l != NULL; l = next) { + next = l->next; + free(l); + } +} diff --git a/common/list.h b/common/list.h new file mode 100644 index 00000000..9185796e --- /dev/null +++ b/common/list.h @@ -0,0 +1,38 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2006 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#ifndef _LIST_H_ +#define _LIST_H_ + +struct slist { + void *data; + struct slist *next; +}; + +struct slist *slist_append(struct slist *list, void *data); + +struct slist *slist_remove(struct slist *list, void *data); + +void slist_free(struct slist *list); + + +#endif /* _LIST_H_ */ -- cgit From 7297697c324a6113371fd60b3668320e5a4817a7 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 9 Mar 2006 19:08:49 +0000 Subject: Small cleanup to the common functions --- common/list.c | 4 +++- common/list.h | 9 +++++---- common/textfile.h | 5 +++++ 3 files changed, 13 insertions(+), 5 deletions(-) (limited to 'common') diff --git a/common/list.c b/common/list.c index cb160501..1aa9d0be 100644 --- a/common/list.c +++ b/common/list.c @@ -3,6 +3,7 @@ * BlueZ - Bluetooth protocol stack for Linux * * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2005-2006 Johan Hedberg * * * This program is free software; you can redistribute it and/or modify @@ -26,7 +27,8 @@ #endif #include -#include +#include +#include #include "list.h" diff --git a/common/list.h b/common/list.h index 9185796e..b16bf946 100644 --- a/common/list.h +++ b/common/list.h @@ -3,6 +3,7 @@ * BlueZ - Bluetooth protocol stack for Linux * * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2005-2006 Johan Hedberg * * * This program is free software; you can redistribute it and/or modify @@ -20,8 +21,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ -#ifndef _LIST_H_ -#define _LIST_H_ + +#ifndef __LIST_H +#define __LIST_H struct slist { void *data; @@ -34,5 +36,4 @@ struct slist *slist_remove(struct slist *list, void *data); void slist_free(struct slist *list); - -#endif /* _LIST_H_ */ +#endif /* __LIST_H */ diff --git a/common/textfile.h b/common/textfile.h index 2e6d57b2..b9c01ad3 100644 --- a/common/textfile.h +++ b/common/textfile.h @@ -21,6 +21,9 @@ * */ +#ifndef __TEXTFILE_H +#define __TEXTFILE_H + int create_dirs(const char *filename, const mode_t mode); int create_file(const char *filename, const mode_t mode); @@ -30,3 +33,5 @@ char *textfile_get(const char *pathname, const char *key); int textfile_foreach(const char *pathname, void (*func)(char *key, char *value, void *data), void *data); + +#endif /* __TEXTFILE_H */ -- cgit From d7c1b5874dcb3b4242c8d905255cf3c07cd7f877 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 9 Mar 2006 19:14:37 +0000 Subject: Fix memory leak in list.c --- common/list.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'common') diff --git a/common/list.c b/common/list.c index 1aa9d0be..bda2b564 100644 --- a/common/list.c +++ b/common/list.c @@ -74,13 +74,14 @@ struct slist *slist_remove(struct slist *list, void *data) return list; next = match->next; - match->next = NULL; + + free(match); /* If the head was removed, return the next element */ if (!prev) return next; - prev->next = match->next; + prev->next = next; return list; } -- cgit From 1477aa78883562b5d5e97e4ec6fa2d23216673c2 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 13 Mar 2006 20:54:47 +0000 Subject: More passkey handler functionality --- common/list.c | 13 +++++++++++++ common/list.h | 5 +++++ 2 files changed, 18 insertions(+) (limited to 'common') diff --git a/common/list.c b/common/list.c index bda2b564..c6d8cb98 100644 --- a/common/list.c +++ b/common/list.c @@ -86,6 +86,19 @@ struct slist *slist_remove(struct slist *list, void *data) return list; } +struct slist *slist_find(struct slist *list, const void *data, + cmp_func_t cmp_func) +{ + struct slist *l; + + for (l = list; l != NULL; l = l->next) { + if (!cmp_func(l->data, data)) + return l; + } + + return NULL; +} + void slist_free(struct slist *list) { struct slist *l, *next; diff --git a/common/list.h b/common/list.h index b16bf946..1838370c 100644 --- a/common/list.h +++ b/common/list.h @@ -30,10 +30,15 @@ struct slist { struct slist *next; }; +typedef int (*cmp_func_t)(const void *a, const void *b); + struct slist *slist_append(struct slist *list, void *data); struct slist *slist_remove(struct slist *list, void *data); +struct slist *slist_find(struct slist *list, const void *data, + cmp_func_t cmp_func); + void slist_free(struct slist *list); #endif /* __LIST_H */ -- cgit From 7b8a634126a3aa79e08d9d35d207f55016f9bda9 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 14 Mar 2006 21:35:31 +0000 Subject: added slist_foreach function and fixed small memory leak --- common/list.c | 9 +++++++++ common/list.h | 2 ++ 2 files changed, 11 insertions(+) (limited to 'common') diff --git a/common/list.c b/common/list.c index c6d8cb98..31ae9d35 100644 --- a/common/list.c +++ b/common/list.c @@ -99,6 +99,15 @@ struct slist *slist_find(struct slist *list, const void *data, return NULL; } +void slist_foreach(struct slist *list, slist_func_t func, void *user_data) +{ + while (list) { + struct slist *next = list->next; + func(list->data, user_data); + list = next; + } +} + void slist_free(struct slist *list) { struct slist *l, *next; diff --git a/common/list.h b/common/list.h index 1838370c..026d470c 100644 --- a/common/list.h +++ b/common/list.h @@ -31,6 +31,7 @@ struct slist { }; typedef int (*cmp_func_t)(const void *a, const void *b); +typedef void (*slist_func_t)(void *data, void *user_data); struct slist *slist_append(struct slist *list, void *data); @@ -39,6 +40,7 @@ struct slist *slist_remove(struct slist *list, void *data); struct slist *slist_find(struct slist *list, const void *data, cmp_func_t cmp_func); +void slist_foreach(struct slist *list, slist_func_t func, void *user_data); void slist_free(struct slist *list); #endif /* __LIST_H */ -- cgit From 0f0f596ae5d5f0f0dd576e5da8b15ee8a652790e Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 16 Mar 2006 22:01:17 +0000 Subject: Fix GWatch leak in glib-ectomy.c --- common/glib-ectomy.c | 1 + 1 file changed, 1 insertion(+) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index efc9e20d..463d0aee 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -179,6 +179,7 @@ void g_main_loop_run(GMainLoop *loop) w->destroy(w->user_data); p->next = w->next; memset(w, 0, sizeof(*w)); + free(w); w = p->next; i++; continue; -- cgit From 8bc26371882b7ebaaa25ca0c2ce81b1f719daeea Mon Sep 17 00:00:00 2001 From: Eduardo Rocha Date: Fri, 24 Mar 2006 14:36:27 +0000 Subject: Fix a SEGFAULT that happens when textfile_del is called using an empty file. --- common/test_textfile.c | 22 ++++++++++++++++++++++ common/textfile.c | 6 ++++-- 2 files changed, 26 insertions(+), 2 deletions(-) (limited to 'common') diff --git a/common/test_textfile.c b/common/test_textfile.c index 5a5b22c5..8b60bbe8 100644 --- a/common/test_textfile.c +++ b/common/test_textfile.c @@ -48,6 +48,28 @@ int main(int argc, char *argv[]) fd = creat(filename, 0644); close(fd); + sprintf(key, "00:00:00:00:00:00"); + if (textfile_del(filename, key) < 0) + fprintf(stderr, "%s (%d)\n", strerror(errno), errno); + + memset(value, 0, sizeof(value)); + if (textfile_put(filename, key, value) < 0) + fprintf(stderr, "%s (%d)\n", strerror(errno), errno); + + str = textfile_get(filename, key); + if (!str) + fprintf(stderr, "No value for %s\n", key); + else + free(str); + + if (textfile_del(filename, key) < 0) + fprintf(stderr, "%s (%d)\n", strerror(errno), errno); + + str = textfile_get(filename, key); + if (str) { + fprintf(stderr, "Found value for %s\n", key); + free(str); + } for (i = 1; i < max + 1; i++) { sprintf(key, "00:00:00:00:00:%02X", i); diff --git a/common/textfile.c b/common/textfile.c index bb55109c..84a72b3c 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -143,8 +143,10 @@ static int write_key(const char *pathname, const char *key, const char *value) size = st.st_size; if (!size) { - pos = lseek(fd, size, SEEK_SET); - err = write_key_value(fd, key, value); + if (value) { + pos = lseek(fd, size, SEEK_SET); + err = write_key_value(fd, key, value); + } goto unlock; } -- cgit From 8fa8629fa44075dfa41b1bff96a7951dd40cfb0a Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 5 Apr 2006 14:03:53 +0000 Subject: added timeout new function --- common/glib-ectomy.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++- common/glib-ectomy.h | 27 +++++++- 2 files changed, 199 insertions(+), 3 deletions(-) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index 463d0aee..f1d79e7f 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -10,8 +10,11 @@ #include #include #include +#include +#include #include "glib-ectomy.h" +#include "list.h" GIOError g_io_channel_read(GIOChannel *channel, gchar *buf, gsize count, gsize *bytes_read) { @@ -89,6 +92,7 @@ struct watch { }; static struct watch watch_head = { .id = 0, .next = 0 }; +static GMainContext *default_context = NULL; void g_io_remove_watch(guint id) { @@ -129,6 +133,23 @@ guint g_io_add_watch(GIOChannel *channel, GIOCondition condition, func, user_data, NULL); } +static GMainContext *g_main_context_default() +{ + + if (default_context) + return default_context; + + default_context = malloc(sizeof(GMainContext)); + if (!default_context) + return NULL; + + memset(default_context, 0, sizeof(GMainContext)); + + default_context->timeout = -1; + + return default_context; +} + GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running) { GMainLoop *ml; @@ -137,11 +158,80 @@ GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running) if (!ml) return NULL; - ml->bail = 0; + memset(ml, 0, sizeof(GMainLoop)); + + if (!context) + ml->context = g_main_context_default(); + else + ml->context = context; + ml->bail = 0; return ml; } +static void timeout_handlers_prepare(GMainContext *context) +{ + struct slist *l = context->ltimeout; + struct timeout *t; + struct timeval tv; + glong msec, timeout = LONG_MAX; + + gettimeofday(&tv, NULL); + + while (l) { + t = l->data; + l = l->next; + + /* calculate the remainning time */ + msec = (t->expiration.tv_sec - tv.tv_sec) * 1000 + + (t->expiration.tv_usec - tv.tv_usec) / 1000; + if (msec < 0) + msec = 0; + + timeout = MIN_TIMEOUT(timeout, msec); + } + + /* set to min value found or NO timeout */ + context->timeout = (timeout != LONG_MAX ? timeout: -1); +} + +static void timeout_handlers_check(GMainContext *context) +{ + struct slist *l = context->ltimeout; + struct timeout *t; + struct timeval tv; + + gettimeofday(&tv, NULL); + + while (l) { + t = l->data; + l = l->next; + + if ((tv.tv_sec < t->expiration.tv_sec) || + (tv.tv_sec == t->expiration.tv_sec && + tv.tv_usec < t->expiration.tv_usec)) + continue; + + if (t->func(t->data)) { + /* if false/expired: remove it from the list */ + context->ltimeout = slist_remove(context->ltimeout, t); + free(t); + } else { + glong secs, msecs; + /* update the next expiration time */ + secs = t->interval / 1000; + msecs = t->interval - secs * 1000; + + t->expiration.tv_sec = tv.tv_sec + secs; + t->expiration.tv_usec = tv.tv_usec + msecs * 1000; + if (t->expiration.tv_usec >= 1000000) { + t->expiration.tv_usec -= 1000000; + t->expiration.tv_sec++; + } + } + } +} + void g_main_loop_run(GMainLoop *loop) { int open_max = sysconf(_SC_OPEN_MAX); @@ -163,7 +253,10 @@ void g_main_loop_run(GMainLoop *loop) nfds++; } - rc = poll(ufds, nfds, -1); + /* calculate the next timeout */ + timeout_handlers_prepare(loop->context); + + rc = poll(ufds, nfds, loop->context->timeout); if (rc < 0) continue; @@ -190,6 +283,9 @@ void g_main_loop_run(GMainLoop *loop) w = w->next; i++; } + + /* check expired timers */ + timeout_handlers_check(loop->context); } free(ufds); @@ -208,3 +304,78 @@ void g_main_loop_quit(GMainLoop *loop) free(w); } } + +void g_main_loop_unref(GMainLoop *loop) +{ + if (!loop->context) + return; + + slist_free(loop->context->ltimeout); + free(loop->context); +} + +guint g_timeout_add(guint interval, timeout_func_t *func, void *data) +{ + struct timeval tv; + guint secs; + guint msecs; + struct timeout *t; + + if (!default_context || !func) + return 0; + + t = malloc(sizeof(*t)); + + if (!t) + return 0; + + t->interval = interval; + t->func = func; + t->data = data; + + gettimeofday(&tv, NULL); + + secs = interval /1000; + msecs = interval - secs * 1000; + + t->expiration.tv_sec = tv.tv_sec + secs; + t->expiration.tv_usec = tv.tv_usec + msecs * 1000; + + if (t->expiration.tv_usec >= 1000000) { + t->expiration.tv_usec -= 1000000; + t->expiration.tv_sec++; + } + + /* attach the timeout the default context */ + t->id = ++default_context->next_id; + default_context->ltimeout = slist_append(default_context->ltimeout, t); + + return t->id; +} + +gint g_timeout_remove(const guint id) +{ + struct slist *l; + struct timeout *t; + + if (!default_context) + return -1; + + l = default_context->ltimeout; + + while (l) { + t = l->data; + l = l->next; + + if (t->id != id) + continue; + + default_context->ltimeout = slist_remove(default_context->ltimeout, t); + free(t); + + return 0; + } + + return -1; +} + diff --git a/common/glib-ectomy.h b/common/glib-ectomy.h index e921b40d..56dac08b 100644 --- a/common/glib-ectomy.h +++ b/common/glib-ectomy.h @@ -28,16 +28,36 @@ typedef ssize_t gssize; #define SSIZE_MAX INT_MAX #endif +#define MIN_TIMEOUT(a, b) (((a) < (b)) ? (a) : (b)) + typedef struct _GIOChannel { int fd; } GIOChannel; +typedef int (timeout_func_t)(void *data); + +typedef struct { + glong tv_sec; + glong tv_usec; +} time_val_t; + +struct timeout { + guint id; + guint interval; + time_val_t expiration; + void *data; + timeout_func_t *func; +}; + typedef struct _GMainContext { - int dummy; + guint next_id; + glong timeout; + struct slist *ltimeout; } GMainContext; typedef struct _GMainLoop { int bail; + GMainContext *context; } GMainLoop; typedef enum { @@ -89,9 +109,14 @@ void g_io_remove_watch(guint id); GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running); void g_main_loop_run(GMainLoop *loop); void g_main_loop_quit(GMainLoop *loop); +void g_main_loop_unref(GMainLoop *loop); +guint g_timeout_add(guint interval, timeout_func_t *func, void *data); +gint g_timeout_remove(const guint id); + #define g_main_new(is_running) g_main_loop_new(NULL, is_running); #define g_main_run(loop) g_main_loop_run(loop) #define g_main_quit(loop) g_main_loop_quit(loop) +#define g_main_unref(loop) g_main_loop_unref(loop) #endif /* __GLIB_ECTOMY_H */ -- cgit From 1f98ca9b57ecd36d032449972b7b9f006ad1e06f Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 10 Apr 2006 17:28:47 +0000 Subject: Fixed discoverable timeout and timeout list data memory leak --- common/glib-ectomy.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index f1d79e7f..7644fd18 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -133,6 +133,14 @@ guint g_io_add_watch(GIOChannel *channel, GIOCondition condition, func, user_data, NULL); } +static void timeout_free(void *data, void *user_data) +{ + struct timeout *t = data; + + if (t) + free (t); +} + static GMainContext *g_main_context_default() { @@ -310,6 +318,7 @@ void g_main_loop_unref(GMainLoop *loop) if (!loop->context) return; + slist_foreach(loop->context->ltimeout, timeout_free, NULL); slist_free(loop->context->ltimeout); free(loop->context); } -- cgit From d69f92a7657292734448903024f4236a94874dd8 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 28 Apr 2006 13:37:48 +0000 Subject: Fixed watch add/remove error --- common/glib-ectomy.c | 77 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 30 deletions(-) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index 7644fd18..16992e0f 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -84,26 +84,49 @@ struct watch { GIOChannel *channel; gint priority; GIOCondition condition; + short *revents; GIOFunc func; gpointer user_data; GDestroyNotify destroy; + struct watch *prev; struct watch *next; }; -static struct watch watch_head = { .id = 0, .next = 0 }; +static struct watch watch_head = { .id = 0, .prev = 0, .next = 0, .revents = 0 }; static GMainContext *default_context = NULL; +static void watch_remove(struct watch *w) +{ + struct watch *p, *n; + + if (!w) + return; + + p = w->prev; + n = w->next; + + if (p) + p->next = n; + + if (n) + n->prev = p; + + free(w); +} + void g_io_remove_watch(guint id) { - struct watch *w, *p; + struct watch *w, *n; - for (p = &watch_head, w = watch_head.next; w; p = w, w = w->next) - if (w->id == id) { - p->next = w->next; - free (w); - return; - } + for (w = watch_head.next; w; w = n) { + n = w->next; + if (w->id != id) + continue; + + watch_remove(w); + return; + } } guint g_io_add_watch_full(GIOChannel *channel, gint priority, @@ -120,7 +143,11 @@ guint g_io_add_watch_full(GIOChannel *channel, gint priority, watch->user_data = user_data; watch->destroy = notify; + watch->prev = 0; watch->next = watch_head.next; + if (watch_head.next) + watch_head.next->prev = watch; + watch_head.next = watch; return watch->id; @@ -250,14 +277,15 @@ void g_main_loop_run(GMainLoop *loop) return; while (!loop->bail) { - int nfds, rc, i; - struct watch *p, *w; + int nfds, rc; + struct watch *n, *w; nfds = 0; for (w = watch_head.next; w != NULL; w = w->next) { ufds[nfds].fd = w->channel->fd; ufds[nfds].events = w->condition; ufds[nfds].revents = 0; + w->revents = &ufds[nfds].revents; nfds++; } @@ -268,28 +296,17 @@ void g_main_loop_run(GMainLoop *loop) if (rc < 0) continue; - p = &watch_head; - w = watch_head.next; - i = 0; - - while (w) { - if (ufds[i].revents) { - gboolean keep = w->func(w->channel, ufds[i].revents, w->user_data); - if (!keep) { - if (w->destroy) - w->destroy(w->user_data); - p->next = w->next; - memset(w, 0, sizeof(*w)); - free(w); - w = p->next; - i++; + for (w = watch_head.next; w; w = n) { + n = w->next; + if (*w->revents) { + gboolean keep = w->func(w->channel, *w->revents, w->user_data); + if (keep) continue; - } - } - p = w; - w = w->next; - i++; + if (w->destroy) + w->destroy(w->user_data); + watch_remove(w); + } } /* check expired timers */ -- cgit From 3b7232c901f19c49451f5b4894d5c3be82c57d18 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 28 Apr 2006 23:29:18 +0000 Subject: Fix another watch remove bug --- common/glib-ectomy.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index 16992e0f..45f9ce0d 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -143,7 +143,7 @@ guint g_io_add_watch_full(GIOChannel *channel, gint priority, watch->user_data = user_data; watch->destroy = notify; - watch->prev = 0; + watch->prev = &watch_head; watch->next = watch_head.next; if (watch_head.next) watch_head.next->prev = watch; @@ -296,17 +296,20 @@ void g_main_loop_run(GMainLoop *loop) if (rc < 0) continue; - for (w = watch_head.next; w; w = n) { - n = w->next; - if (*w->revents) { - gboolean keep = w->func(w->channel, *w->revents, w->user_data); - if (keep) - continue; - - if (w->destroy) - w->destroy(w->user_data); - watch_remove(w); + w = watch_head.next; + while (w) { + if (!*w->revents || w->func(w->channel, *w->revents, w->user_data)) { + w = w->next; + continue; } + + n = w->next; + + if (w->destroy) + w->destroy(w->user_data); + watch_remove(w); + + w = n; } /* check expired timers */ @@ -405,3 +408,5 @@ gint g_timeout_remove(const guint id) return -1; } + + -- cgit From 7d573c7ae14bbbb2d924837413879c71f8c385f4 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 30 Apr 2006 20:40:25 +0000 Subject: Include header file --- common/textfile.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'common') diff --git a/common/textfile.c b/common/textfile.c index 84a72b3c..7814513a 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -36,6 +36,8 @@ #include #include +#include "textfile.h" + int create_dirs(const char *filename, const mode_t mode) { struct stat st; -- cgit From 44bb3977a6ba81cd5536b8e22ebfc767b80313f7 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 30 Apr 2006 20:45:34 +0000 Subject: Some small cleanups --- common/glib-ectomy.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index 45f9ce0d..d78b6172 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -94,6 +94,7 @@ struct watch { }; static struct watch watch_head = { .id = 0, .prev = 0, .next = 0, .revents = 0 }; + static GMainContext *default_context = NULL; static void watch_remove(struct watch *w) @@ -201,6 +202,7 @@ GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running) ml->context = context; ml->bail = 0; + return ml; } @@ -243,8 +245,8 @@ static void timeout_handlers_check(GMainContext *context) l = l->next; if ((tv.tv_sec < t->expiration.tv_sec) || - (tv.tv_sec == t->expiration.tv_sec && - tv.tv_usec < t->expiration.tv_usec)) + (tv.tv_sec == t->expiration.tv_sec && + tv.tv_usec < t->expiration.tv_usec)) continue; if (t->func(t->data)) { @@ -407,6 +409,3 @@ gint g_timeout_remove(const guint id) return -1; } - - - -- cgit From b96133c91a2abcc6b0a6de80176623f0ee6f600e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 4 Jun 2006 12:09:30 +0000 Subject: Build a generic helper library --- common/Makefile.am | 11 ++---- common/oui.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++ common/oui.h | 25 ++++++++++++ 3 files changed, 138 insertions(+), 7 deletions(-) create mode 100644 common/oui.c create mode 100644 common/oui.h (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index d2233f94..4ab7af66 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -1,14 +1,11 @@ -noinst_LIBRARIES = libtextfile.a libglib-ectomy.a liblist.a +noinst_LIBRARIES = libhelper.a -liblist_a_SOURCES = list.h list.c - -libtextfile_a_SOURCES = textfile.h textfile.c - -libglib_ectomy_a_SOURCES = glib-ectomy.h glib-ectomy.c +libhelper_a_SOURCES = oui.h oui.c list.h list.c \ + textfile.h textfile.c glib-ectomy.h glib-ectomy.c noinst_PROGRAMS = test_textfile -test_textfile_LDADD = libtextfile.a +test_textfile_LDADD = libhelper.a MAINTAINERCLEANFILES = Makefile.in diff --git a/common/oui.c b/common/oui.c new file mode 100644 index 00000000..cc695a90 --- /dev/null +++ b/common/oui.c @@ -0,0 +1,109 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2006 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "oui.h" + +/* http://standards.ieee.org/regauth/oui/oui.txt */ + +#define OUIFILE "/var/lib/misc/oui.txt" + +char *ouitocomp(const char *oui) +{ + struct stat st; + char *str, *map, *off, *end; + int fd; + + fd = open("oui.txt", O_RDONLY); + if (fd < 0) { + fd = open(OUIFILE, O_RDONLY); + if (fd < 0) { + fd = open("/usr/share/misc/oui.txt", O_RDONLY); + if (fd < 0) + return NULL; + } + } + + if (fstat(fd, &st) < 0) { + close(fd); + return NULL; + } + + str = malloc(128); + if (!str) { + close(fd); + return NULL; + } + + memset(str, 0, 128); + + map = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); + if (!map || map == MAP_FAILED) { + free(str); + close(fd); + return NULL; + } + + off = strstr(map, oui); + if (off) { + off += 18; + end = strpbrk(off, "\r\n"); + strncpy(str, off, end - off); + } else { + free(str); + str = NULL; + } + + munmap(map, st.st_size); + + close(fd); + + return str; +} + +int oui2comp(const char *oui, char *comp, size_t size) +{ + char *tmp; + + tmp = ouitocomp(oui); + if (!tmp) + return -1; + + snprintf(comp, size, "%s", tmp); + + free(tmp); + + return 0; +} diff --git a/common/oui.h b/common/oui.h new file mode 100644 index 00000000..c166038f --- /dev/null +++ b/common/oui.h @@ -0,0 +1,25 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2006 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +char *ouitocomp(const char *oui); +int oui2comp(const char *oui, char *comp, size_t size); -- cgit From 6370466ffd8daab036ed507ac6a99c27e3140c2e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 6 Jun 2006 00:22:54 +0000 Subject: Use GSourceFunc function type --- common/glib-ectomy.c | 9 ++++----- common/glib-ectomy.h | 7 +++---- 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index d78b6172..d5d4a611 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -171,7 +171,6 @@ static void timeout_free(void *data, void *user_data) static GMainContext *g_main_context_default() { - if (default_context) return default_context; @@ -249,7 +248,7 @@ static void timeout_handlers_check(GMainContext *context) tv.tv_usec < t->expiration.tv_usec)) continue; - if (t->func(t->data)) { + if (t->function(t->data)) { /* if false/expired: remove it from the list */ context->ltimeout = slist_remove(context->ltimeout, t); free(t); @@ -345,14 +344,14 @@ void g_main_loop_unref(GMainLoop *loop) free(loop->context); } -guint g_timeout_add(guint interval, timeout_func_t *func, void *data) +guint g_timeout_add(guint interval, GSourceFunc function, void *data) { struct timeval tv; guint secs; guint msecs; struct timeout *t; - if (!default_context || !func) + if (!default_context || !function) return 0; t = malloc(sizeof(*t)); @@ -361,7 +360,7 @@ guint g_timeout_add(guint interval, timeout_func_t *func, void *data) return 0; t->interval = interval; - t->func = func; + t->function = function; t->data = data; gettimeofday(&tv, NULL); diff --git a/common/glib-ectomy.h b/common/glib-ectomy.h index 56dac08b..18525f78 100644 --- a/common/glib-ectomy.h +++ b/common/glib-ectomy.h @@ -34,7 +34,7 @@ typedef struct _GIOChannel { int fd; } GIOChannel; -typedef int (timeout_func_t)(void *data); +typedef gboolean (*GSourceFunc) (gpointer data); typedef struct { glong tv_sec; @@ -46,7 +46,7 @@ struct timeout { guint interval; time_val_t expiration; void *data; - timeout_func_t *func; + GSourceFunc function; }; typedef struct _GMainContext { @@ -110,10 +110,9 @@ GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running); void g_main_loop_run(GMainLoop *loop); void g_main_loop_quit(GMainLoop *loop); void g_main_loop_unref(GMainLoop *loop); -guint g_timeout_add(guint interval, timeout_func_t *func, void *data); +guint g_timeout_add(guint interval, GSourceFunc function, void *data); gint g_timeout_remove(const guint id); - #define g_main_new(is_running) g_main_loop_new(NULL, is_running); #define g_main_run(loop) g_main_loop_run(loop) #define g_main_quit(loop) g_main_loop_quit(loop) -- cgit From 0ac46d20d06781d5af353272770bab6c244ea20b Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 6 Jun 2006 00:31:35 +0000 Subject: Add basic Bluetooth helper API --- common/Makefile.am | 3 ++- common/helper.c | 42 ++++++++++++++++++++++++++++++++++++++++++ common/helper.h | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 common/helper.c create mode 100644 common/helper.h (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index 4ab7af66..13752a04 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -2,7 +2,8 @@ noinst_LIBRARIES = libhelper.a libhelper_a_SOURCES = oui.h oui.c list.h list.c \ - textfile.h textfile.c glib-ectomy.h glib-ectomy.c + textfile.h textfile.c helper.h helper.c \ + glib-ectomy.h glib-ectomy.c noinst_PROGRAMS = test_textfile diff --git a/common/helper.c b/common/helper.c new file mode 100644 index 00000000..e3e997c8 --- /dev/null +++ b/common/helper.c @@ -0,0 +1,42 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2006 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "glib-ectomy.h" +#include "helper.h" + +int bt_timeout_add(int interval, bt_timeout_func_t function, void *data) +{ + return g_timeout_add(interval, function, data); +} + +int bt_timeout_remove(const int id) +{ + return g_timeout_remove(id); +} diff --git a/common/helper.h b/common/helper.h new file mode 100644 index 00000000..281ad6ee --- /dev/null +++ b/common/helper.h @@ -0,0 +1,32 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2006 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __HELPER_H +#define __HELPER_H + +typedef int (*bt_timeout_func_t) (void *data); + +int bt_timeout_add(int interval, bt_timeout_func_t function, void *data); +int bt_timeout_remove(const int id); + +#endif /* __HELPER_H */ -- cgit From efb24210a3a977fb7474700c37960b3d794793b6 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 6 Jun 2006 00:32:46 +0000 Subject: Use gpointer instead of void * --- common/glib-ectomy.c | 2 +- common/glib-ectomy.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index d5d4a611..dff48ef6 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -344,7 +344,7 @@ void g_main_loop_unref(GMainLoop *loop) free(loop->context); } -guint g_timeout_add(guint interval, GSourceFunc function, void *data) +guint g_timeout_add(guint interval, GSourceFunc function, gpointer data) { struct timeval tv; guint secs; diff --git a/common/glib-ectomy.h b/common/glib-ectomy.h index 18525f78..333687b1 100644 --- a/common/glib-ectomy.h +++ b/common/glib-ectomy.h @@ -45,7 +45,7 @@ struct timeout { guint id; guint interval; time_val_t expiration; - void *data; + gpointer data; GSourceFunc function; }; @@ -110,7 +110,7 @@ GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running); void g_main_loop_run(GMainLoop *loop); void g_main_loop_quit(GMainLoop *loop); void g_main_loop_unref(GMainLoop *loop); -guint g_timeout_add(guint interval, GSourceFunc function, void *data); +guint g_timeout_add(guint interval, GSourceFunc function, gpointer data); gint g_timeout_remove(const guint id); #define g_main_new(is_running) g_main_loop_new(NULL, is_running); -- cgit From a13cbac6d61e4696941a747b376a93bbcffda1a2 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 30 Jun 2006 18:59:27 +0000 Subject: Fixed timeout for pending reply --- common/glib-ectomy.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index dff48ef6..aa1007ee 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -231,6 +231,11 @@ static void timeout_handlers_prepare(GMainContext *context) context->timeout = (timeout != LONG_MAX ? timeout: -1); } +static int timeout_cmp(const void *t1, const void *t2) +{ + return t1-t2; +} + static void timeout_handlers_check(GMainContext *context) { struct slist *l = context->ltimeout; @@ -249,9 +254,17 @@ static void timeout_handlers_check(GMainContext *context) continue; if (t->function(t->data)) { - /* if false/expired: remove it from the list */ - context->ltimeout = slist_remove(context->ltimeout, t); - free(t); + struct slist *match; + /* if false/expired: remove it from the list + * Before remove check again in order to cover the situation + * when the handler is removed/freed by the callback function + */ + match = slist_find(context->ltimeout, t, timeout_cmp); + if (match) { + t = match->data; + context->ltimeout = slist_remove(context->ltimeout, t); + free(t); + } } else { glong secs, msecs; /* update the next expiration time */ -- cgit From f616523e5cdc65726d36dad404ed2f66a2fc8fd8 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 26 Jul 2006 12:53:48 +0000 Subject: Check return values of write() and ftruncate() --- common/textfile.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'common') diff --git a/common/textfile.c b/common/textfile.c index 7814513a..cdb42d13 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -182,10 +182,14 @@ static int write_key(const char *pathname, const char *key, const char *value) len = size - (end - map); if (!len) { munmap(map, size); - ftruncate(fd, base); + if (ftruncate(fd, base) < 0) { + err = errno; + goto unlock; + } pos = lseek(fd, base, SEEK_SET); if (value) err = write_key_value(fd, key, value); + goto unlock; } @@ -203,12 +207,16 @@ static int write_key(const char *pathname, const char *key, const char *value) memcpy(str, end, len); munmap(map, size); - ftruncate(fd, base); + if (ftruncate(fd, base) < 0) { + err = errno; + goto unlock; + } pos = lseek(fd, base, SEEK_SET); if (value) err = write_key_value(fd, key, value); - write(fd, str, len); + if (write(fd, str, len) < 0) + err = errno; free(str); -- cgit From ab767dcf7cf79a3411a5199b97b42e97ef80dbfc Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 26 Jul 2006 12:58:09 +0000 Subject: Add create_name() helper function --- common/textfile.c | 5 +++++ common/textfile.h | 1 + 2 files changed, 6 insertions(+) (limited to 'common') diff --git a/common/textfile.c b/common/textfile.c index cdb42d13..076ec35b 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -88,6 +88,11 @@ int create_file(const char *filename, const mode_t mode) return 0; } +int create_name(char *buf, size_t size, char *address, char *name) +{ + return snprintf(buf, size, "%s/%s/%s", STORAGEDIR, address, name); +} + static inline char *find_key(char *map, const char *key, size_t len) { char *off = strstr(map, key); diff --git a/common/textfile.h b/common/textfile.h index b9c01ad3..21aa023d 100644 --- a/common/textfile.h +++ b/common/textfile.h @@ -26,6 +26,7 @@ int create_dirs(const char *filename, const mode_t mode); int create_file(const char *filename, const mode_t mode); +int create_name(char *buf, size_t size, char *address, char *name); int textfile_put(const char *pathname, const char *key, const char *value); int textfile_del(const char *pathname, const char *key); -- cgit From 86d19dcfa04879c863a1248851cd7854b68242cb Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 26 Jul 2006 13:03:13 +0000 Subject: Add a paramter for the path to create_name() --- common/textfile.c | 4 ++-- common/textfile.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'common') diff --git a/common/textfile.c b/common/textfile.c index 076ec35b..f8b9545e 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -88,9 +88,9 @@ int create_file(const char *filename, const mode_t mode) return 0; } -int create_name(char *buf, size_t size, char *address, char *name) +int create_name(char *buf, size_t size, const char *path, const char *address, const char *name) { - return snprintf(buf, size, "%s/%s/%s", STORAGEDIR, address, name); + return snprintf(buf, size, "%s/%s/%s", path, address, name); } static inline char *find_key(char *map, const char *key, size_t len) diff --git a/common/textfile.h b/common/textfile.h index 21aa023d..74e67eca 100644 --- a/common/textfile.h +++ b/common/textfile.h @@ -26,7 +26,8 @@ int create_dirs(const char *filename, const mode_t mode); int create_file(const char *filename, const mode_t mode); -int create_name(char *buf, size_t size, char *address, char *name); +int create_name(char *buf, size_t size, const char *path, + const char *address, const char *name); int textfile_put(const char *pathname, const char *key, const char *value); int textfile_del(const char *pathname, const char *key); -- cgit From 3c6404cd942f3b69968a390fae2a57dd2980e21a Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Sat, 5 Aug 2006 21:36:31 +0000 Subject: fixed message reply timeout --- common/glib-ectomy.c | 16 ++++++++++++---- common/glib-ectomy.h | 7 +------ 2 files changed, 13 insertions(+), 10 deletions(-) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index aa1007ee..fb737642 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -233,7 +233,16 @@ static void timeout_handlers_prepare(GMainContext *context) static int timeout_cmp(const void *t1, const void *t2) { - return t1-t2; + const struct timeout *tout1 = t1; + const struct timeout *tout2 = t2; + + if (!tout2) + return -1; + + if (tout1 != tout2) + return -1; + + return tout1->id - tout2->id; } static void timeout_handlers_check(GMainContext *context) @@ -248,9 +257,7 @@ static void timeout_handlers_check(GMainContext *context) t = l->data; l = l->next; - if ((tv.tv_sec < t->expiration.tv_sec) || - (tv.tv_sec == t->expiration.tv_sec && - tv.tv_usec < t->expiration.tv_usec)) + if (timercmp(&tv, &t->expiration, <)) continue; if (t->function(t->data)) { @@ -372,6 +379,7 @@ guint g_timeout_add(guint interval, GSourceFunc function, gpointer data) if (!t) return 0; + memset(t, 0, sizeof(*t)); t->interval = interval; t->function = function; t->data = data; diff --git a/common/glib-ectomy.h b/common/glib-ectomy.h index 333687b1..f52a9ce2 100644 --- a/common/glib-ectomy.h +++ b/common/glib-ectomy.h @@ -36,15 +36,10 @@ typedef struct _GIOChannel { typedef gboolean (*GSourceFunc) (gpointer data); -typedef struct { - glong tv_sec; - glong tv_usec; -} time_val_t; - struct timeout { guint id; guint interval; - time_val_t expiration; + struct timeval expiration; gpointer data; GSourceFunc function; }; -- cgit From a1bc48d15a5d6e78efe744eb7b27b6421cb7222f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 16 Aug 2006 10:54:06 +0000 Subject: Convert to using ppoll() and pselect() --- common/ppoll.h | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 common/ppoll.h (limited to 'common') diff --git a/common/ppoll.h b/common/ppoll.h new file mode 100644 index 00000000..6d84a2e8 --- /dev/null +++ b/common/ppoll.h @@ -0,0 +1,5 @@ +static inline int ppoll(struct pollfd *fds, nfds_t nfds, + const struct timespec *timeout, const sigset_t *sigmask) +{ + return poll(fds, nfds, timeout ? timeout->tv_sec * 1000 : 500); +} -- cgit From be52c05a25c0cbadcd605b24d66d0c0b682aee18 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 20 Aug 2006 19:05:10 +0000 Subject: First round of Passkey Release method support --- common/glib-ectomy.c | 18 +++++++----------- common/list.c | 10 ++++++++++ common/list.h | 2 ++ 3 files changed, 19 insertions(+), 11 deletions(-) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index fb737642..214ee571 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -161,14 +161,6 @@ guint g_io_add_watch(GIOChannel *channel, GIOCondition condition, func, user_data, NULL); } -static void timeout_free(void *data, void *user_data) -{ - struct timeout *t = data; - - if (t) - free (t); -} - static GMainContext *g_main_context_default() { if (default_context) @@ -342,16 +334,19 @@ void g_main_loop_run(GMainLoop *loop) void g_main_loop_quit(GMainLoop *loop) { - struct watch *w; + struct watch *w, *next; loop->bail = 1; - for (w = watch_head.next; w; w = w->next) { + for (w = watch_head.next; w; w = next) { + next = w->next; if (w->destroy) w->destroy(w->user_data); watch_head.next = w->next; free(w); } + + watch_head.next = NULL; } void g_main_loop_unref(GMainLoop *loop) @@ -359,9 +354,10 @@ void g_main_loop_unref(GMainLoop *loop) if (!loop->context) return; - slist_foreach(loop->context->ltimeout, timeout_free, NULL); + slist_foreach(loop->context->ltimeout, (slist_func_t)free, NULL); slist_free(loop->context->ltimeout); free(loop->context); + loop->context = NULL; } guint g_timeout_add(guint interval, GSourceFunc function, gpointer data) diff --git a/common/list.c b/common/list.c index 31ae9d35..42d377b7 100644 --- a/common/list.c +++ b/common/list.c @@ -99,6 +99,16 @@ struct slist *slist_find(struct slist *list, const void *data, return NULL; } +int slist_length(struct slist *list) +{ + int len; + + for (len = 0; list != NULL; list = list->next) + len++; + + return len; +} + void slist_foreach(struct slist *list, slist_func_t func, void *user_data) { while (list) { diff --git a/common/list.h b/common/list.h index 026d470c..c43756a9 100644 --- a/common/list.h +++ b/common/list.h @@ -40,6 +40,8 @@ struct slist *slist_remove(struct slist *list, void *data); struct slist *slist_find(struct slist *list, const void *data, cmp_func_t cmp_func); +int slist_length(struct slist *list); + void slist_foreach(struct slist *list, slist_func_t func, void *user_data); void slist_free(struct slist *list); -- cgit From ec3ac41ca8876f36cc8869ab1c384980f793c40f Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 20 Aug 2006 21:41:59 +0000 Subject: Preliminary support for passkey agent timeouts --- common/glib-ectomy.c | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index 214ee571..f90973ba 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -225,16 +225,7 @@ static void timeout_handlers_prepare(GMainContext *context) static int timeout_cmp(const void *t1, const void *t2) { - const struct timeout *tout1 = t1; - const struct timeout *tout2 = t2; - - if (!tout2) - return -1; - - if (tout1 != tout2) - return -1; - - return tout1->id - tout2->id; + return t1 - t2; } static void timeout_handlers_check(GMainContext *context) @@ -246,24 +237,30 @@ static void timeout_handlers_check(GMainContext *context) gettimeofday(&tv, NULL); while (l) { + struct slist *match; + gboolean ret; + t = l->data; l = l->next; if (timercmp(&tv, &t->expiration, <)) continue; - if (t->function(t->data)) { - struct slist *match; - /* if false/expired: remove it from the list - * Before remove check again in order to cover the situation - * when the handler is removed/freed by the callback function - */ - match = slist_find(context->ltimeout, t, timeout_cmp); - if (match) { - t = match->data; - context->ltimeout = slist_remove(context->ltimeout, t); - free(t); - } + ret = t->function(t->data); + + /* Check if the handler was removed/freed by the callback + * function */ + match = slist_find(context->ltimeout, t, timeout_cmp); + + if (!match) + continue; + + /* Update next pointer if callback changed the list */ + l = match->next; + + if (ret == FALSE) { + context->ltimeout = slist_remove(context->ltimeout, t); + free(t); } else { glong secs, msecs; /* update the next expiration time */ -- cgit From d93952ad4b8e6ae7e212037ed1b37940560e814c Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 20 Aug 2006 22:31:34 +0000 Subject: Fix processing of the timeout list in GMainContext --- common/glib-ectomy.c | 65 ++++++++++++++++++++++++++++++++++------------------ common/glib-ectomy.h | 1 + 2 files changed, 44 insertions(+), 22 deletions(-) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index f90973ba..f4e552cd 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -230,21 +230,26 @@ static int timeout_cmp(const void *t1, const void *t2) static void timeout_handlers_check(GMainContext *context) { - struct slist *l = context->ltimeout; struct timeout *t; struct timeval tv; gettimeofday(&tv, NULL); - while (l) { + context->processed = NULL; + + while (context->ltimeout) { struct slist *match; + glong secs, msecs; gboolean ret; - t = l->data; - l = l->next; + t = context->ltimeout->data; + + context->ltimeout = slist_remove(context->ltimeout, t); - if (timercmp(&tv, &t->expiration, <)) + if (timercmp(&tv, &t->expiration, <)) { + context->processed = slist_append(context->processed, t); continue; + } ret = t->function(t->data); @@ -255,26 +260,27 @@ static void timeout_handlers_check(GMainContext *context) if (!match) continue; - /* Update next pointer if callback changed the list */ - l = match->next; - - if (ret == FALSE) { - context->ltimeout = slist_remove(context->ltimeout, t); + if (!ret) { free(t); - } else { - glong secs, msecs; - /* update the next expiration time */ - secs = t->interval / 1000; - msecs = t->interval - secs * 1000; - - t->expiration.tv_sec = tv.tv_sec + secs; - t->expiration.tv_usec = tv.tv_usec + msecs * 1000; - if (t->expiration.tv_usec >= 1000000) { - t->expiration.tv_usec -= 1000000; - t->expiration.tv_sec++; - } + continue; } + + /* update the next expiration time */ + secs = t->interval / 1000; + msecs = t->interval - secs * 1000; + + t->expiration.tv_sec = tv.tv_sec + secs; + t->expiration.tv_usec = tv.tv_usec + msecs * 1000; + if (t->expiration.tv_usec >= 1000000) { + t->expiration.tv_usec -= 1000000; + t->expiration.tv_sec++; + } + + context->processed = slist_append(context->processed, t); } + + context->ltimeout = context->processed; + context->processed = NULL; } void g_main_loop_run(GMainLoop *loop) @@ -420,5 +426,20 @@ gint g_timeout_remove(const guint id) return 0; } + l = default_context->processed; + + while (l) { + t = l->data; + l = l->next; + + if (t->id != id) + continue; + + default_context->processed = slist_remove(default_context->processed, t); + free(t); + + return 0; + } + return -1; } diff --git a/common/glib-ectomy.h b/common/glib-ectomy.h index f52a9ce2..af6f4fbb 100644 --- a/common/glib-ectomy.h +++ b/common/glib-ectomy.h @@ -48,6 +48,7 @@ typedef struct _GMainContext { guint next_id; glong timeout; struct slist *ltimeout; + struct slist *processed; } GMainContext; typedef struct _GMainLoop { -- cgit From 9b19d37cb9c41546648fd5eee81fff46e78f871c Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 20 Aug 2006 22:37:43 +0000 Subject: A little code cleanup --- common/glib-ectomy.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index f4e552cd..2f674cbc 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -238,7 +238,6 @@ static void timeout_handlers_check(GMainContext *context) context->processed = NULL; while (context->ltimeout) { - struct slist *match; glong secs, msecs; gboolean ret; @@ -255,9 +254,7 @@ static void timeout_handlers_check(GMainContext *context) /* Check if the handler was removed/freed by the callback * function */ - match = slist_find(context->ltimeout, t, timeout_cmp); - - if (!match) + if (!slist_find(context->ltimeout, t, timeout_cmp)) continue; if (!ret) { -- cgit From 82983e4f406d388b5219a496de7b0cf0c71d0570 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 21 Aug 2006 06:03:58 +0000 Subject: Leave timeout in context->ltimeouts list before calling the callback --- common/glib-ectomy.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index 2f674cbc..6bbee3f1 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -243,9 +243,8 @@ static void timeout_handlers_check(GMainContext *context) t = context->ltimeout->data; - context->ltimeout = slist_remove(context->ltimeout, t); - if (timercmp(&tv, &t->expiration, <)) { + context->ltimeout = slist_remove(context->ltimeout, t); context->processed = slist_append(context->processed, t); continue; } @@ -257,6 +256,8 @@ static void timeout_handlers_check(GMainContext *context) if (!slist_find(context->ltimeout, t, timeout_cmp)) continue; + context->ltimeout = slist_remove(context->ltimeout, t); + if (!ret) { free(t); continue; -- cgit From 1ae4a800cdffe7349c92f11c577958642ead7de7 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 22 Aug 2006 04:40:25 +0000 Subject: Include ppoll.h into the distribution --- common/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index 13752a04..30211fab 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -9,4 +9,6 @@ noinst_PROGRAMS = test_textfile test_textfile_LDADD = libhelper.a +EXTRA_DIST = ppoll.h + MAINTAINERCLEANFILES = Makefile.in -- cgit From dbe289f011a9ecedf0f4cabb9f25c9564c8aa830 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 25 Aug 2006 13:17:24 +0000 Subject: Fix and cleanup watch functionality --- common/glib-ectomy.c | 252 ++++++++++++++++++++++++++++++--------------------- common/glib-ectomy.h | 22 +---- common/list.c | 15 +++ common/list.h | 2 + 4 files changed, 169 insertions(+), 122 deletions(-) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index 6bbee3f1..9566d936 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -13,8 +13,34 @@ #include #include -#include "glib-ectomy.h" #include "list.h" +#include "glib-ectomy.h" + +struct timeout { + guint id; + guint interval; + struct timeval expiration; + gpointer data; + GSourceFunc function; +}; + +struct _GMainContext { + guint next_id; + glong next_timeout; + + struct slist *timeouts; + struct slist *proc_timeouts; + gboolean timeout_lock; + + struct slist *watches; + struct slist *proc_watches; + gboolean watch_lock; +}; + +struct _GMainLoop { + int bail; + GMainContext *context; +}; GIOError g_io_channel_read(GIOChannel *channel, gchar *buf, gsize count, gsize *bytes_read) { @@ -88,55 +114,82 @@ struct watch { GIOFunc func; gpointer user_data; GDestroyNotify destroy; - - struct watch *prev; - struct watch *next; }; -static struct watch watch_head = { .id = 0, .prev = 0, .next = 0, .revents = 0 }; - static GMainContext *default_context = NULL; -static void watch_remove(struct watch *w) +static void watch_free(struct watch *watch) { - struct watch *p, *n; + if (watch->destroy) + watch->destroy(watch->user_data); + free(watch); +} - if (!w) +void g_io_remove_watch(guint id) +{ + struct slist *l; + struct watch *w; + + if (!default_context) return; - p = w->prev; - n = w->next; + for (l = default_context->watches; l != NULL; l = l->next) { + w = l->data; - if (p) - p->next = n; + if (w->id != id) + continue; - if (n) - n->prev = p; + default_context->watches = slist_remove(default_context->watches, w); + watch_free(w); - free(w); -} + return; + } -void g_io_remove_watch(guint id) -{ - struct watch *w, *n; + for (l = default_context->proc_watches; l != NULL; l = l->next) { + w = l->data; - for (w = watch_head.next; w; w = n) { - n = w->next; if (w->id != id) continue; - watch_remove(w); + default_context->proc_watches = slist_remove(default_context->proc_watches, w); + watch_free(w); + return; } } +static GMainContext *g_main_context_default() +{ + if (default_context) + return default_context; + + default_context = malloc(sizeof(GMainContext)); + if (!default_context) + return NULL; + + memset(default_context, 0, sizeof(GMainContext)); + + default_context->next_timeout = -1; + default_context->next_id = 1; + + return default_context; +} + guint g_io_add_watch_full(GIOChannel *channel, gint priority, GIOCondition condition, GIOFunc func, gpointer user_data, GDestroyNotify notify) { - struct watch *watch = malloc(sizeof(struct watch)); + struct watch *watch; + GMainContext *context = g_main_context_default(); - watch->id = ++watch_head.id; + if (!context) + return 0; + + watch = malloc(sizeof(struct watch)); + if (!watch) + return 0; + + watch->id = context->next_id++; watch->channel = channel; watch->priority = priority; watch->condition = condition; @@ -144,12 +197,10 @@ guint g_io_add_watch_full(GIOChannel *channel, gint priority, watch->user_data = user_data; watch->destroy = notify; - watch->prev = &watch_head; - watch->next = watch_head.next; - if (watch_head.next) - watch_head.next->prev = watch; - - watch_head.next = watch; + if (context->watch_lock) + context->proc_watches = slist_prepend(context->proc_watches, watch); + else + context->watches = slist_prepend(context->watches, watch); return watch->id; } @@ -161,22 +212,6 @@ guint g_io_add_watch(GIOChannel *channel, GIOCondition condition, func, user_data, NULL); } -static GMainContext *g_main_context_default() -{ - if (default_context) - return default_context; - - default_context = malloc(sizeof(GMainContext)); - if (!default_context) - return NULL; - - memset(default_context, 0, sizeof(GMainContext)); - - default_context->timeout = -1; - - return default_context; -} - GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running) { GMainLoop *ml; @@ -199,16 +234,14 @@ GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running) static void timeout_handlers_prepare(GMainContext *context) { - struct slist *l = context->ltimeout; - struct timeout *t; + struct slist *l; struct timeval tv; glong msec, timeout = LONG_MAX; gettimeofday(&tv, NULL); - while (l) { - t = l->data; - l = l->next; + for (l = context->timeouts; l != NULL; l = l->next) { + struct timeout *t = l->data; /* calculate the remainning time */ msec = (t->expiration.tv_sec - tv.tv_sec) * 1000 + @@ -220,32 +253,30 @@ static void timeout_handlers_prepare(GMainContext *context) } /* set to min value found or NO timeout */ - context->timeout = (timeout != LONG_MAX ? timeout: -1); + context->next_timeout = (timeout != LONG_MAX ? timeout : -1); } -static int timeout_cmp(const void *t1, const void *t2) +static int ptr_cmp(const void *t1, const void *t2) { return t1 - t2; } static void timeout_handlers_check(GMainContext *context) { - struct timeout *t; struct timeval tv; gettimeofday(&tv, NULL); - context->processed = NULL; + context->timeout_lock = TRUE; - while (context->ltimeout) { + while (context->timeouts) { + struct timeout *t = context->timeouts->data; glong secs, msecs; gboolean ret; - t = context->ltimeout->data; - if (timercmp(&tv, &t->expiration, <)) { - context->ltimeout = slist_remove(context->ltimeout, t); - context->processed = slist_append(context->processed, t); + context->timeouts = slist_remove(context->timeouts, t); + context->proc_timeouts = slist_append(context->proc_timeouts, t); continue; } @@ -253,10 +284,10 @@ static void timeout_handlers_check(GMainContext *context) /* Check if the handler was removed/freed by the callback * function */ - if (!slist_find(context->ltimeout, t, timeout_cmp)) + if (!slist_find(context->timeouts, t, ptr_cmp)) continue; - context->ltimeout = slist_remove(context->ltimeout, t); + context->timeouts = slist_remove(context->timeouts, t); if (!ret) { free(t); @@ -274,58 +305,77 @@ static void timeout_handlers_check(GMainContext *context) t->expiration.tv_sec++; } - context->processed = slist_append(context->processed, t); + context->proc_timeouts = slist_append(context->proc_timeouts, t); } - context->ltimeout = context->processed; - context->processed = NULL; + context->timeouts = context->proc_timeouts; + context->proc_timeouts = NULL; + context->timeout_lock = FALSE; } void g_main_loop_run(GMainLoop *loop) { int open_max = sysconf(_SC_OPEN_MAX); struct pollfd *ufds; + GMainContext *context = loop->context; ufds = malloc(open_max * sizeof(struct pollfd)); if (!ufds) return; while (!loop->bail) { - int nfds, rc; - struct watch *n, *w; + int nfds; + struct slist *l; + struct watch *w; - nfds = 0; - for (w = watch_head.next; w != NULL; w = w->next) { + for (nfds = 0, l = context->watches; l != NULL; l = l->next, nfds++) { + w = l->data; ufds[nfds].fd = w->channel->fd; ufds[nfds].events = w->condition; ufds[nfds].revents = 0; w->revents = &ufds[nfds].revents; - nfds++; } /* calculate the next timeout */ - timeout_handlers_prepare(loop->context); + timeout_handlers_prepare(context); - rc = poll(ufds, nfds, loop->context->timeout); - if (rc < 0) + if (poll(ufds, nfds, context->next_timeout) < 0) continue; - w = watch_head.next; - while (w) { - if (!*w->revents || w->func(w->channel, *w->revents, w->user_data)) { - w = w->next; + context->watch_lock = TRUE; + + while (context->watches) { + gboolean ret; + + w = context->watches->data; + + if (!*w->revents) { + context->watches = slist_remove(context->watches, w); + context->proc_watches = slist_append(context->proc_watches, w); continue; } - n = w->next; + ret = w->func(w->channel, *w->revents, w->user_data); + + /* Check if the watch was removed/freed by the callback + * function */ + if (!slist_find(context->watches, w, ptr_cmp)) + continue; - if (w->destroy) - w->destroy(w->user_data); - watch_remove(w); + context->watches = slist_remove(context->watches, w); - w = n; + if (!ret) { + watch_free(w); + continue; + } + + context->proc_watches = slist_append(context->proc_watches, w); } + context->watches = context->proc_watches; + context->proc_watches = NULL; + context->watch_lock = FALSE; + /* check expired timers */ timeout_handlers_check(loop->context); } @@ -335,19 +385,7 @@ void g_main_loop_run(GMainLoop *loop) void g_main_loop_quit(GMainLoop *loop) { - struct watch *w, *next; - loop->bail = 1; - - for (w = watch_head.next; w; w = next) { - next = w->next; - if (w->destroy) - w->destroy(w->user_data); - watch_head.next = w->next; - free(w); - } - - watch_head.next = NULL; } void g_main_loop_unref(GMainLoop *loop) @@ -355,8 +393,12 @@ void g_main_loop_unref(GMainLoop *loop) if (!loop->context) return; - slist_foreach(loop->context->ltimeout, (slist_func_t)free, NULL); - slist_free(loop->context->ltimeout); + slist_foreach(loop->context->watches, (slist_func_t)watch_free, NULL); + slist_free(loop->context->watches); + + slist_foreach(loop->context->timeouts, (slist_func_t)free, NULL); + slist_free(loop->context->timeouts); + free(loop->context); loop->context = NULL; } @@ -395,8 +437,12 @@ guint g_timeout_add(guint interval, GSourceFunc function, gpointer data) } /* attach the timeout the default context */ - t->id = ++default_context->next_id; - default_context->ltimeout = slist_append(default_context->ltimeout, t); + t->id = default_context->next_id++; + + if (default_context->timeout_lock) + default_context->proc_timeouts = slist_prepend(default_context->proc_timeouts, t); + else + default_context->timeouts = slist_prepend(default_context->timeouts, t); return t->id; } @@ -409,7 +455,7 @@ gint g_timeout_remove(const guint id) if (!default_context) return -1; - l = default_context->ltimeout; + l = default_context->timeouts; while (l) { t = l->data; @@ -418,13 +464,13 @@ gint g_timeout_remove(const guint id) if (t->id != id) continue; - default_context->ltimeout = slist_remove(default_context->ltimeout, t); + default_context->timeouts = slist_remove(default_context->timeouts, t); free(t); return 0; } - l = default_context->processed; + l = default_context->proc_timeouts; while (l) { t = l->data; @@ -433,7 +479,7 @@ gint g_timeout_remove(const guint id) if (t->id != id) continue; - default_context->processed = slist_remove(default_context->processed, t); + default_context->proc_timeouts = slist_remove(default_context->proc_timeouts, t); free(t); return 0; diff --git a/common/glib-ectomy.h b/common/glib-ectomy.h index af6f4fbb..16f4810d 100644 --- a/common/glib-ectomy.h +++ b/common/glib-ectomy.h @@ -36,25 +36,9 @@ typedef struct _GIOChannel { typedef gboolean (*GSourceFunc) (gpointer data); -struct timeout { - guint id; - guint interval; - struct timeval expiration; - gpointer data; - GSourceFunc function; -}; - -typedef struct _GMainContext { - guint next_id; - glong timeout; - struct slist *ltimeout; - struct slist *processed; -} GMainContext; - -typedef struct _GMainLoop { - int bail; - GMainContext *context; -} GMainLoop; +typedef struct _GMainContext GMainContext; + +typedef struct _GMainLoop GMainLoop; typedef enum { G_IO_ERROR_NONE, diff --git a/common/list.c b/common/list.c index 42d377b7..a887bcdd 100644 --- a/common/list.c +++ b/common/list.c @@ -55,6 +55,21 @@ struct slist *slist_append(struct slist *list, void *data) return list; } +struct slist *slist_prepend(struct slist *list, void *data) +{ + struct slist *entry; + + entry = malloc(sizeof(struct slist)); + /* FIXME: this currently just silently fails */ + if (!entry) + return list; + + entry->data = data; + entry->next = list; + + return entry; +} + struct slist *slist_remove(struct slist *list, void *data) { struct slist *l, *next, *prev = NULL, *match = NULL; diff --git a/common/list.h b/common/list.h index c43756a9..1b502110 100644 --- a/common/list.h +++ b/common/list.h @@ -35,6 +35,8 @@ typedef void (*slist_func_t)(void *data, void *user_data); struct slist *slist_append(struct slist *list, void *data); +struct slist *slist_prepend(struct slist *list, void *data); + struct slist *slist_remove(struct slist *list, void *data); struct slist *slist_find(struct slist *list, const void *data, -- cgit From 448146fdeb6a90cdf11826fcdc88ce9068eb9646 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sat, 26 Aug 2006 13:40:11 +0000 Subject: More cleanups to glib-ectomy.c --- common/glib-ectomy.c | 89 ++++++++++++++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 41 deletions(-) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index 9566d936..41641ee6 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -38,7 +38,7 @@ struct _GMainContext { }; struct _GMainLoop { - int bail; + gboolean is_running; GMainContext *context; }; @@ -125,56 +125,57 @@ static void watch_free(struct watch *watch) free(watch); } +static GMainContext *g_main_context_default() +{ + if (default_context) + return default_context; + + default_context = malloc(sizeof(GMainContext)); + if (!default_context) + return NULL; + + memset(default_context, 0, sizeof(GMainContext)); + + default_context->next_timeout = -1; + default_context->next_id = 1; + + return default_context; +} + void g_io_remove_watch(guint id) { + GMainContext *context = g_main_context_default(); struct slist *l; struct watch *w; - if (!default_context) + if (!context) return; - for (l = default_context->watches; l != NULL; l = l->next) { + for (l = context->watches; l != NULL; l = l->next) { w = l->data; if (w->id != id) continue; - default_context->watches = slist_remove(default_context->watches, w); + context->watches = slist_remove(context->watches, w); watch_free(w); return; } - for (l = default_context->proc_watches; l != NULL; l = l->next) { + for (l = context->proc_watches; l != NULL; l = l->next) { w = l->data; if (w->id != id) continue; - default_context->proc_watches = slist_remove(default_context->proc_watches, w); + context->proc_watches = slist_remove(context->proc_watches, w); watch_free(w); return; } } -static GMainContext *g_main_context_default() -{ - if (default_context) - return default_context; - - default_context = malloc(sizeof(GMainContext)); - if (!default_context) - return NULL; - - memset(default_context, 0, sizeof(GMainContext)); - - default_context->next_timeout = -1; - default_context->next_id = 1; - - return default_context; -} - guint g_io_add_watch_full(GIOChannel *channel, gint priority, GIOCondition condition, GIOFunc func, gpointer user_data, GDestroyNotify notify) @@ -216,18 +217,20 @@ GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running) { GMainLoop *ml; + if (!context) + context = g_main_context_default(); + + if (!context) + return NULL; + ml = malloc(sizeof(GMainLoop)); if (!ml) return NULL; memset(ml, 0, sizeof(GMainLoop)); - if (!context) - ml->context = g_main_context_default(); - else - ml->context = context; - - ml->bail = 0; + ml->context = context; + ml->is_running = is_running; return ml; } @@ -323,7 +326,9 @@ void g_main_loop_run(GMainLoop *loop) if (!ufds) return; - while (!loop->bail) { + loop->is_running = TRUE; + + while (loop->is_running) { int nfds; struct slist *l; struct watch *w; @@ -385,7 +390,7 @@ void g_main_loop_run(GMainLoop *loop) void g_main_loop_quit(GMainLoop *loop) { - loop->bail = 1; + loop->is_running = FALSE; } void g_main_loop_unref(GMainLoop *loop) @@ -405,12 +410,13 @@ void g_main_loop_unref(GMainLoop *loop) guint g_timeout_add(guint interval, GSourceFunc function, gpointer data) { + GMainContext *context = g_main_context_default(); struct timeval tv; guint secs; guint msecs; struct timeout *t; - if (!default_context || !function) + if (!context || !function) return 0; t = malloc(sizeof(*t)); @@ -437,25 +443,26 @@ guint g_timeout_add(guint interval, GSourceFunc function, gpointer data) } /* attach the timeout the default context */ - t->id = default_context->next_id++; + t->id = context->next_id++; - if (default_context->timeout_lock) - default_context->proc_timeouts = slist_prepend(default_context->proc_timeouts, t); + if (context->timeout_lock) + context->proc_timeouts = slist_prepend(context->proc_timeouts, t); else - default_context->timeouts = slist_prepend(default_context->timeouts, t); + context->timeouts = slist_prepend(context->timeouts, t); return t->id; } gint g_timeout_remove(const guint id) { + GMainContext *context = g_main_context_default(); struct slist *l; struct timeout *t; - if (!default_context) + if (!context) return -1; - l = default_context->timeouts; + l = context->timeouts; while (l) { t = l->data; @@ -464,13 +471,13 @@ gint g_timeout_remove(const guint id) if (t->id != id) continue; - default_context->timeouts = slist_remove(default_context->timeouts, t); + context->timeouts = slist_remove(context->timeouts, t); free(t); return 0; } - l = default_context->proc_timeouts; + l = context->proc_timeouts; while (l) { t = l->data; @@ -479,7 +486,7 @@ gint g_timeout_remove(const guint id) if (t->id != id) continue; - default_context->proc_timeouts = slist_remove(default_context->proc_timeouts, t); + context->proc_timeouts = slist_remove(context->proc_timeouts, t); free(t); return 0; -- cgit From ea7b976177bffc7f3c89e380a1273e1d85b2a24f Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sat, 26 Aug 2006 16:55:47 +0000 Subject: Cleanup/fix glib-ectomy.c and its usage --- common/glib-ectomy.c | 23 ++++++++++++++++++++++- common/glib-ectomy.h | 6 +++--- 2 files changed, 25 insertions(+), 4 deletions(-) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index 41641ee6..33d20533 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -24,6 +24,11 @@ struct timeout { GSourceFunc function; }; +struct _GIOChannel { + int fd; + gboolean close_on_unref; +}; + struct _GMainContext { guint next_id; glong next_timeout; @@ -82,8 +87,17 @@ void g_io_channel_close(GIOChannel *channel) return; close(channel->fd); + channel->fd = -1; +} + +void g_io_channel_unref(GIOChannel *channel) +{ + if (!channel) + return; + + if (channel->close_on_unref && channel->fd >= 0) + g_io_channel_close(channel); - memset(channel, 0, sizeof(channel)); free(channel); } @@ -95,11 +109,18 @@ GIOChannel *g_io_channel_unix_new(int fd) if (!channel) return NULL; + memset(channel, 0, sizeof(GIOChannel)); + channel->fd = fd; return channel; } +void g_io_channel_set_close_on_unref(GIOChannel *channel, gboolean do_close) +{ + channel->close_on_unref = do_close; +} + gint g_io_channel_unix_get_fd(GIOChannel *channel) { return channel->fd; diff --git a/common/glib-ectomy.h b/common/glib-ectomy.h index 16f4810d..2885f019 100644 --- a/common/glib-ectomy.h +++ b/common/glib-ectomy.h @@ -30,9 +30,7 @@ typedef ssize_t gssize; #define MIN_TIMEOUT(a, b) (((a) < (b)) ? (a) : (b)) -typedef struct _GIOChannel { - int fd; -} GIOChannel; +typedef struct _GIOChannel GIOChannel; typedef gboolean (*GSourceFunc) (gpointer data); @@ -78,6 +76,8 @@ GIOError g_io_channel_read(GIOChannel *channel, gchar *buf, gsize count, gsize * void g_io_channel_close(GIOChannel *channel); GIOChannel *g_io_channel_unix_new(int fd); +void g_io_channel_unref(GIOChannel *channel); +void g_io_channel_set_close_on_unref(GIOChannel *channel, gboolean do_close); gint g_io_channel_unix_get_fd(GIOChannel *channel); guint g_io_add_watch(GIOChannel *channel, GIOCondition condition, GIOFunc func, gpointer user_data); -- cgit From 406212bb1c90b4454167d0ed9984d4f6c6a4efe0 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 31 Aug 2006 08:31:39 +0000 Subject: Add textfile_caseget() function --- common/textfile.c | 51 +++++++++++++++++++++++++++++++++------------------ common/textfile.h | 1 + 2 files changed, 34 insertions(+), 18 deletions(-) (limited to 'common') diff --git a/common/textfile.c b/common/textfile.c index f8b9545e..d76398c4 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -25,6 +25,7 @@ #include #endif +#define _GNU_SOURCE #include #include #include @@ -93,13 +94,17 @@ int create_name(char *buf, size_t size, const char *path, const char *address, c return snprintf(buf, size, "%s/%s/%s", path, address, name); } -static inline char *find_key(char *map, const char *key, size_t len) +static inline char *find_key(char *map, const char *key, size_t len, int icase) { - char *off = strstr(map, key); + char *off = (icase) ? strcasestr(map, key) : strstr(map, key); while (off && ((off > map && *(off - 1) != '\r' && - *(off - 1) != '\n') || *(off + len) != ' ')) - off = strstr(off + len, key); + *(off - 1) != '\n') || *(off + len) != ' ')) { + if (icase) + off = strcasestr(off + len, key); + else + off = strstr(off + len, key); + } return off; } @@ -126,7 +131,7 @@ static inline int write_key_value(int fd, const char *key, const char *value) return err; } -static int write_key(const char *pathname, const char *key, const char *value) +static int write_key(const char *pathname, const char *key, const char *value, int icase) { struct stat st; char *map, *off, *end, *str; @@ -163,7 +168,7 @@ static int write_key(const char *pathname, const char *key, const char *value) goto unlock; } - off = find_key(map, key, strlen(key)); + off = find_key(map, key, strlen(key), icase); if (!off) { if (value) { munmap(map, size); @@ -240,17 +245,7 @@ close: return -err; } -int textfile_put(const char *pathname, const char *key, const char *value) -{ - return write_key(pathname, key, value); -} - -int textfile_del(const char *pathname, const char *key) -{ - return write_key(pathname, key, NULL); -} - -char *textfile_get(const char *pathname, const char *key) +static char *read_key(const char *pathname, const char *key, int icase) { struct stat st; char *map, *off, *end, *str = NULL; @@ -280,7 +275,7 @@ char *textfile_get(const char *pathname, const char *key) } len = strlen(key); - off = find_key(map, key, len); + off = find_key(map, key, len, icase); if (!off) { err = EILSEQ; goto unmap; @@ -314,6 +309,26 @@ close: return str; } +int textfile_put(const char *pathname, const char *key, const char *value) +{ + return write_key(pathname, key, value, 0); +} + +int textfile_del(const char *pathname, const char *key) +{ + return write_key(pathname, key, NULL, 0); +} + +char *textfile_get(const char *pathname, const char *key) +{ + return read_key(pathname, key, 0); +} + +char *textfile_caseget(const char *pathname, const char *key) +{ + return read_key(pathname, key, 1); +} + int textfile_foreach(const char *pathname, void (*func)(char *key, char *value, void *data), void *data) { diff --git a/common/textfile.h b/common/textfile.h index 74e67eca..d89720d7 100644 --- a/common/textfile.h +++ b/common/textfile.h @@ -32,6 +32,7 @@ int create_name(char *buf, size_t size, const char *path, int textfile_put(const char *pathname, const char *key, const char *value); int textfile_del(const char *pathname, const char *key); char *textfile_get(const char *pathname, const char *key); +char *textfile_caseget(const char *pathname, const char *key); int textfile_foreach(const char *pathname, void (*func)(char *key, char *value, void *data), void *data); -- cgit From 50d400b1de38cbf75a2004a53e412dc6343d82bb Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 13 Sep 2006 14:58:58 +0000 Subject: Fix some memory leaks in textfile.c --- common/textfile.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'common') diff --git a/common/textfile.c b/common/textfile.c index d76398c4..8c46563c 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -219,6 +219,7 @@ static int write_key(const char *pathname, const char *key, const char *value, i munmap(map, size); if (ftruncate(fd, base) < 0) { err = errno; + free(str); goto unlock; } pos = lseek(fd, base, SEEK_SET); @@ -384,6 +385,7 @@ int textfile_foreach(const char *pathname, end = strpbrk(off, "\r\n"); if (!end) { err = EILSEQ; + free(key); break; } @@ -392,6 +394,7 @@ int textfile_foreach(const char *pathname, value = malloc(len + 1); if (!value) { err = errno; + free(key); break; } -- cgit From 439de080e210d17c3809e096cbe8b3ac5ab21144 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Tue, 19 Sep 2006 21:15:54 +0000 Subject: Add proper UTF-8 validation of device names (both local and remote) --- common/glib-ectomy.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++ common/glib-ectomy.h | 2 ++ 2 files changed, 89 insertions(+) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index 33d20533..56357648 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -515,3 +515,90 @@ gint g_timeout_remove(const guint id) return -1; } + +/* UTF-8 Validation: approximate copy/paste from glib2. */ + +#define UNICODE_VALID(c) \ + ((c) < 0x110000 && \ + (((c) & 0xFFFFF800) != 0xD800) && \ + ((c) < 0xFDD0 || (c) > 0xFDEF) && \ + ((c) & 0xFFFE) != 0xFFFE) + +#define CONTINUATION_CHAR(c, val) \ + do { \ + if (((c) & 0xc0) != 0x80) /* 10xxxxxx */ \ + goto failed; \ + (val) <<= 6; \ + (val) |= (c) & 0x3f; \ + } while (0) + +#define INCREMENT_AND_CHECK_MAX(i, max_len) \ + do { \ + (i)++; \ + if ((max_len) >= 0 && (i) >= (max_len)) \ + goto failed; \ + } while (0) + + +gboolean g_utf8_validate(const gchar *str, gssize max_len, const gchar **end) +{ + unsigned long val, min, i; + const unsigned char *p, *last; + + min = val = 0; + + for (p = (unsigned char *) str, i = 0; p[i]; i++) { + if (max_len >= 0 && i >= max_len) + break; + + if (p[i] < 128) + continue; + + last = &p[i]; + + if ((p[i] & 0xe0) == 0xc0) { /* 110xxxxx */ + if ((p[i] & 0x1e) == 0) + goto failed; + INCREMENT_AND_CHECK_MAX(i, max_len); + if ((p[i] & 0xc0) != 0x80) + goto failed; /* 10xxxxxx */ + } else { + if ((p[i] & 0xf0) == 0xe0) { + /* 1110xxxx */ + min = (1 << 11); + val = p[i] & 0x0f; + goto two_remaining; + } else if ((p[i] & 0xf8) == 0xf0) { + /* 11110xxx */ + min = (1 << 16); + val = p[i] & 0x07; + } else + goto failed; + + INCREMENT_AND_CHECK_MAX(i, max_len); + CONTINUATION_CHAR(p[i], val); +two_remaining: + INCREMENT_AND_CHECK_MAX(i, max_len); + CONTINUATION_CHAR(p[i], val); + + INCREMENT_AND_CHECK_MAX(i, max_len); + CONTINUATION_CHAR(p[i], val); + + if (val < min || !UNICODE_VALID(val)) + goto failed; + } + } + + if (end) + *end = (const gchar *) &p[i]; + + return TRUE; + +failed: + if (end) + *end = (const gchar *) last; + + return FALSE; +} + + diff --git a/common/glib-ectomy.h b/common/glib-ectomy.h index 2885f019..4d00870c 100644 --- a/common/glib-ectomy.h +++ b/common/glib-ectomy.h @@ -93,6 +93,8 @@ void g_main_loop_unref(GMainLoop *loop); guint g_timeout_add(guint interval, GSourceFunc function, gpointer data); gint g_timeout_remove(const guint id); +gboolean g_utf8_validate(const gchar *str, gssize max_len, const gchar **end); + #define g_main_new(is_running) g_main_loop_new(NULL, is_running); #define g_main_run(loop) g_main_loop_run(loop) #define g_main_quit(loop) g_main_loop_quit(loop) -- cgit From d389437b875a46fdc136e11b81a781d04380d518 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Tue, 19 Sep 2006 22:10:00 +0000 Subject: Add check for end of string in all places after incrementing the current char --- common/glib-ectomy.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index 56357648..83a2bb7b 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -532,11 +532,11 @@ gint g_timeout_remove(const guint id) (val) |= (c) & 0x3f; \ } while (0) -#define INCREMENT_AND_CHECK_MAX(i, max_len) \ - do { \ - (i)++; \ - if ((max_len) >= 0 && (i) >= (max_len)) \ - goto failed; \ +#define INCREMENT_AND_CHECK_MAX(p, i, max_len) \ + do { \ + (i)++; \ + if ((p)[(i)] == '\0' || ((max_len) >= 0 && (i) >= (max_len))) \ + goto failed; \ } while (0) @@ -559,7 +559,7 @@ gboolean g_utf8_validate(const gchar *str, gssize max_len, const gchar **end) if ((p[i] & 0xe0) == 0xc0) { /* 110xxxxx */ if ((p[i] & 0x1e) == 0) goto failed; - INCREMENT_AND_CHECK_MAX(i, max_len); + INCREMENT_AND_CHECK_MAX(p, i, max_len); if ((p[i] & 0xc0) != 0x80) goto failed; /* 10xxxxxx */ } else { @@ -575,13 +575,13 @@ gboolean g_utf8_validate(const gchar *str, gssize max_len, const gchar **end) } else goto failed; - INCREMENT_AND_CHECK_MAX(i, max_len); + INCREMENT_AND_CHECK_MAX(p, i, max_len); CONTINUATION_CHAR(p[i], val); two_remaining: - INCREMENT_AND_CHECK_MAX(i, max_len); + INCREMENT_AND_CHECK_MAX(p, i, max_len); CONTINUATION_CHAR(p[i], val); - INCREMENT_AND_CHECK_MAX(i, max_len); + INCREMENT_AND_CHECK_MAX(p, i, max_len); CONTINUATION_CHAR(p[i], val); if (val < min || !UNICODE_VALID(val)) -- cgit From 8900002499f30d2b76447be3b87d3fae9642267d Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 24 Sep 2006 17:53:07 +0000 Subject: Don't call close for already closed IO channels --- common/glib-ectomy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index 83a2bb7b..6831fcff 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -83,7 +83,7 @@ retry: void g_io_channel_close(GIOChannel *channel) { - if (!channel) + if (!channel || channel->fd < 0) return; close(channel->fd); -- cgit From b7f70f67039d79361f7aa12b572da4f97e717595 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Tue, 26 Sep 2006 10:26:59 +0000 Subject: Fix closing of a GIOChannel so that G_IO_NVAL gets properly signaled --- common/glib-ectomy.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index 6831fcff..fe6f524e 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -26,6 +26,7 @@ struct timeout { struct _GIOChannel { int fd; + gboolean closed; gboolean close_on_unref; }; @@ -52,6 +53,9 @@ GIOError g_io_channel_read(GIOChannel *channel, gchar *buf, gsize count, gsize * int fd = channel->fd; gssize result; + if (channel->closed) + return G_IO_STATUS_ERROR; + /* At least according to the Debian manpage for read */ if (count > SSIZE_MAX) count = SSIZE_MAX; @@ -83,11 +87,12 @@ retry: void g_io_channel_close(GIOChannel *channel) { - if (!channel || channel->fd < 0) + if (!channel || channel->closed) return; close(channel->fd); - channel->fd = -1; + + channel->closed = TRUE; } void g_io_channel_unref(GIOChannel *channel) @@ -123,6 +128,9 @@ void g_io_channel_set_close_on_unref(GIOChannel *channel, gboolean do_close) gint g_io_channel_unix_get_fd(GIOChannel *channel) { + if (channel->closed) + return -1; + return channel->fd; } -- cgit From 247635fe3905e4cc084a167c6db6e53dd7b0554d Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 27 Sep 2006 16:24:26 +0000 Subject: Support for prioritized watches --- common/glib-ectomy.c | 22 ++++++++++++++++++---- common/glib-ectomy.h | 6 ++++++ common/list.c | 30 ++++++++++++++++++++++++++++++ common/list.h | 2 ++ 4 files changed, 56 insertions(+), 4 deletions(-) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index fe6f524e..f3478edf 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -205,6 +205,20 @@ void g_io_remove_watch(guint id) } } +static struct slist *watch_list_add(struct slist *l, struct watch *watch) +{ + struct slist *cur; + + for (cur = l; cur != NULL; cur = cur->next) { + struct watch *w = cur->data; + + if (w->priority >= watch->priority) + break; + } + + return slist_insert_before(l, cur, watch); +} + guint g_io_add_watch_full(GIOChannel *channel, gint priority, GIOCondition condition, GIOFunc func, gpointer user_data, GDestroyNotify notify) @@ -228,9 +242,9 @@ guint g_io_add_watch_full(GIOChannel *channel, gint priority, watch->destroy = notify; if (context->watch_lock) - context->proc_watches = slist_prepend(context->proc_watches, watch); + context->proc_watches = watch_list_add(context->proc_watches, watch); else - context->watches = slist_prepend(context->watches, watch); + context->watches = watch_list_add(context->watches, watch); return watch->id; } @@ -385,7 +399,7 @@ void g_main_loop_run(GMainLoop *loop) if (!*w->revents) { context->watches = slist_remove(context->watches, w); - context->proc_watches = slist_append(context->proc_watches, w); + context->proc_watches = watch_list_add(context->proc_watches, w); continue; } @@ -403,7 +417,7 @@ void g_main_loop_run(GMainLoop *loop) continue; } - context->proc_watches = slist_append(context->proc_watches, w); + context->proc_watches = watch_list_add(context->proc_watches, w); } context->watches = context->proc_watches; diff --git a/common/glib-ectomy.h b/common/glib-ectomy.h index 4d00870c..411cc25f 100644 --- a/common/glib-ectomy.h +++ b/common/glib-ectomy.h @@ -69,6 +69,12 @@ typedef enum { G_IO_NVAL = POLLNVAL } GIOCondition; +#define G_PRIORITY_HIGH -100 +#define G_PRIORITY_DEFAULT 0 +#define G_PRIORITY_HIGH_IDLE 100 +#define G_PRIORITY_DEFAULT_IDLE 200 +#define G_PRIORITY_LOW 300 + typedef void (*GDestroyNotify) (gpointer data); typedef gboolean (*GIOFunc) (GIOChannel *source, GIOCondition condition, gpointer data); diff --git a/common/list.c b/common/list.c index a887bcdd..579d9574 100644 --- a/common/list.c +++ b/common/list.c @@ -70,6 +70,36 @@ struct slist *slist_prepend(struct slist *list, void *data) return entry; } +struct slist *slist_insert_before(struct slist *list, struct slist *sibling, void *data) +{ + struct slist *entry, *prev, *cur; + + entry = malloc(sizeof(struct slist)); + if (!entry) + return list; + + entry->data = data; + entry->next = NULL; + + if (!list) + return entry; + + for (cur = list, prev = NULL; cur != NULL; prev = cur, cur = prev->next) { + if (cur == sibling) + break; + } + + if (!prev) { + entry->next = list; + return entry; + } + + entry->next = prev->next; + prev->next = entry; + + return list; +} + struct slist *slist_remove(struct slist *list, void *data) { struct slist *l, *next, *prev = NULL, *match = NULL; diff --git a/common/list.h b/common/list.h index 1b502110..f6576429 100644 --- a/common/list.h +++ b/common/list.h @@ -37,6 +37,8 @@ struct slist *slist_append(struct slist *list, void *data); struct slist *slist_prepend(struct slist *list, void *data); +struct slist *slist_insert_before(struct slist *list, struct slist *sibling, void *data); + struct slist *slist_remove(struct slist *list, void *data); struct slist *slist_find(struct slist *list, const void *data, -- cgit From 48d9984c99f55dc249050f56aa1c01ad56dac82d Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 12 Oct 2006 07:47:40 +0000 Subject: Implement slist_insert_sorted and slist_find functions --- common/list.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ common/list.h | 4 +++ 2 files changed, 94 insertions(+) (limited to 'common') diff --git a/common/list.c b/common/list.c index 579d9574..65d83295 100644 --- a/common/list.c +++ b/common/list.c @@ -100,6 +100,48 @@ struct slist *slist_insert_before(struct slist *list, struct slist *sibling, voi return list; } +struct slist *slist_insert_sorted(struct slist *list, void *data, cmp_func_t cmp_func) +{ + struct slist *tmp, *prev, *entry; + int cmp; + + entry = malloc(sizeof(struct slist)); + if (!entry) + return list; + + entry->data = data; + entry->next = NULL; + + if (!list) + return entry; + + prev = NULL; + tmp = list; + + cmp = cmp_func(data, tmp->data); + + while (tmp->next && cmp > 0) { + prev = tmp; + tmp = tmp->next; + + cmp = cmp_func(data, tmp->data); + } + + if (!tmp->next && cmp > 0) { + tmp->next = entry; + return list; + } + + if (prev) { + prev->next = entry; + entry->next = tmp; + return list; + } else { + entry->next = list; + return entry; + } +} + struct slist *slist_remove(struct slist *list, void *data) { struct slist *l, *next, *prev = NULL, *match = NULL; @@ -144,6 +186,54 @@ struct slist *slist_find(struct slist *list, const void *data, return NULL; } +static struct slist *slist_sort_merge(struct slist *l1, struct slist *l2, + cmp_func_t cmp_func) +{ + struct slist list, *l; + int cmp; + + l = &list; + + while (l1 && l2) { + cmp = cmp_func(l1->data, l2->data); + + if (cmp <= 0) { + l = l->next = l1; + l1 = l1->next; + } else { + l = l->next = l2; + l2 = l2->next; + } + } + + l->next = l1 ? l1 : l2; + + return list.next; +} + +struct slist *slist_sort(struct slist *list, cmp_func_t cmp_func) +{ + struct slist *l1, *l2; + + if (!list || !list->next) + return list; + + l1 = list; + l2 = list->next; + + while ((l2 = l2->next) != NULL) { + if ((l2 = l2->next) == NULL) + break; + l1 = l1->next; + } + + l2 = l1->next; + l1->next = NULL; + + return slist_sort_merge(slist_sort(list, cmp_func), + slist_sort(l2, cmp_func), cmp_func); +} + int slist_length(struct slist *list) { int len; diff --git a/common/list.h b/common/list.h index f6576429..9868a79a 100644 --- a/common/list.h +++ b/common/list.h @@ -39,11 +39,15 @@ struct slist *slist_prepend(struct slist *list, void *data); struct slist *slist_insert_before(struct slist *list, struct slist *sibling, void *data); +struct slist *slist_insert_sorted(struct slist *list, void *data, cmp_func_t cmp_func); + struct slist *slist_remove(struct slist *list, void *data); struct slist *slist_find(struct slist *list, const void *data, cmp_func_t cmp_func); +struct slist *slist_sort(struct slist *list, cmp_func_t cmp_func); + int slist_length(struct slist *list); void slist_foreach(struct slist *list, slist_func_t func, void *user_data); -- cgit From 351ec5438c38eb319ff861f1498fa0dacb747e60 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 12 Oct 2006 07:51:37 +0000 Subject: Use slist_insert_sorted for maintaining watch list --- common/glib-ectomy.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index f3478edf..46d92154 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -205,20 +205,13 @@ void g_io_remove_watch(guint id) } } -static struct slist *watch_list_add(struct slist *l, struct watch *watch) +int watch_prio_cmp(struct watch *w1, struct watch *w2) { - struct slist *cur; - - for (cur = l; cur != NULL; cur = cur->next) { - struct watch *w = cur->data; - - if (w->priority >= watch->priority) - break; - } - - return slist_insert_before(l, cur, watch); + return w1->priority - w2->priority; } +#define watch_list_add(l, w) slist_insert_sorted((l), (w), (cmp_func_t) watch_prio_cmp) + guint g_io_add_watch_full(GIOChannel *channel, gint priority, GIOCondition condition, GIOFunc func, gpointer user_data, GDestroyNotify notify) -- cgit From b86c496307b2b284fabb1a33490163a78aeeb831 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 12 Oct 2006 07:54:47 +0000 Subject: Remove slist_insert_before as it is not needed anymore --- common/list.c | 30 ------------------------------ common/list.h | 2 -- 2 files changed, 32 deletions(-) (limited to 'common') diff --git a/common/list.c b/common/list.c index 65d83295..827f1789 100644 --- a/common/list.c +++ b/common/list.c @@ -70,36 +70,6 @@ struct slist *slist_prepend(struct slist *list, void *data) return entry; } -struct slist *slist_insert_before(struct slist *list, struct slist *sibling, void *data) -{ - struct slist *entry, *prev, *cur; - - entry = malloc(sizeof(struct slist)); - if (!entry) - return list; - - entry->data = data; - entry->next = NULL; - - if (!list) - return entry; - - for (cur = list, prev = NULL; cur != NULL; prev = cur, cur = prev->next) { - if (cur == sibling) - break; - } - - if (!prev) { - entry->next = list; - return entry; - } - - entry->next = prev->next; - prev->next = entry; - - return list; -} - struct slist *slist_insert_sorted(struct slist *list, void *data, cmp_func_t cmp_func) { struct slist *tmp, *prev, *entry; diff --git a/common/list.h b/common/list.h index 9868a79a..c11424ca 100644 --- a/common/list.h +++ b/common/list.h @@ -37,8 +37,6 @@ struct slist *slist_append(struct slist *list, void *data); struct slist *slist_prepend(struct slist *list, void *data); -struct slist *slist_insert_before(struct slist *list, struct slist *sibling, void *data); - struct slist *slist_insert_sorted(struct slist *list, void *data, cmp_func_t cmp_func); struct slist *slist_remove(struct slist *list, void *data); -- cgit From 80ecd35469885e6f8ef300819a994dd155550dcb Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 30 Oct 2006 15:22:22 +0000 Subject: Move logging.c from hcid/ to common/ --- common/Makefile.am | 2 +- common/logging.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ common/logging.h | 35 +++++++++++++++++++++ 3 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 common/logging.c create mode 100644 common/logging.h (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index 30211fab..b2f6fb33 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -3,7 +3,7 @@ noinst_LIBRARIES = libhelper.a libhelper_a_SOURCES = oui.h oui.c list.h list.c \ textfile.h textfile.c helper.h helper.c \ - glib-ectomy.h glib-ectomy.c + glib-ectomy.h glib-ectomy.c logging.h logging.c noinst_PROGRAMS = test_textfile diff --git a/common/logging.c b/common/logging.c new file mode 100644 index 00000000..ddaf0d33 --- /dev/null +++ b/common/logging.c @@ -0,0 +1,90 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2006 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +static volatile int debug_enabled = 0; + +void info(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + + vsyslog(LOG_INFO, format, ap); + + va_end(ap); +} + +void error(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + + vsyslog(LOG_ERR, format, ap); + + va_end(ap); +} + +void debug(const char *format, ...) +{ + va_list ap; + + if (!debug_enabled) + return; + + va_start(ap, format); + + vsyslog(LOG_DEBUG, format, ap); + + va_end(ap); +} + +void enable_debug() +{ + debug_enabled = 1; +} + +void disable_debug() +{ + debug_enabled = 0; +} + +void start_logging(const char *ident, const char *message) +{ + openlog(ident, LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_DAEMON); + + info(message); +} + +void stop_logging(void) +{ + closelog(); +} diff --git a/common/logging.h b/common/logging.h new file mode 100644 index 00000000..1e2ca525 --- /dev/null +++ b/common/logging.h @@ -0,0 +1,35 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2006 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __LOGGING_H +#define __LOGGING_H + +void info(const char *format, ...); +void error(const char *format, ...); +void debug(const char *format, ...); +void enable_debug(); +void disable_debug(); +void start_logging(const char *ident, const char *message); +void stop_logging(void); + +#endif /* __LOGGING_H */ -- cgit From 1badf196a83fb8d32e212c49b7487b08962c18f0 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 1 Nov 2006 12:58:31 +0000 Subject: More cleanup. Move common dbus stuff to common/dbus.c. hcid/dbus.c -> hcid/dbus-hci.c --- common/Makefile.am | 5 +- common/dbus.c | 563 +++++++++++++++++++++++++++++++++++++++++++++++++++++ common/dbus.h | 50 +++++ 3 files changed, 617 insertions(+), 1 deletion(-) create mode 100644 common/dbus.c create mode 100644 common/dbus.h (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index b2f6fb33..83ec45f4 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -1,9 +1,12 @@ +AM_CFLAGS = @DBUS_CFLAGS@ + noinst_LIBRARIES = libhelper.a libhelper_a_SOURCES = oui.h oui.c list.h list.c \ textfile.h textfile.c helper.h helper.c \ - glib-ectomy.h glib-ectomy.c logging.h logging.c + glib-ectomy.h glib-ectomy.c logging.h logging.c \ + dbus.h dbus.c noinst_PROGRAMS = test_textfile diff --git a/common/dbus.c b/common/dbus.c new file mode 100644 index 00000000..5ef1725e --- /dev/null +++ b/common/dbus.c @@ -0,0 +1,563 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2006 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include + +#include "glib-ectomy.h" +#include "dbus.h" +#include "logging.h" +#include "list.h" + +#define DISPATCH_TIMEOUT 0 + +static int name_listener_initialized = 0; + +static struct slist *name_listeners = NULL; + +typedef struct { + uint32_t id; + DBusTimeout *timeout; +} timeout_handler_t; + +struct watch_info { + guint watch_id; + GIOChannel *io; + DBusConnection *conn; +}; + +struct disconnect_data { + void (*disconnect_cb)(void *); + void *user_data; +}; + +struct name_callback { + name_cb_t func; + void *user_data; +}; + +struct name_data { + char *name; + struct slist *callbacks; +}; + +static struct name_data *name_data_find(const char *name) +{ + struct slist *current; + + for (current = name_listeners; current != NULL; current = current->next) { + struct name_data *data = current->data; + if (strcmp(name, data->name) == 0) + return data; + } + + return NULL; +} + +static struct name_callback *name_callback_find(struct slist *callbacks, + name_cb_t func, void *user_data) +{ + struct slist *current; + + for (current = callbacks; current != NULL; current = current->next) { + struct name_callback *cb = current->data; + if (cb->func == func && cb->user_data == user_data) + return cb; + } + + return NULL; +} + +static void name_data_free(struct name_data *data) +{ + struct slist *l; + + for (l = data->callbacks; l != NULL; l = l->next) + free(l->data); + + slist_free(data->callbacks); + + if (data->name) + free(data->name); + + free(data); +} + +static int name_data_add(const char *name, name_cb_t func, void *user_data) +{ + int first = 1; + struct name_data *data = NULL; + struct name_callback *cb = NULL; + + cb = malloc(sizeof(struct name_callback)); + if (!cb) + goto failed; + + cb->func = func; + cb->user_data = user_data; + + data = name_data_find(name); + if (data) { + first = 0; + goto done; + } + + data = malloc(sizeof(struct name_data)); + if (!data) + goto failed; + + memset(data, 0, sizeof(struct name_data)); + + data->name = strdup(name); + if (!data->name) + goto failed; + + name_listeners = slist_append(name_listeners, data); + +done: + data->callbacks = slist_append(data->callbacks, cb); + return first; + +failed: + if (data) + name_data_free(data); + + if (cb) + free(cb); + + return 0; +} + +static void name_data_remove(const char *name, name_cb_t func, void *user_data) +{ + struct name_data *data; + struct name_callback *cb = NULL; + + data = name_data_find(name); + if (!data) + return; + + cb = name_callback_find(data->callbacks, func, user_data); + if (cb) { + data->callbacks = slist_remove(data->callbacks, cb); + free(cb); + } + + if (!data->callbacks) { + name_listeners = slist_remove(name_listeners, data); + name_data_free(data); + } +} + +static DBusHandlerResult name_exit_filter(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + struct slist *l; + struct name_data *data; + char *name, *old, *new; + + if (!dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, + "NameOwnerChanged")) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (!dbus_message_get_args(message, NULL, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_STRING, &old, + DBUS_TYPE_STRING, &new, + DBUS_TYPE_INVALID)) { + error("Invalid arguments for NameOwnerChanged signal"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + /* We are not interested of service creations */ + if (*new != '\0') + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + data = name_data_find(name); + if (!data) { + error("Got NameOwnerChanged signal for %s which has no listeners", name); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + for (l = data->callbacks; l != NULL; l = l->next) { + struct name_callback *cb = l->data; + cb->func(name, cb->user_data); + } + + name_listeners = slist_remove(name_listeners, data); + name_data_free(data); + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +int name_listener_add(DBusConnection *connection, const char *name, + name_cb_t func, void *user_data) +{ + DBusError err; + char match_string[128]; + int first; + + if (!name_listener_initialized) { + if (!dbus_connection_add_filter(connection, name_exit_filter, NULL, NULL)) { + error("dbus_connection_add_filter() failed"); + return -1; + } + name_listener_initialized = 1; + } + + first = name_data_add(name, func, user_data); + /* The filter is already added if this is not the first callback + * registration for the name */ + if (!first) + return 0; + + debug("name_listener_add(%s)", name); + + snprintf(match_string, sizeof(match_string), + "interface=%s,member=NameOwnerChanged,arg0=%s", + DBUS_INTERFACE_DBUS, name); + + dbus_error_init(&err); + dbus_bus_add_match(connection, match_string, &err); + + if (dbus_error_is_set(&err)) { + error("Adding match rule \"%s\" failed: %s", match_string, + err.message); + dbus_error_free(&err); + name_data_remove(name, func, user_data); + return -1; + } + + return 0; +} + +int name_listener_remove(DBusConnection *connection, const char *name, + name_cb_t func, void *user_data) +{ + struct name_data *data; + struct name_callback *cb; + DBusError err; + char match_string[128]; + + debug("name_listener_remove(%s)", name); + + data = name_data_find(name); + if (!data) { + error("remove_name_listener: no listener for %s", name); + return -1; + } + + cb = name_callback_find(data->callbacks, func, user_data); + if (!cb) { + error("No matching callback found for %s", name); + return -1; + } + + data->callbacks = slist_remove(data->callbacks, cb); + free(cb); + + /* Don't remove the filter if other callbacks exist */ + if (data->callbacks) + return 0; + + snprintf(match_string, sizeof(match_string), + "interface=%s,member=NameOwnerChanged,arg0=%s", + DBUS_INTERFACE_DBUS, name); + + dbus_error_init(&err); + dbus_bus_remove_match(connection, match_string, &err); + + if (dbus_error_is_set(&err)) { + error("Removing owner match rule for %s failed: %s", + name, err.message); + dbus_error_free(&err); + return -1; + } + + name_data_remove(name, func, user_data); + + return 0; +} + +static DBusHandlerResult disconnect_filter(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + const char *iface,*method; + struct disconnect_data *dc_data = data; + + if (dbus_message_get_type (msg) != DBUS_MESSAGE_TYPE_SIGNAL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + iface = dbus_message_get_interface(msg); + method = dbus_message_get_member(msg); + + if ((strcmp(iface, DBUS_INTERFACE_LOCAL) == 0) && + (strcmp(method, "Disconnected") == 0)) { + error("Got disconnected from the system message bus"); + dbus_connection_unref(conn); + dc_data->disconnect_cb(dc_data->user_data); + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static gboolean message_dispatch_cb(void *data) +{ + DBusConnection *connection = data; + + dbus_connection_ref(connection); + + /* Dispatch messages */ + while (dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS); + + dbus_connection_unref(connection); + + return FALSE; +} + +static gboolean watch_func(GIOChannel *chan, GIOCondition cond, gpointer data) +{ + DBusWatch *watch = data; + struct watch_info *info = dbus_watch_get_data(watch); + int flags = 0; + + if (cond & G_IO_IN) flags |= DBUS_WATCH_READABLE; + if (cond & G_IO_OUT) flags |= DBUS_WATCH_WRITABLE; + if (cond & G_IO_HUP) flags |= DBUS_WATCH_HANGUP; + if (cond & G_IO_ERR) flags |= DBUS_WATCH_ERROR; + + dbus_watch_handle(watch, flags); + + if (dbus_connection_get_dispatch_status(info->conn) == DBUS_DISPATCH_DATA_REMAINS) + g_timeout_add(DISPATCH_TIMEOUT, message_dispatch_cb, info->conn); + + return TRUE; +} + +static dbus_bool_t add_watch(DBusWatch *watch, void *data) +{ + GIOCondition cond = G_IO_HUP | G_IO_ERR; + DBusConnection *conn = data; + struct watch_info *info; + int fd, flags; + + if (!dbus_watch_get_enabled(watch)) + return TRUE; + + info = malloc(sizeof(struct watch_info)); + if (info == NULL) + return FALSE; + + fd = dbus_watch_get_fd(watch); + info->io = g_io_channel_unix_new(fd); + info->conn = dbus_connection_ref(conn); + + dbus_watch_set_data(watch, info, NULL); + + flags = dbus_watch_get_flags(watch); + + if (flags & DBUS_WATCH_READABLE) cond |= G_IO_IN; + if (flags & DBUS_WATCH_WRITABLE) cond |= G_IO_OUT; + + info->watch_id = g_io_add_watch(info->io, cond, watch_func, watch); + + return TRUE; +} + +static void remove_watch(DBusWatch *watch, void *data) +{ + struct watch_info *info = dbus_watch_get_data(watch); + + dbus_watch_set_data(watch, NULL, NULL); + + if (info) { + g_io_remove_watch(info->watch_id); + g_io_channel_unref(info->io); + dbus_connection_unref(info->conn); + free(info); + } +} + +static void watch_toggled(DBusWatch *watch, void *data) +{ + /* Because we just exit on OOM, enable/disable is + * no different from add/remove */ + if (dbus_watch_get_enabled(watch)) + add_watch(watch, data); + else + remove_watch(watch, data); +} + +static gboolean timeout_handler_dispatch(gpointer data) +{ + timeout_handler_t *handler = data; + + /* if not enabled should not be polled by the main loop */ + if (dbus_timeout_get_enabled(handler->timeout) != TRUE) + return FALSE; + + dbus_timeout_handle(handler->timeout); + + return FALSE; +} + +static void timeout_handler_free(void *data) +{ + timeout_handler_t *handler = data; + if (!handler) + return; + + g_timeout_remove(handler->id); + free(handler); +} + +static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) +{ + timeout_handler_t *handler; + + if (!dbus_timeout_get_enabled (timeout)) + return TRUE; + + handler = malloc(sizeof(timeout_handler_t)); + memset(handler, 0, sizeof(timeout_handler_t)); + + handler->timeout = timeout; + handler->id = g_timeout_add(dbus_timeout_get_interval(timeout), + timeout_handler_dispatch, handler); + + dbus_timeout_set_data(timeout, handler, timeout_handler_free); + + return TRUE; +} + +static void remove_timeout(DBusTimeout *timeout, void *data) +{ + +} + +static void timeout_toggled(DBusTimeout *timeout, void *data) +{ + if (dbus_timeout_get_enabled(timeout)) + add_timeout(timeout, data); + else + remove_timeout(timeout, data); +} + +static void dispatch_status_cb(DBusConnection *conn, + DBusDispatchStatus new_status, + void *data) +{ + if (!dbus_connection_get_is_connected(conn)) + return; + + if (new_status == DBUS_DISPATCH_DATA_REMAINS) + g_timeout_add(DISPATCH_TIMEOUT, message_dispatch_cb, data); +} + +DBusConnection *init_dbus(void (*disconnect_cb)(void *), void *user_data) +{ + DBusConnection *conn; + DBusError err; + struct disconnect_data *dc_data; + + dbus_error_init(&err); + + conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); + + if (dbus_error_is_set(&err)) { + error("Can't open system message bus connection: %s", + err.message); + dbus_error_free(&err); + return NULL; + } + + dbus_connection_set_watch_functions(conn, add_watch, remove_watch, + watch_toggled, conn, NULL); + + dbus_connection_set_timeout_functions(conn, add_timeout, remove_timeout, + timeout_toggled, conn, NULL); + + dbus_connection_set_dispatch_status_function(conn, dispatch_status_cb, + conn, NULL); + + if (!disconnect_cb) + return conn; + + dc_data = malloc(sizeof(struct disconnect_data)); + if (!dc_data) { + error("Allocating disconnect data failed"); + dbus_connection_unref(conn); + return NULL; + } + + dc_data->disconnect_cb = disconnect_cb; + dc_data->user_data = user_data; + + dbus_connection_set_exit_on_disconnect(conn, FALSE); + + if (!dbus_connection_add_filter(conn, disconnect_filter, + dc_data, free)) { + error("Can't add D-Bus disconnect filter"); + free(dc_data); + dbus_connection_unref(conn); + return NULL; + } + + return conn; +} + +static char simple_xml[] = DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE ""; + +DBusHandlerResult simple_introspect(DBusConnection *conn, DBusMessage *msg, void *data) +{ + DBusMessage *reply; + const char *path, *ptr = simple_xml; + + path = dbus_message_get_path(msg); + + info("Introspect path:%s", path); + + if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING)) { + error("Unexpected signature to introspect call"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + reply = dbus_message_new_method_return(msg); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + dbus_message_append_args(reply, DBUS_TYPE_STRING, &ptr, + DBUS_TYPE_INVALID); + + return send_message_and_unref(conn, reply); +} + diff --git a/common/dbus.h b/common/dbus.h new file mode 100644 index 00000000..59afd6e6 --- /dev/null +++ b/common/dbus.h @@ -0,0 +1,50 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2006 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __H_BLUEZ_DBUS_H__ +#define __H_BLUEZ_DBUS_H__ + +#include + +DBusConnection *init_dbus(void (*disconnect_cb)(void *), void *user_data); + +typedef void (*name_cb_t)(const char *name, void *user_data); + +int name_listener_add(DBusConnection *connection, const char *name, + name_cb_t func, void *user_data); +int name_listener_remove(DBusConnection *connection, const char *name, + name_cb_t func, void *user_data); + +DBusHandlerResult simple_introspect(DBusConnection *conn, DBusMessage *msg, void *data); + +static inline DBusHandlerResult send_message_and_unref(DBusConnection *conn, DBusMessage *msg) +{ + if (msg) { + dbus_connection_send(conn, msg, NULL); + dbus_message_unref(msg); + } + + return DBUS_HANDLER_RESULT_HANDLED; +} + +#endif /* __H_BLUEZ_DBUS_H__ */ -- cgit From 001689d4b42a6fa28eb757347211544e127206a1 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 1 Nov 2006 13:07:35 +0000 Subject: Unify Makefile.am style --- common/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index 83ec45f4..7249a51f 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -1,6 +1,4 @@ -AM_CFLAGS = @DBUS_CFLAGS@ - noinst_LIBRARIES = libhelper.a libhelper_a_SOURCES = oui.h oui.c list.h list.c \ @@ -12,6 +10,8 @@ noinst_PROGRAMS = test_textfile test_textfile_LDADD = libhelper.a +AM_CFLAGS = @DBUS_CFLAGS@ + EXTRA_DIST = ppoll.h MAINTAINERCLEANFILES = Makefile.in -- cgit From a59e6d0bdc38728c96254f589fa2e64f0542a8a8 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 7 Nov 2006 20:34:46 +0000 Subject: Add textfile_casedel() function --- common/textfile.c | 5 +++++ common/textfile.h | 1 + 2 files changed, 6 insertions(+) (limited to 'common') diff --git a/common/textfile.c b/common/textfile.c index 8c46563c..795c99a3 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -320,6 +320,11 @@ int textfile_del(const char *pathname, const char *key) return write_key(pathname, key, NULL, 0); } +int textfile_casedel(const char *pathname, const char *key) +{ + return write_key(pathname, key, NULL, 1); +} + char *textfile_get(const char *pathname, const char *key) { return read_key(pathname, key, 0); diff --git a/common/textfile.h b/common/textfile.h index d89720d7..b1a31100 100644 --- a/common/textfile.h +++ b/common/textfile.h @@ -31,6 +31,7 @@ int create_name(char *buf, size_t size, const char *path, int textfile_put(const char *pathname, const char *key, const char *value); int textfile_del(const char *pathname, const char *key); +int textfile_casedel(const char *pathname, const char *key); char *textfile_get(const char *pathname, const char *key); char *textfile_caseget(const char *pathname, const char *key); -- cgit From e1046e6b02c2eef72ad63f2a61949e1ca606f63f Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 10 Nov 2006 17:59:14 +0000 Subject: Added raw service record to xml conversion functions --- common/Makefile.am | 2 +- common/sdp-xml.c | 400 +++++++++++++++++++++++++++++++++++++++++++++++++++++ common/sdp-xml.h | 35 +++++ 3 files changed, 436 insertions(+), 1 deletion(-) create mode 100644 common/sdp-xml.c create mode 100644 common/sdp-xml.h (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index 7249a51f..d71ca3b6 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -4,7 +4,7 @@ noinst_LIBRARIES = libhelper.a libhelper_a_SOURCES = oui.h oui.c list.h list.c \ textfile.h textfile.c helper.h helper.c \ glib-ectomy.h glib-ectomy.c logging.h logging.c \ - dbus.h dbus.c + dbus.h dbus.c sdp-xml.h sdp-xml.c noinst_PROGRAMS = test_textfile diff --git a/common/sdp-xml.c b/common/sdp-xml.c new file mode 100644 index 00000000..5c6dd877 --- /dev/null +++ b/common/sdp-xml.c @@ -0,0 +1,400 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2006 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "sdp-xml.h" + +#include +#include +#include +#include +#include + +#define STRBUFSIZE 256 +#define MAXINDENT 64 + +static void convert_raw_data_to_xml(sdp_data_t *value, int indent_level, + void *data, + void (*appender) (void *, const char *)) +{ + int i, hex; + char buf[STRBUFSIZE]; + char indent[MAXINDENT]; + char next_indent[MAXINDENT]; + + if (!value) + return; + + if (indent_level >= MAXINDENT) + indent_level = MAXINDENT - 2; + + for (i = 0; i < indent_level; i++) { + indent[i] = '\t'; + next_indent[i] = '\t'; + } + + indent[i] = '\0'; + next_indent[i] = '\t'; + next_indent[i + 1] = '\0'; + + buf[STRBUFSIZE - 1] = '\0'; + + switch (value->dtd) { + case SDP_DATA_NIL: + appender(data, indent); + appender(data, "\n"); + break; + case SDP_BOOL: + appender(data, indent); + appender(data, "val.uint8 ? "true" : "false"); + appender(data, "\" />\n"); + break; + case SDP_UINT8: + appender(data, indent); + appender(data, "val.uint8); + appender(data, buf); + appender(data, "\" />\n"); + break; + case SDP_UINT16: + appender(data, indent); + appender(data, "val.uint16); + appender(data, buf); + appender(data, "\" />\n"); + break; + case SDP_UINT32: + appender(data, indent); + appender(data, "val.uint32); + appender(data, buf); + appender(data, "\" />\n"); + break; + case SDP_UINT64: + appender(data, indent); + appender(data, "val.uint64); + appender(data, buf); + appender(data, "\" />\n"); + break; + case SDP_UINT128: + appender(data, indent); + appender(data, "val.uint128.data[i]); + } + + appender(data, buf); + appender(data, "\" />\n"); + break; + case SDP_INT8: + appender(data, indent); + appender(data, "val.int8); + appender(data, buf); + appender(data, "\" />\n"); + break; + case SDP_INT16: + appender(data, indent); + appender(data, "val.int16); + appender(data, buf); + appender(data, "\" />\n"); + break; + case SDP_INT32: + appender(data, indent); + appender(data, "val.int32); + appender(data, buf); + appender(data, "\" />\n"); + break; + case SDP_INT64: + appender(data, indent); + appender(data, "val.int64); + appender(data, buf); + appender(data, "\" />\n"); + break; + case SDP_INT128: + appender(data, indent); + appender(data, "val.int128.data[i]); + } + appender(data, buf); + + appender(data, "\" />\n"); + break; + case SDP_UUID16: + appender(data, indent); + appender(data, "val.uuid.value.uuid16); + appender(data, buf); + appender(data, "\" />\n"); + break; + case SDP_UUID32: + appender(data, indent); + appender(data, "val.uuid.value.uuid32); + appender(data, buf); + appender(data, "\" />\n"); + break; + case SDP_UUID128: + appender(data, indent); + appender(data, "val.uuid.value. + uuid128.data[0], + (unsigned char) value->val.uuid.value. + uuid128.data[1], + (unsigned char) value->val.uuid.value. + uuid128.data[2], + (unsigned char) value->val.uuid.value. + uuid128.data[3], + (unsigned char) value->val.uuid.value. + uuid128.data[4], + (unsigned char) value->val.uuid.value. + uuid128.data[5], + (unsigned char) value->val.uuid.value. + uuid128.data[6], + (unsigned char) value->val.uuid.value. + uuid128.data[7], + (unsigned char) value->val.uuid.value. + uuid128.data[8], + (unsigned char) value->val.uuid.value. + uuid128.data[9], + (unsigned char) value->val.uuid.value. + uuid128.data[10], + (unsigned char) value->val.uuid.value. + uuid128.data[11], + (unsigned char) value->val.uuid.value. + uuid128.data[12], + (unsigned char) value->val.uuid.value. + uuid128.data[13], + (unsigned char) value->val.uuid.value. + uuid128.data[14], + (unsigned char) value->val.uuid.value. + uuid128.data[15]); + + appender(data, buf); + appender(data, "\" />\n"); + break; + case SDP_TEXT_STR8: + case SDP_TEXT_STR16: + case SDP_TEXT_STR32: + { + hex = 0; + + int num_chars_to_escape = 0; + + for (i = 0; i < value->unitSize; i++) { + if (i == (value->unitSize - 1) + && value->val.str[i] == '\0') + break; + if (!isprint(value->val.str[i])) { + hex = 1; + break; + } + + /* XML is evil, must do this... */ + if ((value->val.str[i] == '<') || + (value->val.str[i] == '>') || + (value->val.str[i] == '"') || + (value->val.str[i] == '&')) + num_chars_to_escape++; + + } + + appender(data, indent); + + appender(data, "unitSize * 2 + 1)); + + /* 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], + "%02x", + (unsigned char) value->val.str[i]); + + strBuf[value->unitSize * 2] = '\0'; + } + else { + int j; + /* escape the XML disallowed chars */ + strBuf = (char *) + malloc(sizeof(char) * + (value->unitSize + 1 + num_chars_to_escape * 4)); + for (i = 0, j = 0; i < value->unitSize; i++) { + if (value->val.str[i] == '&') { + strBuf[j++] = '&'; + strBuf[j++] = 'a'; + strBuf[j++] = 'm'; + strBuf[j++] = 'p'; + } + else if (value->val.str[i] == '<') { + strBuf[j++] = '&'; + strBuf[j++] = 'l'; + strBuf[j++] = 't'; + } + else if (value->val.str[i] == '>') { + strBuf[j++] = '&'; + strBuf[j++] = 'g'; + strBuf[j++] = 't'; + } + else if (value->val.str[i] == '"') { + strBuf[j++] = '&'; + strBuf[j++] = 'q'; + strBuf[j++] = 'u'; + strBuf[j++] = 'o'; + strBuf[j++] = 't'; + } + else { + strBuf[j++] = value->val.str[i]; + } + } + + strBuf[j] = '\0'; + } + + appender(data, "value=\""); + appender(data, strBuf); + appender(data, "\" />\n"); + free(strBuf); + break; + } + case SDP_URL_STR8: + case SDP_URL_STR16: + case SDP_URL_STR32: + appender(data, indent); + appender(data, "val.str); + appender(data, "\" />\n"); + break; + case SDP_SEQ8: + case SDP_SEQ16: + case SDP_SEQ32: + appender(data, indent); + appender(data, "\n"); + + convert_raw_data_to_xml(value->val.dataseq, + indent_level + 1, data, + appender); + + appender(data, indent); + appender(data, "\n"); + + break; + case SDP_ALT8: + case SDP_ALT16: + case SDP_ALT32: + appender(data, indent); + + appender(data, "\n"); + + convert_raw_data_to_xml(value->val.dataseq, + indent_level + 1, data, + appender); + appender(data, indent); + + appender(data, "\n"); + + break; + default: + break; + } + + convert_raw_data_to_xml(value->next, indent_level, data, + appender); +} + +struct conversion_data +{ + void *data; + 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; + sdp_data_t *value = (sdp_data_t *) val; + char buf[STRBUFSIZE]; + + buf[STRBUFSIZE - 1] = '\0'; + snprintf(buf, STRBUFSIZE - 1, "\t\n", + value->attrId); + cd->appender(cd->data, buf); + + if (data) + convert_raw_data_to_xml(value, 2, cd->data, + cd->appender); + else + cd->appender(cd->data, "\t\tNULL\n"); + + cd->appender(cd->data, "\t\n"); +} + +/* + Will convert the sdp record to XML. The appender and data can be used + 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 *)) +{ + struct conversion_data cd; + + cd.data = data; + cd.appender = appender; + + if (rec && rec->attrlist) { + appender(data, "\n\n"); + appender(data, "\n"); + sdp_list_foreach(rec->attrlist, + convert_raw_attr_to_xml_func, &cd); + appender(data, "\n"); + } +} + diff --git a/common/sdp-xml.h b/common/sdp-xml.h new file mode 100644 index 00000000..fe781f57 --- /dev/null +++ b/common/sdp-xml.h @@ -0,0 +1,35 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2006 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +#ifndef __SDP_XML_H__ +#define __SDP_XML_H__ + +#include +#include + +void convert_sdp_record_to_xml(sdp_record_t * rec, + void *userData, + void (*appendFunc) (void *, const char *)); + +#endif /* __SDP_XML_H__ */ -- cgit From 6f9503c6dd849b1cb21bd4e17acf079e2e546b06 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 13 Nov 2006 06:38:28 +0000 Subject: Add skeleton for expat support --- common/Makefile.am | 2 +- common/sdp-expat.c | 0 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 common/sdp-expat.c (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index d71ca3b6..1203652a 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -4,7 +4,7 @@ noinst_LIBRARIES = libhelper.a libhelper_a_SOURCES = oui.h oui.c list.h list.c \ textfile.h textfile.c helper.h helper.c \ glib-ectomy.h glib-ectomy.c logging.h logging.c \ - dbus.h dbus.c sdp-xml.h sdp-xml.c + dbus.h dbus.c sdp-xml.h sdp-xml.c sdp-expat.c noinst_PROGRAMS = test_textfile diff --git a/common/sdp-expat.c b/common/sdp-expat.c new file mode 100644 index 00000000..e69de29b -- cgit From 150f9b6873e4ec8473194bdfdc0b05b4d0d37158 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 13 Nov 2006 07:17:40 +0000 Subject: Add Expat library check and dummy skeleton --- common/Makefile.am | 10 ++++++++-- common/sdp-dummy.c | 0 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 common/sdp-dummy.c (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index 1203652a..182d574e 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -1,10 +1,16 @@ +if EXPAT +sdp_sources = sdp-expat.c +else +sdp_sources = sdp-dummy.c +endif + noinst_LIBRARIES = libhelper.a libhelper_a_SOURCES = oui.h oui.c list.h list.c \ textfile.h textfile.c helper.h helper.c \ glib-ectomy.h glib-ectomy.c logging.h logging.c \ - dbus.h dbus.c sdp-xml.h sdp-xml.c sdp-expat.c + dbus.h dbus.c sdp-xml.h sdp-xml.c $(sdp_sources) noinst_PROGRAMS = test_textfile @@ -12,6 +18,6 @@ test_textfile_LDADD = libhelper.a AM_CFLAGS = @DBUS_CFLAGS@ -EXTRA_DIST = ppoll.h +EXTRA_DIST = ppoll.h sdp-dummy.c sdp-expat.c MAINTAINERCLEANFILES = Makefile.in diff --git a/common/sdp-dummy.c b/common/sdp-dummy.c new file mode 100644 index 00000000..e69de29b -- cgit From 0ff36a95d3ab972290c3d66bad6e721298cf0ba3 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 13 Nov 2006 07:28:02 +0000 Subject: Link the Expat library --- common/Makefile.am | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index 182d574e..f709ecab 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -1,8 +1,10 @@ if EXPAT sdp_sources = sdp-expat.c +sdp_libadd = /usr/lib/libexpat.a else sdp_sources = sdp-dummy.c +sdp_libadd = endif noinst_LIBRARIES = libhelper.a @@ -12,6 +14,8 @@ libhelper_a_SOURCES = oui.h oui.c list.h list.c \ glib-ectomy.h glib-ectomy.c logging.h logging.c \ dbus.h dbus.c sdp-xml.h sdp-xml.c $(sdp_sources) +libhelper_a_LIBADD = $(sdp_libadd) + noinst_PROGRAMS = test_textfile test_textfile_LDADD = libhelper.a -- cgit From b1a10a46b1cdeb034823b83c993836b0dce3ed06 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 13 Nov 2006 07:38:20 +0000 Subject: Cleanup SDP XML support --- common/sdp-dummy.c | 28 ++++++++++++++++++++++++++++ common/sdp-expat.c | 33 +++++++++++++++++++++++++++++++++ common/sdp-xml.c | 21 +++++++++++---------- common/sdp-xml.h | 14 ++++++-------- 4 files changed, 78 insertions(+), 18 deletions(-) (limited to 'common') diff --git a/common/sdp-dummy.c b/common/sdp-dummy.c index e69de29b..8ed637e7 100644 --- a/common/sdp-dummy.c +++ b/common/sdp-dummy.c @@ -0,0 +1,28 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2005-2006 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "sdp-xml.h" diff --git a/common/sdp-expat.c b/common/sdp-expat.c index e69de29b..0ab15d7a 100644 --- a/common/sdp-expat.c +++ b/common/sdp-expat.c @@ -0,0 +1,33 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2005-2006 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include + +#include "sdp-xml.h" diff --git a/common/sdp-xml.c b/common/sdp-xml.c index 5c6dd877..ee5601ee 100644 --- a/common/sdp-xml.c +++ b/common/sdp-xml.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2005-2006 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify @@ -25,20 +25,23 @@ #include #endif -#include "sdp-xml.h" - #include -#include -#include +#include +#include #include +#include #include +#include +#include + +#include "sdp-xml.h" + #define STRBUFSIZE 256 #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]; @@ -381,8 +384,7 @@ static void convert_raw_attr_to_xml_func(void *val, void *data) (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; @@ -397,4 +399,3 @@ void convert_sdp_record_to_xml(sdp_record_t *rec, appender(data, "\n"); } } - diff --git a/common/sdp-xml.h b/common/sdp-xml.h index fe781f57..5e6bb7ce 100644 --- a/common/sdp-xml.h +++ b/common/sdp-xml.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2005-2006 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify @@ -22,14 +22,12 @@ */ -#ifndef __SDP_XML_H__ -#define __SDP_XML_H__ +#ifndef __SDP_XML_H +#define __SDP_XML_H -#include #include -void convert_sdp_record_to_xml(sdp_record_t * rec, - void *userData, - void (*appendFunc) (void *, const char *)); +void convert_sdp_record_to_xml(sdp_record_t *rec, + void *user_data, void (*append_func) (void *, const char *)); -#endif /* __SDP_XML_H__ */ +#endif /* __SDP_XML_H */ -- cgit From 40e3342c520a00d47d68f7791cb70cb49d698630 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 13 Nov 2006 07:58:40 +0000 Subject: Add D-Bus name setup to common function --- common/dbus.c | 25 ++++++++++++++++++++----- common/dbus.h | 2 +- 2 files changed, 21 insertions(+), 6 deletions(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index 5ef1725e..c8ed07e4 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -483,19 +483,18 @@ static void dispatch_status_cb(DBusConnection *conn, g_timeout_add(DISPATCH_TIMEOUT, message_dispatch_cb, data); } -DBusConnection *init_dbus(void (*disconnect_cb)(void *), void *user_data) +DBusConnection *init_dbus(const char *name, void (*disconnect_cb)(void *), void *user_data) { + struct disconnect_data *dc_data; DBusConnection *conn; DBusError err; - struct disconnect_data *dc_data; dbus_error_init(&err); conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); if (dbus_error_is_set(&err)) { - error("Can't open system message bus connection: %s", - err.message); + error("Can't connect to system message bus: %s", err.message); dbus_error_free(&err); return NULL; } @@ -507,7 +506,23 @@ DBusConnection *init_dbus(void (*disconnect_cb)(void *), void *user_data) timeout_toggled, conn, NULL); dbus_connection_set_dispatch_status_function(conn, dispatch_status_cb, - conn, NULL); + conn, NULL); + + if (name) { + dbus_error_init(&err); + + if (dbus_bus_request_name(conn, name, 0, &err) != + DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER ) { + error("Could not become the primary owner of %s.", name); + return NULL; + } + + if (dbus_error_is_set(&err)) { + error("Can't get bus name %s: %s", name, err.message); + dbus_error_free(&err); + return NULL; + } + } if (!disconnect_cb) return conn; diff --git a/common/dbus.h b/common/dbus.h index 59afd6e6..39d3cd88 100644 --- a/common/dbus.h +++ b/common/dbus.h @@ -26,7 +26,7 @@ #include -DBusConnection *init_dbus(void (*disconnect_cb)(void *), void *user_data); +DBusConnection *init_dbus(const char *name, void (*disconnect_cb)(void *), void *user_data); typedef void (*name_cb_t)(const char *name, void *user_data); -- cgit From 7d1722afcf324d700515f5fc5f4face2e665ce07 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 17 Nov 2006 16:16:34 +0000 Subject: Fix linking with expat library --- common/Makefile.am | 4 ---- 1 file changed, 4 deletions(-) (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index f709ecab..182d574e 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -1,10 +1,8 @@ if EXPAT sdp_sources = sdp-expat.c -sdp_libadd = /usr/lib/libexpat.a else sdp_sources = sdp-dummy.c -sdp_libadd = endif noinst_LIBRARIES = libhelper.a @@ -14,8 +12,6 @@ libhelper_a_SOURCES = oui.h oui.c list.h list.c \ glib-ectomy.h glib-ectomy.c logging.h logging.c \ dbus.h dbus.c sdp-xml.h sdp-xml.c $(sdp_sources) -libhelper_a_LIBADD = $(sdp_libadd) - noinst_PROGRAMS = test_textfile test_textfile_LDADD = libhelper.a -- cgit From 214cc18ef97fcaa0a4c3746e183caf5820bc811b Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 22 Nov 2006 06:06:36 +0000 Subject: Add first draft XML based service record registration --- common/sdp-dummy.c | 11 ++ common/sdp-expat.c | 381 +++++++++++++++++++++++++++++++++++++++++++++++++++++ common/sdp-xml.c | 354 +++++++++++++++++++++++++++++++++++++++++++++---- common/sdp-xml.h | 11 ++ 4 files changed, 731 insertions(+), 26 deletions(-) (limited to 'common') diff --git a/common/sdp-dummy.c b/common/sdp-dummy.c index 8ed637e7..b1f74df7 100644 --- a/common/sdp-dummy.c +++ b/common/sdp-dummy.c @@ -25,4 +25,15 @@ #include #endif +#include +#include + +#include "logging.h" #include "sdp-xml.h" + +sdp_record_t *sdp_xml_parse_record(const char *data, int size) +{ + error("No XML parser available"); + + return -1; +} diff --git a/common/sdp-expat.c b/common/sdp-expat.c index 0ab15d7a..cc2ff575 100644 --- a/common/sdp-expat.c +++ b/common/sdp-expat.c @@ -25,9 +25,390 @@ #include #endif +#include +#include +#include + #include #include #include +#include "logging.h" #include "sdp-xml.h" + +/* Expat specific implementation of the context struct */ + +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 */ + struct sdp_xml_data *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 */ + struct sdp_xml_data *stack_head; /* Top of the stack of attributes */ + int attrId; /* Id of the most recently processed attribute */ +}; + +#define DEFAULT_XML_DATA_SIZE 1024 + +static struct sdp_xml_data *sdp_xml_data_alloc() +{ + struct sdp_xml_data *elem; + + elem = malloc(sizeof(struct sdp_xml_data)); + + /* Null terminate the text */ + elem->size = DEFAULT_XML_DATA_SIZE; + elem->text = malloc(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(struct sdp_xml_data *elem) +{ + if (elem->data) + sdp_data_free(elem->data); + + if (elem->name) + free(elem->name); + + free(elem->text); + free(elem); +} + +static struct sdp_xml_data *sdp_xml_data_expand(struct sdp_xml_data *elem) +{ + char *newbuf; + + newbuf = 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, + struct sdp_xml_context *context) +{ + const char *data = context->stack_head->text; + + if (!strcmp(el, "bool")) + return sdp_xml_parse_int(data, SDP_BOOL); + else if (!strcmp(el, "uint8")) + return sdp_xml_parse_int(data, SDP_UINT8); + else if (!strcmp(el, "uint16")) + return sdp_xml_parse_int(data, SDP_UINT16); + else if (!strcmp(el, "uint32")) + return sdp_xml_parse_int(data, SDP_UINT32); + else if (!strcmp(el, "uint64")) + return sdp_xml_parse_int(data, SDP_UINT64); + else if (!strcmp(el, "uint128")) + return sdp_xml_parse_int(data, SDP_UINT128); + else if (!strcmp(el, "int8")) + return sdp_xml_parse_int(data, SDP_INT8); + else if (!strcmp(el, "int16")) + return sdp_xml_parse_int(data, SDP_INT16); + else if (!strcmp(el, "int32")) + return sdp_xml_parse_int(data, SDP_INT32); + else if (!strcmp(el, "int64")) + return sdp_xml_parse_int(data, SDP_INT64); + else if (!strcmp(el, "int128")) + return sdp_xml_parse_int(data, SDP_INT128); + else if (!strcmp(el, "uuid")) + return sdp_xml_parse_uuid(data); + else if (!strcmp(el, "url")) + return sdp_xml_parse_url(data); + else if (!strcmp(el, "text")) + return sdp_xml_parse_text(data, context->stack_head->type); + else if (!strcmp(el, "nil")) + return sdp_xml_parse_nil(data); + + return NULL; +} + +static void convert_xml_to_sdp_start(void *data, const char *el, const char **attr) +{ + struct sdp_xml_context *context = data; + int i; + + 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) { + struct sdp_xml_data *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) +{ + struct sdp_xml_context *context = data; + struct sdp_xml_data *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); + } +} + +static struct sdp_xml_context *sdp_xml_init_context() +{ + struct sdp_xml_context *context; + + context = malloc(sizeof(struct 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; +} + +static void sdp_xml_free_context(struct sdp_xml_context *context) +{ + struct sdp_xml_data *elem; + + /* Free the stack */ + while (context->stack_head) { + elem = context->stack_head; + context->stack_head = elem->next; + sdp_xml_data_free(elem); + } + + XML_ParserFree(context->parser); + + free(context); +} + +static int sdp_xml_parse_chunk(struct sdp_xml_context *context, + const char *data, int size, int final) +{ + if (!XML_Parse(context->parser, data, size, final)) { + error("Parse error at line %d: %s\n", + XML_GetCurrentLineNumber(context->parser), + XML_ErrorString(XML_GetErrorCode(context->parser))); + return -1; + } + + return 0; +} + +sdp_record_t *sdp_xml_parse_record(const char *data, int size) +{ + struct sdp_xml_context *context; + sdp_record_t *record; + + context = sdp_xml_init_context(); + + if (sdp_xml_parse_chunk(context, data, size, 1) < 0) { + sdp_record_free(context->sdprec); + sdp_xml_free_context(context); + return NULL; + } + + record = context->sdprec; + + sdp_xml_free_context(context); + + return record; +} diff --git a/common/sdp-xml.c b/common/sdp-xml.c index ee5601ee..8b290b88 100644 --- a/common/sdp-xml.c +++ b/common/sdp-xml.c @@ -31,17 +31,20 @@ #include #include #include +#include #include #include +#include "logging.h" + #include "sdp-xml.h" -#define STRBUFSIZE 256 +#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]; @@ -70,12 +73,14 @@ static void convert_raw_data_to_xml(sdp_data_t *value, int indent_level, appender(data, indent); appender(data, "\n"); break; + case SDP_BOOL: appender(data, indent); appender(data, "val.uint8 ? "true" : "false"); appender(data, "\" />\n"); break; + case SDP_UINT8: appender(data, indent); appender(data, "\n"); break; + case SDP_UINT16: appender(data, indent); appender(data, "\n"); break; + case SDP_UINT32: appender(data, indent); appender(data, "\n"); break; + case SDP_UINT64: appender(data, indent); appender(data, "\n"); break; + case SDP_UINT128: appender(data, indent); appender(data, "\n"); break; + case SDP_INT8: appender(data, indent); appender(data, "\n"); break; + case SDP_INT16: appender(data, indent); appender(data, "\n"); break; + case SDP_INT32: appender(data, indent); appender(data, "\n"); break; + case SDP_INT64: appender(data, indent); appender(data, "\n"); break; + case SDP_INT128: appender(data, indent); appender(data, "\n"); break; + case SDP_UUID16: appender(data, indent); appender(data, "val.uuid.value.uuid16); + snprintf(buf, STRBUFSIZE - 1, "0x%04x", value->val.uuid.value.uuid16); appender(data, buf); appender(data, "\" />\n"); break; + case SDP_UUID32: appender(data, indent); appender(data, "val.uuid.value.uuid32); + snprintf(buf, STRBUFSIZE - 1, "0x%08x", value->val.uuid.value.uuid32); appender(data, buf); appender(data, "\" />\n"); break; + case SDP_UUID128: appender(data, indent); appender(data, "\n"); break; + case SDP_TEXT_STR8: case SDP_TEXT_STR16: case SDP_TEXT_STR32: @@ -256,7 +272,7 @@ static void convert_raw_data_to_xml(sdp_data_t *value, int indent_level, 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]); @@ -306,6 +322,7 @@ static void convert_raw_data_to_xml(sdp_data_t *value, int indent_level, free(strBuf); break; } + case SDP_URL_STR8: case SDP_URL_STR16: case SDP_URL_STR32: @@ -314,6 +331,7 @@ static void convert_raw_data_to_xml(sdp_data_t *value, int indent_level, appender(data, value->val.str); appender(data, "\" />\n"); break; + case SDP_SEQ8: case SDP_SEQ16: case SDP_SEQ32: @@ -321,13 +339,13 @@ static void convert_raw_data_to_xml(sdp_data_t *value, int indent_level, appender(data, "\n"); convert_raw_data_to_xml(value->val.dataseq, - indent_level + 1, data, - appender); + indent_level + 1, data, appender); appender(data, indent); appender(data, "\n"); break; + case SDP_ALT8: case SDP_ALT16: case SDP_ALT32: @@ -336,25 +354,20 @@ static void convert_raw_data_to_xml(sdp_data_t *value, int indent_level, appender(data, "\n"); convert_raw_data_to_xml(value->val.dataseq, - indent_level + 1, data, - appender); + indent_level + 1, data, appender); appender(data, indent); appender(data, "\n"); - break; - default: break; } - convert_raw_data_to_xml(value->next, indent_level, data, - appender); + 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) @@ -369,8 +382,7 @@ static void convert_raw_attr_to_xml_func(void *val, void *data) cd->appender(cd->data, buf); if (data) - convert_raw_data_to_xml(value, 2, cd->data, - cd->appender); + convert_raw_data_to_xml(value, 2, cd->data, cd->appender); else cd->appender(cd->data, "\t\tNULL\n"); @@ -378,13 +390,13 @@ static void convert_raw_attr_to_xml_func(void *val, void *data) } /* - Will convert the sdp record to XML. The appender and data can be used - 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. -*/ + * Will convert the sdp record to XML. The appender and data can be used + * 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; @@ -399,3 +411,293 @@ void convert_sdp_record_to_xml(sdp_record_t *rec, appender(data, "\n"); } } + +static 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; + uint32_t val; + uint16_t val2 = val; + + len = strlen(data); + + if (len == 36) + return sdp_xml_parse_uuid128(data); + + val = strtoll(data, &endptr, 16); + + /* Couldn't parse */ + if (*endptr != '\0') + return NULL; + + if (val > USHRT_MAX) + return sdp_data_alloc(SDP_UUID32, &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; +} + +static 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 char *sdp_xml_parse_text_decode(const char *data, char encoding, uint32_t *length) +{ + int len = strlen(data); + char *text; + + if (encoding == SDP_XML_ENCODING_NORMAL) { + text = strdup(data); + *length = len; + } else { + char buf[3], *decoded; + int i; + + decoded = malloc((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; + *length = len >> 1; + } + + return text; +} + +#if 0 +static sdp_data_t *sdp_xml_parse_text_with_size(const char *data, char encoding, uint8_t dtd) +{ + char *text; + uint32_t length; + sdp_data_t *ret; + + text = sdp_xml_parse_text_decode(data, encoding, &length); + ret = sdp_data_alloc_with_length(dtd, text, length); + + debug("Unit size %d length %d: -->%s<--\n", ret->unitSize, length, text); + + return ret; +} +#endif + +sdp_data_t *sdp_xml_parse_text(const char *data, char encoding) +{ + uint8_t dtd = SDP_TEXT_STR8; + char *text; + uint32_t length; + sdp_data_t *ret; + + text = sdp_xml_parse_text_decode(data, encoding, &length); + + if (length > UCHAR_MAX) + dtd = SDP_TEXT_STR16; + + ret = sdp_data_alloc_with_length(dtd, text, length); + + debug("Unit size %d length %d: -->%s<--\n", ret->unitSize, length, text); + + return ret; +} + +sdp_data_t *sdp_xml_parse_nil(const char *data) +{ + return sdp_data_alloc(SDP_DATA_NIL, 0); +} diff --git a/common/sdp-xml.h b/common/sdp-xml.h index 5e6bb7ce..16bea948 100644 --- a/common/sdp-xml.h +++ b/common/sdp-xml.h @@ -27,7 +27,18 @@ #include +#define SDP_XML_ENCODING_NORMAL 0 +#define SDP_XML_ENCODING_HEX 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_url(const char *data); +sdp_data_t *sdp_xml_parse_int(const char *data, uint8_t dtd); +sdp_data_t *sdp_xml_parse_uuid(const char *data); + +sdp_record_t *sdp_xml_parse_record(const char *data, int size); + #endif /* __SDP_XML_H */ -- cgit From 6cb273616dd0ff36eb5320387db84346bd0c478e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 22 Nov 2006 06:17:12 +0000 Subject: Fix UUID16 parsing --- common/sdp-xml.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'common') diff --git a/common/sdp-xml.c b/common/sdp-xml.c index 8b290b88..9fe5b087 100644 --- a/common/sdp-xml.c +++ b/common/sdp-xml.c @@ -445,7 +445,7 @@ sdp_data_t *sdp_xml_parse_uuid(const char *data) int len; char *endptr; uint32_t val; - uint16_t val2 = val; + uint16_t val2; len = strlen(data); @@ -461,6 +461,8 @@ sdp_data_t *sdp_xml_parse_uuid(const char *data) if (val > USHRT_MAX) return sdp_data_alloc(SDP_UUID32, &val); + val2 = val; + return sdp_data_alloc(SDP_UUID16, &val2); /* Should never get here */ -- cgit From b2afe935ff341cd05e90db4cc636574e3ce98d89 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 22 Nov 2006 06:19:35 +0000 Subject: Use "boolean" instead of "bool" --- common/sdp-expat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common') diff --git a/common/sdp-expat.c b/common/sdp-expat.c index cc2ff575..a3b4048d 100644 --- a/common/sdp-expat.c +++ b/common/sdp-expat.c @@ -112,7 +112,7 @@ static sdp_data_t *sdp_xml_parse_datatype(const char *el, { const char *data = context->stack_head->text; - if (!strcmp(el, "bool")) + if (!strcmp(el, "boolean")) return sdp_xml_parse_int(data, SDP_BOOL); else if (!strcmp(el, "uint8")) return sdp_xml_parse_int(data, SDP_UINT8); -- cgit From dece25be6d34c098514ada240a52e13b6c8946c1 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 9 Jan 2007 16:57:24 +0000 Subject: Return NULL in case of the dummy XML parser --- common/sdp-dummy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common') diff --git a/common/sdp-dummy.c b/common/sdp-dummy.c index b1f74df7..434bfbc2 100644 --- a/common/sdp-dummy.c +++ b/common/sdp-dummy.c @@ -35,5 +35,5 @@ sdp_record_t *sdp_xml_parse_record(const char *data, int size) { error("No XML parser available"); - return -1; + return NULL; } -- cgit From c97480f11bdfdc3cbb867b8127074bcb6b047024 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 12 Jan 2007 00:37:42 +0000 Subject: Allow compilation against GLib --- common/Makefile.am | 17 +++++++++++++---- common/dbus.c | 1 + common/glib-ectomy.h | 8 ++++++++ 3 files changed, 22 insertions(+), 4 deletions(-) (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index 182d574e..3774edf9 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -5,19 +5,28 @@ else sdp_sources = sdp-dummy.c endif +if GLIB +glib_sources = +glib_cflags = @GLIB_CFLAGS@ +else +glib_sources = glib-ectomy.c +glib_cflags = +endif + noinst_LIBRARIES = libhelper.a libhelper_a_SOURCES = oui.h oui.c list.h list.c \ textfile.h textfile.c helper.h helper.c \ - glib-ectomy.h glib-ectomy.c logging.h logging.c \ - dbus.h dbus.c sdp-xml.h sdp-xml.c $(sdp_sources) + logging.h logging.c dbus.h dbus.c \ + sdp-xml.h sdp-xml.c $(sdp_sources) \ + glib-ectomy.h $(glib_sources) noinst_PROGRAMS = test_textfile test_textfile_LDADD = libhelper.a -AM_CFLAGS = @DBUS_CFLAGS@ +AM_CFLAGS = @DBUS_CFLAGS@ $(glib_cflags) -EXTRA_DIST = ppoll.h sdp-dummy.c sdp-expat.c +EXTRA_DIST = ppoll.h sdp-dummy.c sdp-expat.c glib-ectomy.c MAINTAINERCLEANFILES = Makefile.in diff --git a/common/dbus.c b/common/dbus.c index c8ed07e4..eb8c77f3 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include diff --git a/common/glib-ectomy.h b/common/glib-ectomy.h index 411cc25f..8502deb5 100644 --- a/common/glib-ectomy.h +++ b/common/glib-ectomy.h @@ -1,6 +1,12 @@ #ifndef __GLIB_ECTOMY_H #define __GLIB_ECTOMY_H +#ifdef HAVE_GLIB +#include +#define g_timeout_remove g_source_remove +#define g_io_remove_watch g_source_remove +#else + #include #include @@ -106,4 +112,6 @@ gboolean g_utf8_validate(const gchar *str, gssize max_len, const gchar **end); #define g_main_quit(loop) g_main_loop_quit(loop) #define g_main_unref(loop) g_main_loop_unref(loop) +#endif + #endif /* __GLIB_ECTOMY_H */ -- cgit From f711e58f8f635d0afcf3f02da83780bef83c4347 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sat, 13 Jan 2007 12:27:09 +0000 Subject: Rename struct slist to GSList and slist_* to g_slist_* --- common/Makefile.am | 2 +- common/dbus.c | 29 +++--- common/glib-ectomy.c | 256 +++++++++++++++++++++++++++++++++++++++++++++------ common/glib-ectomy.h | 30 ++++++ common/list.c | 234 ---------------------------------------------- common/list.h | 54 ----------- 6 files changed, 273 insertions(+), 332 deletions(-) delete mode 100644 common/list.c delete mode 100644 common/list.h (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index 3774edf9..eb6e62b0 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -15,7 +15,7 @@ endif noinst_LIBRARIES = libhelper.a -libhelper_a_SOURCES = oui.h oui.c list.h list.c \ +libhelper_a_SOURCES = oui.h oui.c \ textfile.h textfile.c helper.h helper.c \ logging.h logging.c dbus.h dbus.c \ sdp-xml.h sdp-xml.c $(sdp_sources) \ diff --git a/common/dbus.c b/common/dbus.c index eb8c77f3..2162feab 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -37,13 +37,12 @@ #include "glib-ectomy.h" #include "dbus.h" #include "logging.h" -#include "list.h" #define DISPATCH_TIMEOUT 0 static int name_listener_initialized = 0; -static struct slist *name_listeners = NULL; +static GSList *name_listeners = NULL; typedef struct { uint32_t id; @@ -68,12 +67,12 @@ struct name_callback { struct name_data { char *name; - struct slist *callbacks; + GSList *callbacks; }; static struct name_data *name_data_find(const char *name) { - struct slist *current; + GSList *current; for (current = name_listeners; current != NULL; current = current->next) { struct name_data *data = current->data; @@ -84,10 +83,10 @@ static struct name_data *name_data_find(const char *name) return NULL; } -static struct name_callback *name_callback_find(struct slist *callbacks, +static struct name_callback *name_callback_find(GSList *callbacks, name_cb_t func, void *user_data) { - struct slist *current; + GSList *current; for (current = callbacks; current != NULL; current = current->next) { struct name_callback *cb = current->data; @@ -100,12 +99,12 @@ static struct name_callback *name_callback_find(struct slist *callbacks, static void name_data_free(struct name_data *data) { - struct slist *l; + GSList *l; for (l = data->callbacks; l != NULL; l = l->next) free(l->data); - slist_free(data->callbacks); + g_slist_free(data->callbacks); if (data->name) free(data->name); @@ -142,10 +141,10 @@ static int name_data_add(const char *name, name_cb_t func, void *user_data) if (!data->name) goto failed; - name_listeners = slist_append(name_listeners, data); + name_listeners = g_slist_append(name_listeners, data); done: - data->callbacks = slist_append(data->callbacks, cb); + data->callbacks = g_slist_append(data->callbacks, cb); return first; failed: @@ -169,12 +168,12 @@ static void name_data_remove(const char *name, name_cb_t func, void *user_data) cb = name_callback_find(data->callbacks, func, user_data); if (cb) { - data->callbacks = slist_remove(data->callbacks, cb); + data->callbacks = g_slist_remove(data->callbacks, cb); free(cb); } if (!data->callbacks) { - name_listeners = slist_remove(name_listeners, data); + name_listeners = g_slist_remove(name_listeners, data); name_data_free(data); } } @@ -182,7 +181,7 @@ static void name_data_remove(const char *name, name_cb_t func, void *user_data) static DBusHandlerResult name_exit_filter(DBusConnection *connection, DBusMessage *message, void *user_data) { - struct slist *l; + GSList *l; struct name_data *data; char *name, *old, *new; @@ -214,7 +213,7 @@ static DBusHandlerResult name_exit_filter(DBusConnection *connection, cb->func(name, cb->user_data); } - name_listeners = slist_remove(name_listeners, data); + name_listeners = g_slist_remove(name_listeners, data); name_data_free(data); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -283,7 +282,7 @@ int name_listener_remove(DBusConnection *connection, const char *name, return -1; } - data->callbacks = slist_remove(data->callbacks, cb); + data->callbacks = g_slist_remove(data->callbacks, cb); free(cb); /* Don't remove the filter if other callbacks exist */ diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c index 46d92154..b45d26f4 100644 --- a/common/glib-ectomy.c +++ b/common/glib-ectomy.c @@ -13,7 +13,6 @@ #include #include -#include "list.h" #include "glib-ectomy.h" struct timeout { @@ -34,12 +33,12 @@ struct _GMainContext { guint next_id; glong next_timeout; - struct slist *timeouts; - struct slist *proc_timeouts; + GSList *timeouts; + GSList *proc_timeouts; gboolean timeout_lock; - struct slist *watches; - struct slist *proc_watches; + GSList *watches; + GSList *proc_watches; gboolean watch_lock; }; @@ -174,7 +173,7 @@ static GMainContext *g_main_context_default() void g_io_remove_watch(guint id) { GMainContext *context = g_main_context_default(); - struct slist *l; + GSList *l; struct watch *w; if (!context) @@ -186,7 +185,7 @@ void g_io_remove_watch(guint id) if (w->id != id) continue; - context->watches = slist_remove(context->watches, w); + context->watches = g_slist_remove(context->watches, w); watch_free(w); return; @@ -198,7 +197,7 @@ void g_io_remove_watch(guint id) if (w->id != id) continue; - context->proc_watches = slist_remove(context->proc_watches, w); + context->proc_watches = g_slist_remove(context->proc_watches, w); watch_free(w); return; @@ -210,7 +209,7 @@ int watch_prio_cmp(struct watch *w1, struct watch *w2) return w1->priority - w2->priority; } -#define watch_list_add(l, w) slist_insert_sorted((l), (w), (cmp_func_t) watch_prio_cmp) +#define watch_list_add(l, w) g_slist_insert_sorted((l), (w), (GCompareFunc) watch_prio_cmp) guint g_io_add_watch_full(GIOChannel *channel, gint priority, GIOCondition condition, GIOFunc func, @@ -273,7 +272,7 @@ GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running) static void timeout_handlers_prepare(GMainContext *context) { - struct slist *l; + GSList *l; struct timeval tv; glong msec, timeout = LONG_MAX; @@ -314,8 +313,8 @@ static void timeout_handlers_check(GMainContext *context) gboolean ret; if (timercmp(&tv, &t->expiration, <)) { - context->timeouts = slist_remove(context->timeouts, t); - context->proc_timeouts = slist_append(context->proc_timeouts, t); + context->timeouts = g_slist_remove(context->timeouts, t); + context->proc_timeouts = g_slist_append(context->proc_timeouts, t); continue; } @@ -323,10 +322,10 @@ static void timeout_handlers_check(GMainContext *context) /* Check if the handler was removed/freed by the callback * function */ - if (!slist_find(context->timeouts, t, ptr_cmp)) + if (!g_slist_find_custom(context->timeouts, t, ptr_cmp)) continue; - context->timeouts = slist_remove(context->timeouts, t); + context->timeouts = g_slist_remove(context->timeouts, t); if (!ret) { free(t); @@ -344,7 +343,7 @@ static void timeout_handlers_check(GMainContext *context) t->expiration.tv_sec++; } - context->proc_timeouts = slist_append(context->proc_timeouts, t); + context->proc_timeouts = g_slist_append(context->proc_timeouts, t); } context->timeouts = context->proc_timeouts; @@ -366,7 +365,7 @@ void g_main_loop_run(GMainLoop *loop) while (loop->is_running) { int nfds; - struct slist *l; + GSList *l; struct watch *w; for (nfds = 0, l = context->watches; l != NULL; l = l->next, nfds++) { @@ -391,7 +390,7 @@ void g_main_loop_run(GMainLoop *loop) w = context->watches->data; if (!*w->revents) { - context->watches = slist_remove(context->watches, w); + context->watches = g_slist_remove(context->watches, w); context->proc_watches = watch_list_add(context->proc_watches, w); continue; } @@ -400,10 +399,10 @@ void g_main_loop_run(GMainLoop *loop) /* Check if the watch was removed/freed by the callback * function */ - if (!slist_find(context->watches, w, ptr_cmp)) + if (!g_slist_find_custom(context->watches, w, ptr_cmp)) continue; - context->watches = slist_remove(context->watches, w); + context->watches = g_slist_remove(context->watches, w); if (!ret) { watch_free(w); @@ -434,11 +433,11 @@ void g_main_loop_unref(GMainLoop *loop) if (!loop->context) return; - slist_foreach(loop->context->watches, (slist_func_t)watch_free, NULL); - slist_free(loop->context->watches); + g_slist_foreach(loop->context->watches, (GFunc)watch_free, NULL); + g_slist_free(loop->context->watches); - slist_foreach(loop->context->timeouts, (slist_func_t)free, NULL); - slist_free(loop->context->timeouts); + g_slist_foreach(loop->context->timeouts, (GFunc)free, NULL); + g_slist_free(loop->context->timeouts); free(loop->context); loop->context = NULL; @@ -482,9 +481,9 @@ guint g_timeout_add(guint interval, GSourceFunc function, gpointer data) t->id = context->next_id++; if (context->timeout_lock) - context->proc_timeouts = slist_prepend(context->proc_timeouts, t); + context->proc_timeouts = g_slist_prepend(context->proc_timeouts, t); else - context->timeouts = slist_prepend(context->timeouts, t); + context->timeouts = g_slist_prepend(context->timeouts, t); return t->id; } @@ -492,7 +491,7 @@ guint g_timeout_add(guint interval, GSourceFunc function, gpointer data) gint g_timeout_remove(const guint id) { GMainContext *context = g_main_context_default(); - struct slist *l; + GSList *l; struct timeout *t; if (!context) @@ -507,7 +506,7 @@ gint g_timeout_remove(const guint id) if (t->id != id) continue; - context->timeouts = slist_remove(context->timeouts, t); + context->timeouts = g_slist_remove(context->timeouts, t); free(t); return 0; @@ -522,7 +521,7 @@ gint g_timeout_remove(const guint id) if (t->id != id) continue; - context->proc_timeouts = slist_remove(context->proc_timeouts, t); + context->proc_timeouts = g_slist_remove(context->proc_timeouts, t); free(t); return 0; @@ -616,4 +615,205 @@ failed: return FALSE; } +/* GSList functions */ +GSList *g_slist_append(GSList *list, void *data) +{ + GSList *entry, *tail; + + entry = malloc(sizeof(GSList)); + /* FIXME: this currently just silently fails */ + if (!entry) + return list; + + entry->data = data; + entry->next = NULL; + + if (!list) + return entry; + + /* Find the end of the list */ + for (tail = list; tail->next; tail = tail->next); + + tail->next = entry; + + return list; +} + +GSList *g_slist_prepend(GSList *list, void *data) +{ + GSList *entry; + + entry = malloc(sizeof(GSList)); + /* FIXME: this currently just silently fails */ + if (!entry) + return list; + + entry->data = data; + entry->next = list; + + return entry; +} + +GSList *g_slist_insert_sorted(GSList *list, void *data, GCompareFunc cmp_func) +{ + GSList *tmp, *prev, *entry; + int cmp; + + entry = malloc(sizeof(GSList)); + if (!entry) + return list; + + entry->data = data; + entry->next = NULL; + + if (!list) + return entry; + + prev = NULL; + tmp = list; + + cmp = cmp_func(data, tmp->data); + + while (tmp->next && cmp > 0) { + prev = tmp; + tmp = tmp->next; + + cmp = cmp_func(data, tmp->data); + } + + if (!tmp->next && cmp > 0) { + tmp->next = entry; + return list; + } + + if (prev) { + prev->next = entry; + entry->next = tmp; + return list; + } else { + entry->next = list; + return entry; + } +} + +GSList *g_slist_remove(GSList *list, void *data) +{ + GSList *l, *next, *prev = NULL, *match = NULL; + + if (!list) + return NULL; + + for (l = list; l != NULL; l = l->next) { + if (l->data == data) { + match = l; + break; + } + prev = l; + } + + if (!match) + return list; + + next = match->next; + + free(match); + + /* If the head was removed, return the next element */ + if (!prev) + return next; + + prev->next = next; + + return list; +} + +GSList *g_slist_find_custom(GSList *list, const void *data, + GCompareFunc cmp_func) +{ + GSList *l; + + for (l = list; l != NULL; l = l->next) { + if (!cmp_func(l->data, data)) + return l; + } + + return NULL; +} + +static GSList *g_slist_sort_merge(GSList *l1, GSList *l2, + GCompareFunc cmp_func) +{ + GSList list, *l; + int cmp; + + l = &list; + + while (l1 && l2) { + cmp = cmp_func(l1->data, l2->data); + + if (cmp <= 0) { + l = l->next = l1; + l1 = l1->next; + } else { + l = l->next = l2; + l2 = l2->next; + } + } + + l->next = l1 ? l1 : l2; + + return list.next; +} + +GSList *g_slist_sort(GSList *list, GCompareFunc cmp_func) +{ + GSList *l1, *l2; + + if (!list || !list->next) + return list; + + l1 = list; + l2 = list->next; + + while ((l2 = l2->next) != NULL) { + if ((l2 = l2->next) == NULL) + break; + l1 = l1->next; + } + + l2 = l1->next; + l1->next = NULL; + + return g_slist_sort_merge(g_slist_sort(list, cmp_func), + g_slist_sort(l2, cmp_func), cmp_func); +} + +int g_slist_length(GSList *list) +{ + int len; + + for (len = 0; list != NULL; list = list->next) + len++; + + return len; +} + +void g_slist_foreach(GSList *list, GFunc func, void *user_data) +{ + while (list) { + GSList *next = list->next; + func(list->data, user_data); + list = next; + } +} + +void g_slist_free(GSList *list) +{ + GSList *l, *next; + + for (l = list; l != NULL; l = next) { + next = l->next; + free(l); + } +} diff --git a/common/glib-ectomy.h b/common/glib-ectomy.h index 8502deb5..02fa0230 100644 --- a/common/glib-ectomy.h +++ b/common/glib-ectomy.h @@ -112,6 +112,36 @@ gboolean g_utf8_validate(const gchar *str, gssize max_len, const gchar **end); #define g_main_quit(loop) g_main_loop_quit(loop) #define g_main_unref(loop) g_main_loop_unref(loop) +/* Begin GSList declarations */ + +typedef struct _GSList { + void *data; + struct _GSList *next; +} GSList; + +typedef int (*GCompareFunc)(const void *a, const void *b); +typedef void (*GFunc)(void *data, void *user_data); + +GSList *g_slist_append(GSList *list, void *data); + +GSList *g_slist_prepend(GSList *list, void *data); + +GSList *g_slist_insert_sorted(GSList *list, void *data, GCompareFunc cmp_func); + +GSList *g_slist_remove(GSList *list, void *data); + +GSList *g_slist_find_custom(GSList *list, const void *data, + GCompareFunc cmp_func); + +GSList *g_slist_sort(GSList *list, GCompareFunc cmp_func); + +int g_slist_length(GSList *list); + +void g_slist_foreach(GSList *list, GFunc func, void *user_data); +void g_slist_free(GSList *list); + +/* End GSList declarations */ + #endif #endif /* __GLIB_ECTOMY_H */ diff --git a/common/list.c b/common/list.c deleted file mode 100644 index 827f1789..00000000 --- a/common/list.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2006 Marcel Holtmann - * Copyright (C) 2005-2006 Johan Hedberg - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include "list.h" - -struct slist *slist_append(struct slist *list, void *data) -{ - struct slist *entry, *tail; - - entry = malloc(sizeof(struct slist)); - /* FIXME: this currently just silently fails */ - if (!entry) - return list; - - entry->data = data; - entry->next = NULL; - - if (!list) - return entry; - - /* Find the end of the list */ - for (tail = list; tail->next; tail = tail->next); - - tail->next = entry; - - return list; -} - -struct slist *slist_prepend(struct slist *list, void *data) -{ - struct slist *entry; - - entry = malloc(sizeof(struct slist)); - /* FIXME: this currently just silently fails */ - if (!entry) - return list; - - entry->data = data; - entry->next = list; - - return entry; -} - -struct slist *slist_insert_sorted(struct slist *list, void *data, cmp_func_t cmp_func) -{ - struct slist *tmp, *prev, *entry; - int cmp; - - entry = malloc(sizeof(struct slist)); - if (!entry) - return list; - - entry->data = data; - entry->next = NULL; - - if (!list) - return entry; - - prev = NULL; - tmp = list; - - cmp = cmp_func(data, tmp->data); - - while (tmp->next && cmp > 0) { - prev = tmp; - tmp = tmp->next; - - cmp = cmp_func(data, tmp->data); - } - - if (!tmp->next && cmp > 0) { - tmp->next = entry; - return list; - } - - if (prev) { - prev->next = entry; - entry->next = tmp; - return list; - } else { - entry->next = list; - return entry; - } -} - -struct slist *slist_remove(struct slist *list, void *data) -{ - struct slist *l, *next, *prev = NULL, *match = NULL; - - if (!list) - return NULL; - - for (l = list; l != NULL; l = l->next) { - if (l->data == data) { - match = l; - break; - } - prev = l; - } - - if (!match) - return list; - - next = match->next; - - free(match); - - /* If the head was removed, return the next element */ - if (!prev) - return next; - - prev->next = next; - - return list; -} - -struct slist *slist_find(struct slist *list, const void *data, - cmp_func_t cmp_func) -{ - struct slist *l; - - for (l = list; l != NULL; l = l->next) { - if (!cmp_func(l->data, data)) - return l; - } - - return NULL; -} - -static struct slist *slist_sort_merge(struct slist *l1, struct slist *l2, - cmp_func_t cmp_func) -{ - struct slist list, *l; - int cmp; - - l = &list; - - while (l1 && l2) { - cmp = cmp_func(l1->data, l2->data); - - if (cmp <= 0) { - l = l->next = l1; - l1 = l1->next; - } else { - l = l->next = l2; - l2 = l2->next; - } - } - - l->next = l1 ? l1 : l2; - - return list.next; -} - -struct slist *slist_sort(struct slist *list, cmp_func_t cmp_func) -{ - struct slist *l1, *l2; - - if (!list || !list->next) - return list; - - l1 = list; - l2 = list->next; - - while ((l2 = l2->next) != NULL) { - if ((l2 = l2->next) == NULL) - break; - l1 = l1->next; - } - - l2 = l1->next; - l1->next = NULL; - - return slist_sort_merge(slist_sort(list, cmp_func), - slist_sort(l2, cmp_func), cmp_func); -} - -int slist_length(struct slist *list) -{ - int len; - - for (len = 0; list != NULL; list = list->next) - len++; - - return len; -} - -void slist_foreach(struct slist *list, slist_func_t func, void *user_data) -{ - while (list) { - struct slist *next = list->next; - func(list->data, user_data); - list = next; - } -} - -void slist_free(struct slist *list) -{ - struct slist *l, *next; - - for (l = list; l != NULL; l = next) { - next = l->next; - free(l); - } -} diff --git a/common/list.h b/common/list.h deleted file mode 100644 index c11424ca..00000000 --- a/common/list.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2006 Marcel Holtmann - * Copyright (C) 2005-2006 Johan Hedberg - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifndef __LIST_H -#define __LIST_H - -struct slist { - void *data; - struct slist *next; -}; - -typedef int (*cmp_func_t)(const void *a, const void *b); -typedef void (*slist_func_t)(void *data, void *user_data); - -struct slist *slist_append(struct slist *list, void *data); - -struct slist *slist_prepend(struct slist *list, void *data); - -struct slist *slist_insert_sorted(struct slist *list, void *data, cmp_func_t cmp_func); - -struct slist *slist_remove(struct slist *list, void *data); - -struct slist *slist_find(struct slist *list, const void *data, - cmp_func_t cmp_func); - -struct slist *slist_sort(struct slist *list, cmp_func_t cmp_func); - -int slist_length(struct slist *list); - -void slist_foreach(struct slist *list, slist_func_t func, void *user_data); -void slist_free(struct slist *list); - -#endif /* __LIST_H */ -- cgit From 607695ed109340f4b7a5628420e0a8e8aee34f4e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 13 Jan 2007 17:48:12 +0000 Subject: Update copyright information --- common/dbus.c | 3 +-- common/dbus.h | 2 +- common/helper.c | 2 +- common/helper.h | 2 +- common/logging.c | 2 +- common/logging.h | 2 +- common/oui.c | 2 +- common/oui.h | 2 +- common/sdp-dummy.c | 2 +- common/sdp-expat.c | 2 +- common/sdp-xml.c | 2 +- common/sdp-xml.h | 2 +- common/test_textfile.c | 2 +- common/textfile.c | 2 +- common/textfile.h | 2 +- 15 files changed, 15 insertions(+), 16 deletions(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index 2162feab..1f2e13b0 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2004-2007 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify @@ -575,4 +575,3 @@ DBusHandlerResult simple_introspect(DBusConnection *conn, DBusMessage *msg, void return send_message_and_unref(conn, reply); } - diff --git a/common/dbus.h b/common/dbus.h index 39d3cd88..393ebcf9 100644 --- a/common/dbus.h +++ b/common/dbus.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2004-2007 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/helper.c b/common/helper.c index e3e997c8..edc39d9d 100644 --- a/common/helper.c +++ b/common/helper.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2004-2007 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/helper.h b/common/helper.h index 281ad6ee..c5cd2c43 100644 --- a/common/helper.h +++ b/common/helper.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2004-2007 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/logging.c b/common/logging.c index ddaf0d33..22cbd7e0 100644 --- a/common/logging.c +++ b/common/logging.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2004-2007 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/logging.h b/common/logging.h index 1e2ca525..92bbd064 100644 --- a/common/logging.h +++ b/common/logging.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2004-2007 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/oui.c b/common/oui.c index cc695a90..4b60ef16 100644 --- a/common/oui.c +++ b/common/oui.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2004-2007 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/oui.h b/common/oui.h index c166038f..252ce4f3 100644 --- a/common/oui.h +++ b/common/oui.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2004-2007 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/sdp-dummy.c b/common/sdp-dummy.c index 434bfbc2..d1afe426 100644 --- a/common/sdp-dummy.c +++ b/common/sdp-dummy.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2005-2006 Marcel Holtmann + * Copyright (C) 2005-2007 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/sdp-expat.c b/common/sdp-expat.c index a3b4048d..1b87c397 100644 --- a/common/sdp-expat.c +++ b/common/sdp-expat.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2005-2006 Marcel Holtmann + * Copyright (C) 2005-2007 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/sdp-xml.c b/common/sdp-xml.c index 9fe5b087..43c96319 100644 --- a/common/sdp-xml.c +++ b/common/sdp-xml.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2005-2006 Marcel Holtmann + * Copyright (C) 2005-2007 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/sdp-xml.h b/common/sdp-xml.h index 16bea948..ab8ed09b 100644 --- a/common/sdp-xml.h +++ b/common/sdp-xml.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2005-2006 Marcel Holtmann + * Copyright (C) 2005-2007 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/test_textfile.c b/common/test_textfile.c index 8b60bbe8..814c806b 100644 --- a/common/test_textfile.c +++ b/common/test_textfile.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2004-2007 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/textfile.c b/common/textfile.c index 795c99a3..36bde03f 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2004-2007 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/textfile.h b/common/textfile.h index b1a31100..11d42d1e 100644 --- a/common/textfile.h +++ b/common/textfile.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2004-2007 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify -- cgit From 4d5ea9b073c2cd77d6c833935a9f35f23aba83e7 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 13 Jan 2007 18:29:50 +0000 Subject: Add function for to toggle debug setting --- common/logging.c | 9 +++++++-- common/logging.h | 5 +++-- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'common') diff --git a/common/logging.c b/common/logging.c index 22cbd7e0..123dd809 100644 --- a/common/logging.c +++ b/common/logging.c @@ -67,12 +67,17 @@ void debug(const char *format, ...) va_end(ap); } -void enable_debug() +void toggle_debug(void) +{ + debug_enabled %= 1; +} + +void enable_debug(void) { debug_enabled = 1; } -void disable_debug() +void disable_debug(void) { debug_enabled = 0; } diff --git a/common/logging.h b/common/logging.h index 92bbd064..9ccc349d 100644 --- a/common/logging.h +++ b/common/logging.h @@ -27,8 +27,9 @@ void info(const char *format, ...); void error(const char *format, ...); void debug(const char *format, ...); -void enable_debug(); -void disable_debug(); +void toggle_debug(void); +void enable_debug(void); +void disable_debug(void); void start_logging(const char *ident, const char *message); void stop_logging(void); -- cgit From 5603520e2008d58609e3526d3eb45e088bfcb1d1 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 13 Jan 2007 18:34:41 +0000 Subject: Typo --- common/dbus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index 1f2e13b0..3b0c1097 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -513,7 +513,7 @@ DBusConnection *init_dbus(const char *name, void (*disconnect_cb)(void *), void if (dbus_bus_request_name(conn, name, 0, &err) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER ) { - error("Could not become the primary owner of %s.", name); + error("Could not become the primary owner of %s", name); return NULL; } -- cgit From 857b5c494b814a835973b23932f76d0283a18cc1 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 13 Jan 2007 18:44:29 +0000 Subject: Allow parameters for init message --- common/logging.c | 17 ++++++++++++++--- common/logging.h | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) (limited to 'common') diff --git a/common/logging.c b/common/logging.c index 123dd809..79d8d362 100644 --- a/common/logging.c +++ b/common/logging.c @@ -31,13 +31,18 @@ static volatile int debug_enabled = 0; +static inline void vinfo(const char *format, va_list ap) +{ + vsyslog(LOG_INFO, format, ap); +} + void info(const char *format, ...) { va_list ap; va_start(ap, format); - vsyslog(LOG_INFO, format, ap); + vinfo(format, ap); va_end(ap); } @@ -82,11 +87,17 @@ void disable_debug(void) debug_enabled = 0; } -void start_logging(const char *ident, const char *message) +void start_logging(const char *ident, const char *message, ...) { + va_list ap; + openlog(ident, LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_DAEMON); - info(message); + va_start(ap, message); + + vinfo(message, ap); + + va_end(ap); } void stop_logging(void) diff --git a/common/logging.h b/common/logging.h index 9ccc349d..c9134425 100644 --- a/common/logging.h +++ b/common/logging.h @@ -30,7 +30,7 @@ void debug(const char *format, ...); void toggle_debug(void); void enable_debug(void); void disable_debug(void); -void start_logging(const char *ident, const char *message); +void start_logging(const char *ident, const char *message, ...); void stop_logging(void); #endif /* __LOGGING_H */ -- cgit From 24e6b9de235b5592e7c64651875001cbd1d5590d Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 13 Jan 2007 19:51:57 +0000 Subject: Add notify framework --- common/Makefile.am | 10 +++++++++- common/notify-dummy.c | 0 common/notify-inotify.c | 0 common/notify.h | 0 4 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 common/notify-dummy.c create mode 100644 common/notify-inotify.c create mode 100644 common/notify.h (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index eb6e62b0..45520838 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -5,6 +5,12 @@ else sdp_sources = sdp-dummy.c endif +if INOTIFY +notify_sources = notify-inotify.c +else +notify_sources = notify-dummy.c +endif + if GLIB glib_sources = glib_cflags = @GLIB_CFLAGS@ @@ -19,6 +25,7 @@ libhelper_a_SOURCES = oui.h oui.c \ textfile.h textfile.c helper.h helper.c \ logging.h logging.c dbus.h dbus.c \ sdp-xml.h sdp-xml.c $(sdp_sources) \ + notify.h $(notify_sources) \ glib-ectomy.h $(glib_sources) noinst_PROGRAMS = test_textfile @@ -27,6 +34,7 @@ test_textfile_LDADD = libhelper.a AM_CFLAGS = @DBUS_CFLAGS@ $(glib_cflags) -EXTRA_DIST = ppoll.h sdp-dummy.c sdp-expat.c glib-ectomy.c +EXTRA_DIST = ppoll.h sdp-dummy.c sdp-expat.c \ + notify-dummy.c notify-inotify.c glib-ectomy.c MAINTAINERCLEANFILES = Makefile.in diff --git a/common/notify-dummy.c b/common/notify-dummy.c new file mode 100644 index 00000000..e69de29b diff --git a/common/notify-inotify.c b/common/notify-inotify.c new file mode 100644 index 00000000..e69de29b diff --git a/common/notify.h b/common/notify.h new file mode 100644 index 00000000..e69de29b -- cgit From 55295dbb667c2d0701b1285217e7f1242ca6ae83 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 13 Jan 2007 20:43:18 +0000 Subject: Add basic notification support --- common/notify-dummy.c | 36 ++++++++++++++++ common/notify-inotify.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++ common/notify.h | 25 ++++++++++++ 3 files changed, 167 insertions(+) (limited to 'common') diff --git a/common/notify-dummy.c b/common/notify-dummy.c index e69de29b..f199e972 100644 --- a/common/notify-dummy.c +++ b/common/notify-dummy.c @@ -0,0 +1,36 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2006-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "notify.h" + +void notify_init(void) +{ +} + +void notify_close(void) +{ +} diff --git a/common/notify-inotify.c b/common/notify-inotify.c index e69de29b..a1e12a6a 100644 --- a/common/notify-inotify.c +++ b/common/notify-inotify.c @@ -0,0 +1,106 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2006-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "glib-ectomy.h" +#include "logging.h" +#include "notify.h" + +static GIOChannel *io = NULL; + +static int fd = -1; +static int wd = -1; + +static gboolean io_event(GIOChannel *chan, GIOCondition cond, gpointer data) +{ + unsigned char buf[129]; + struct inotify_event *evt = (struct inotify_event *) buf; + int len; + + if (cond & (G_IO_HUP | G_IO_ERR)) + return FALSE; + + memset(buf, 0, sizeof(buf)); + + len = read(fd, buf, sizeof(buf) - 1); + if (len < sizeof(struct inotify_event)) + return TRUE; + + if (evt->mask & (IN_CREATE | IN_MOVED_TO)) + debug("File %s/%s created", CONFIGDIR, evt->name); + + if (evt->mask & (IN_DELETE | IN_MOVED_FROM)) + debug("File %s/%s deleted", CONFIGDIR, evt->name); + + if (evt->mask & IN_MODIFY) + debug("File %s/%s modified", CONFIGDIR, evt->name); + + return TRUE; +} + +void notify_init(void) +{ + fd = inotify_init(); + if (fd < 0) { + error("Creation of inotify context failed"); + return; + } + + io = g_io_channel_unix_new(fd); + if (!io) { + error("Creation of inotify channel failed"); + return; + } + + g_io_add_watch(io, G_IO_IN, io_event, NULL); + + wd = inotify_add_watch(fd, CONFIGDIR, + IN_ONLYDIR | IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVE); + if (wd < 0) + error("Creation of watch for %s failed", CONFIGDIR); +} + +void notify_close(void) +{ + if (wd != -1) { + inotify_rm_watch(fd, wd); + wd = -1; + } + + if (io) { + g_io_channel_unref(io); + io = NULL; + } + + if (fd != -1) { + close(fd); + fd = -1; + } +} diff --git a/common/notify.h b/common/notify.h index e69de29b..d82a7ca2 100644 --- a/common/notify.h +++ b/common/notify.h @@ -0,0 +1,25 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2006-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +void notify_init(void); +void notify_close(void); -- cgit From a3418be8059ffc30a0858a738f8955ceae9b39ea Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 13 Jan 2007 20:54:12 +0000 Subject: Fix toggle logic --- common/logging.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common') diff --git a/common/logging.c b/common/logging.c index 79d8d362..52fd8071 100644 --- a/common/logging.c +++ b/common/logging.c @@ -74,7 +74,7 @@ void debug(const char *format, ...) void toggle_debug(void) { - debug_enabled %= 1; + debug_enabled = (debug_enabled + 1) % 2; } void enable_debug(void) -- cgit From 603a99217dc455370b09967e7628412c13b6663b Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 13 Jan 2007 21:13:24 +0000 Subject: Allow adding user defined directories --- common/notify-dummy.c | 8 +++++++ common/notify-inotify.c | 59 ++++++++++++++++++++++++++++++++++++++++--------- common/notify.h | 2 ++ 3 files changed, 58 insertions(+), 11 deletions(-) (limited to 'common') diff --git a/common/notify-dummy.c b/common/notify-dummy.c index f199e972..3443a467 100644 --- a/common/notify-dummy.c +++ b/common/notify-dummy.c @@ -34,3 +34,11 @@ void notify_init(void) void notify_close(void) { } + +void notify_add(const char *pathname) +{ +} + +void notify_remove(const char *pathname) +{ +} diff --git a/common/notify-inotify.c b/common/notify-inotify.c index a1e12a6a..2b14b744 100644 --- a/common/notify-inotify.c +++ b/common/notify-inotify.c @@ -26,6 +26,7 @@ #endif #include +#include #include #include @@ -38,6 +39,8 @@ static GIOChannel *io = NULL; static int fd = -1; static int wd = -1; +static char *name = NULL; + static gboolean io_event(GIOChannel *chan, GIOCondition cond, gpointer data) { unsigned char buf[129]; @@ -53,20 +56,26 @@ static gboolean io_event(GIOChannel *chan, GIOCondition cond, gpointer data) if (len < sizeof(struct inotify_event)) return TRUE; + if (evt->wd != wd) + return TRUE; + if (evt->mask & (IN_CREATE | IN_MOVED_TO)) - debug("File %s/%s created", CONFIGDIR, evt->name); + debug("File %s/%s created", name, evt->name); if (evt->mask & (IN_DELETE | IN_MOVED_FROM)) - debug("File %s/%s deleted", CONFIGDIR, evt->name); + debug("File %s/%s deleted", name, evt->name); if (evt->mask & IN_MODIFY) - debug("File %s/%s modified", CONFIGDIR, evt->name); + debug("File %s/%s modified", name, evt->name); return TRUE; } void notify_init(void) { + if (fd != -1) + return; + fd = inotify_init(); if (fd < 0) { error("Creation of inotify context failed"); @@ -80,15 +89,13 @@ void notify_init(void) } g_io_add_watch(io, G_IO_IN, io_event, NULL); - - wd = inotify_add_watch(fd, CONFIGDIR, - IN_ONLYDIR | IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVE); - if (wd < 0) - error("Creation of watch for %s failed", CONFIGDIR); } void notify_close(void) { + if (fd == -1) + return; + if (wd != -1) { inotify_rm_watch(fd, wd); wd = -1; @@ -99,8 +106,38 @@ void notify_close(void) io = NULL; } - if (fd != -1) { - close(fd); - fd = -1; + close(fd); + fd = -1; + + if (name) { + free(name); + name = NULL; } } + +void notify_add(const char *pathname) +{ + if (fd == -1 || wd != -1) + return; + + if (name) + free(name); + + name = strdup(pathname); + if (!name) + return; + + wd = inotify_add_watch(fd, pathname, + IN_ONLYDIR | IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVE); + if (wd < 0) + error("Creation of watch for %s failed", pathname); +} + +void notify_remove(const char *pathname) +{ + if (fd == -1 || wd == -1) + return; + + inotify_rm_watch(fd, wd); + wd = -1; +} diff --git a/common/notify.h b/common/notify.h index d82a7ca2..b6b40034 100644 --- a/common/notify.h +++ b/common/notify.h @@ -23,3 +23,5 @@ void notify_init(void); void notify_close(void); +void notify_add(const char *pathname); +void notify_remove(const char *pathname); -- cgit From 84fa9983df320c0bd5c400735474b5c0e98e5efd Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 13 Jan 2007 21:39:57 +0000 Subject: Add callback for notifications --- common/notify-dummy.c | 2 +- common/notify-inotify.c | 16 +++++++++++----- common/notify.h | 10 +++++++++- 3 files changed, 21 insertions(+), 7 deletions(-) (limited to 'common') diff --git a/common/notify-dummy.c b/common/notify-dummy.c index 3443a467..33f7909e 100644 --- a/common/notify-dummy.c +++ b/common/notify-dummy.c @@ -35,7 +35,7 @@ void notify_close(void) { } -void notify_add(const char *pathname) +void notify_add(const char *pathname, notify_func func, void *user_data) { } diff --git a/common/notify-inotify.c b/common/notify-inotify.c index 2b14b744..53ab7d55 100644 --- a/common/notify-inotify.c +++ b/common/notify-inotify.c @@ -41,6 +41,8 @@ static int wd = -1; static char *name = NULL; +static notify_func callback = NULL; + static gboolean io_event(GIOChannel *chan, GIOCondition cond, gpointer data) { unsigned char buf[129]; @@ -56,17 +58,17 @@ static gboolean io_event(GIOChannel *chan, GIOCondition cond, gpointer data) if (len < sizeof(struct inotify_event)) return TRUE; - if (evt->wd != wd) + if (evt->wd != wd || !callback) return TRUE; if (evt->mask & (IN_CREATE | IN_MOVED_TO)) - debug("File %s/%s created", name, evt->name); + callback(NOTIFY_CREATE, evt->name, NULL); if (evt->mask & (IN_DELETE | IN_MOVED_FROM)) - debug("File %s/%s deleted", name, evt->name); + callback(NOTIFY_DELETE, evt->name, NULL); if (evt->mask & IN_MODIFY) - debug("File %s/%s modified", name, evt->name); + callback(NOTIFY_MODIFY, evt->name, NULL); return TRUE; } @@ -115,7 +117,7 @@ void notify_close(void) } } -void notify_add(const char *pathname) +void notify_add(const char *pathname, notify_func func, void *user_data) { if (fd == -1 || wd != -1) return; @@ -131,6 +133,8 @@ void notify_add(const char *pathname) IN_ONLYDIR | IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVE); if (wd < 0) error("Creation of watch for %s failed", pathname); + + callback = func; } void notify_remove(const char *pathname) @@ -140,4 +144,6 @@ void notify_remove(const char *pathname) inotify_rm_watch(fd, wd); wd = -1; + + callback = NULL; } diff --git a/common/notify.h b/common/notify.h index b6b40034..3a58c508 100644 --- a/common/notify.h +++ b/common/notify.h @@ -21,7 +21,15 @@ * */ +typedef void (*notify_func)(int action, const char *name, void *user_data); + +enum { + NOTIFY_CREATE, + NOTIFY_DELETE, + NOTIFY_MODIFY, +}; + void notify_init(void); void notify_close(void); -void notify_add(const char *pathname); +void notify_add(const char *pathname, notify_func func, void *user_data); void notify_remove(const char *pathname); -- cgit From e6dbdf0ffc56cc647ecd84abfefb1f0a1872a853 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 13 Jan 2007 21:47:30 +0000 Subject: Remove helper stuff --- common/Makefile.am | 5 ++--- common/helper.c | 42 ------------------------------------------ common/helper.h | 32 -------------------------------- 3 files changed, 2 insertions(+), 77 deletions(-) delete mode 100644 common/helper.c delete mode 100644 common/helper.h (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index 45520838..f4868562 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -21,9 +21,8 @@ endif noinst_LIBRARIES = libhelper.a -libhelper_a_SOURCES = oui.h oui.c \ - textfile.h textfile.c helper.h helper.c \ - logging.h logging.c dbus.h dbus.c \ +libhelper_a_SOURCES = oui.h oui.c dbus.h dbus.c \ + textfile.h textfile.c logging.h logging.c \ sdp-xml.h sdp-xml.c $(sdp_sources) \ notify.h $(notify_sources) \ glib-ectomy.h $(glib_sources) diff --git a/common/helper.c b/common/helper.c deleted file mode 100644 index edc39d9d..00000000 --- a/common/helper.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2007 Marcel Holtmann - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include "glib-ectomy.h" -#include "helper.h" - -int bt_timeout_add(int interval, bt_timeout_func_t function, void *data) -{ - return g_timeout_add(interval, function, data); -} - -int bt_timeout_remove(const int id) -{ - return g_timeout_remove(id); -} diff --git a/common/helper.h b/common/helper.h deleted file mode 100644 index c5cd2c43..00000000 --- a/common/helper.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2007 Marcel Holtmann - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifndef __HELPER_H -#define __HELPER_H - -typedef int (*bt_timeout_func_t) (void *data); - -int bt_timeout_add(int interval, bt_timeout_func_t function, void *data); -int bt_timeout_remove(const int id); - -#endif /* __HELPER_H */ -- cgit From e8b9bf6bfc52751b75ade32609817ab859a3e889 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 15 Jan 2007 11:01:41 +0000 Subject: Provide IN_ONLYDIR if missing --- common/notify-inotify.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'common') diff --git a/common/notify-inotify.c b/common/notify-inotify.c index 53ab7d55..27719dbf 100644 --- a/common/notify-inotify.c +++ b/common/notify-inotify.c @@ -30,6 +30,10 @@ #include #include +#ifndef IN_ONLYDIR +#define IN_ONLYDIR 0x01000000 +#endif + #include "glib-ectomy.h" #include "logging.h" #include "notify.h" -- cgit From 467f83c3ac4e4afba959e8cfd8aadb0f1614c9fb Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 15 Jan 2007 18:38:58 +0000 Subject: Preliminary support for catching the unique bus name of an execed service --- common/dbus.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ common/dbus.h | 3 +++ 2 files changed, 48 insertions(+) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index 3b0c1097..070535d7 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -308,6 +308,51 @@ int name_listener_remove(DBusConnection *connection, const char *name, return 0; } +dbus_bool_t dbus_bus_get_unix_process_id(DBusConnection *conn, const char *name, + unsigned long *pid) +{ + DBusMessage *msg, *reply; + dbus_uint32_t pid_arg; + + msg = dbus_message_new_method_call("org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "GetConnectionUnixProcessID"); + if (!msg) { + error("Unable to allocate new message"); + return FALSE; + } + + if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &name, + DBUS_TYPE_INVALID)) { + error("Unable to append arguments to message"); + dbus_message_unref(msg); + return FALSE; + } + + reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, NULL); + if (!reply) { + error("Sending GetConnectionUnixProcessID failed"); + dbus_message_unref(msg); + return FALSE; + } + + if (!dbus_message_get_args(reply, NULL, DBUS_TYPE_UINT32, &pid_arg, + DBUS_TYPE_INVALID)) { + error("Getting GetConnectionUnixProcessID args failed"); + dbus_message_unref(msg); + dbus_message_unref(reply); + return FALSE; + } + + *pid = (unsigned long) pid_arg; + + dbus_message_unref(msg); + dbus_message_unref(reply); + + return TRUE; +} + static DBusHandlerResult disconnect_filter(DBusConnection *conn, DBusMessage *msg, void *data) { diff --git a/common/dbus.h b/common/dbus.h index 393ebcf9..51049391 100644 --- a/common/dbus.h +++ b/common/dbus.h @@ -35,6 +35,9 @@ int name_listener_add(DBusConnection *connection, const char *name, int name_listener_remove(DBusConnection *connection, const char *name, name_cb_t func, void *user_data); +dbus_bool_t dbus_bus_get_unix_process_id(DBusConnection *conn, const char *name, + unsigned long *pid); + DBusHandlerResult simple_introspect(DBusConnection *conn, DBusMessage *msg, void *data); static inline DBusHandlerResult send_message_and_unref(DBusConnection *conn, DBusMessage *msg) -- cgit From bbb1288a3ff9cd6a4c6f3090b5022dda5c8a022e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 17 Jan 2007 23:42:18 +0000 Subject: Use dbus_connection_setup_with_g_main() function when available --- common/dbus.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index 070535d7..f8a2f0ac 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -34,6 +34,10 @@ #include +#ifdef HAVE_DBUS_GLIB +#include +#endif + #include "glib-ectomy.h" #include "dbus.h" #include "logging.h" @@ -375,6 +379,7 @@ static DBusHandlerResult disconnect_filter(DBusConnection *conn, return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } +#ifndef HAVE_DBUS_GLIB static gboolean message_dispatch_cb(void *data) { DBusConnection *connection = data; @@ -527,6 +532,7 @@ static void dispatch_status_cb(DBusConnection *conn, if (new_status == DBUS_DISPATCH_DATA_REMAINS) g_timeout_add(DISPATCH_TIMEOUT, message_dispatch_cb, data); } +#endif DBusConnection *init_dbus(const char *name, void (*disconnect_cb)(void *), void *user_data) { @@ -544,6 +550,9 @@ DBusConnection *init_dbus(const char *name, void (*disconnect_cb)(void *), void return NULL; } +#ifdef HAVE_DBUS_GLIB + dbus_connection_setup_with_g_main(conn, NULL); +#else dbus_connection_set_watch_functions(conn, add_watch, remove_watch, watch_toggled, conn, NULL); @@ -552,6 +561,7 @@ DBusConnection *init_dbus(const char *name, void (*disconnect_cb)(void *), void dbus_connection_set_dispatch_status_function(conn, dispatch_status_cb, conn, NULL); +#endif if (name) { dbus_error_init(&err); -- cgit From a4c11055a71ed680d4071152d8bb9852dffb733b Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 17 Jan 2007 23:52:46 +0000 Subject: In case of D-Bus GLib bindings don't define unneeded structures --- common/dbus.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index f8a2f0ac..7792360e 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -48,6 +48,7 @@ static int name_listener_initialized = 0; static GSList *name_listeners = NULL; +#ifdef HAVE_DBUS_GLIB typedef struct { uint32_t id; DBusTimeout *timeout; @@ -58,6 +59,7 @@ struct watch_info { GIOChannel *io; DBusConnection *conn; }; +#endif struct disconnect_data { void (*disconnect_cb)(void *); -- cgit From fa6cce02d57d4720af01da3cee545eb611dd890c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 17 Jan 2007 23:53:20 +0000 Subject: Typo --- common/dbus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index 7792360e..e11b94e4 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -48,7 +48,7 @@ static int name_listener_initialized = 0; static GSList *name_listeners = NULL; -#ifdef HAVE_DBUS_GLIB +#ifndef HAVE_DBUS_GLIB typedef struct { uint32_t id; DBusTimeout *timeout; -- cgit From 461b066346015907451b9eb693a293a92b1ed06e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 17 Jan 2007 23:57:24 +0000 Subject: Add missing dbus_connection_unref() calls in failure cases --- common/dbus.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index e11b94e4..730dfb67 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -571,12 +571,14 @@ DBusConnection *init_dbus(const char *name, void (*disconnect_cb)(void *), void if (dbus_bus_request_name(conn, name, 0, &err) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER ) { error("Could not become the primary owner of %s", name); + dbus_connection_unref(conn); return NULL; } if (dbus_error_is_set(&err)) { error("Can't get bus name %s: %s", name, err.message); dbus_error_free(&err); + dbus_connection_unref(conn); return NULL; } } -- cgit From 125780a23b51802aea47920c79ee8e368d11592f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 18 Jan 2007 01:08:40 +0000 Subject: Add generic method table handling --- common/dbus.c | 29 ++++++++++++++++++++++++++++- common/dbus.h | 17 +++++++++++++++-- 2 files changed, 43 insertions(+), 3 deletions(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index 730dfb67..63e5e38f 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -611,7 +611,8 @@ DBusConnection *init_dbus(const char *name, void (*disconnect_cb)(void *), void static char simple_xml[] = DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE ""; -DBusHandlerResult simple_introspect(DBusConnection *conn, DBusMessage *msg, void *data) +DBusHandlerResult simple_introspect(DBusConnection *conn, + DBusMessage *msg, void *user_data) { DBusMessage *reply; const char *path, *ptr = simple_xml; @@ -634,3 +635,29 @@ DBusHandlerResult simple_introspect(DBusConnection *conn, DBusMessage *msg, void return send_message_and_unref(conn, reply); } + +static DBusHandlerResult generic_message_function(DBusConnection *conn, + DBusMessage *msg, void *user_data) +{ + struct message_table *table = user_data; + struct message_table *current; + const char *member; + + if (dbus_message_is_method_call(msg, DBUS_INTERFACE_INTROSPECTABLE, + "Introspect") == TRUE) + return simple_introspect(conn, msg, user_data); + + member = dbus_message_get_member(msg); + + for (current = table; current->handler; current++) { + if (dbus_message_is_method_call(msg, current->interface, current->member) == TRUE && + dbus_message_has_signature(msg, current->signature) == TRUE) + return current->handler(conn, msg, user_data); + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +DBusObjectPathVTable generic_object_path = { + .message_function = generic_message_function, +}; diff --git a/common/dbus.h b/common/dbus.h index 51049391..d050237d 100644 --- a/common/dbus.h +++ b/common/dbus.h @@ -28,6 +28,21 @@ DBusConnection *init_dbus(const char *name, void (*disconnect_cb)(void *), void *user_data); +typedef DBusHandlerResult (*message_func_t) (DBusConnection *conn, + DBusMessage *msg, void *user_data); + +struct message_table { + const char *interface; + const char *member; + const char *signature; + message_func_t handler; +}; + +extern DBusObjectPathVTable generic_object_path; + +DBusHandlerResult simple_introspect(DBusConnection *conn, + DBusMessage *msg, void *user_data); + typedef void (*name_cb_t)(const char *name, void *user_data); int name_listener_add(DBusConnection *connection, const char *name, @@ -38,8 +53,6 @@ int name_listener_remove(DBusConnection *connection, const char *name, dbus_bool_t dbus_bus_get_unix_process_id(DBusConnection *conn, const char *name, unsigned long *pid); -DBusHandlerResult simple_introspect(DBusConnection *conn, DBusMessage *msg, void *data); - static inline DBusHandlerResult send_message_and_unref(DBusConnection *conn, DBusMessage *msg) { if (msg) { -- cgit From ee6b2930a0519021232f92f615f6a8fd9cd61805 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 18 Jan 2007 17:56:00 +0000 Subject: Add more D-Bus helpers --- common/Makefile.am | 1 + common/dbus-helper.c | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++ common/dbus-helper.h | 51 +++++++++++++++ 3 files changed, 227 insertions(+) create mode 100644 common/dbus-helper.c create mode 100644 common/dbus-helper.h (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index f4868562..a92ff9a3 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -23,6 +23,7 @@ noinst_LIBRARIES = libhelper.a libhelper_a_SOURCES = oui.h oui.c dbus.h dbus.c \ textfile.h textfile.c logging.h logging.c \ + dbus-helper.h dbus-helper.c \ sdp-xml.h sdp-xml.c $(sdp_sources) \ notify.h $(notify_sources) \ glib-ectomy.h $(glib_sources) diff --git a/common/dbus-helper.c b/common/dbus-helper.c new file mode 100644 index 00000000..bb6e7102 --- /dev/null +++ b/common/dbus-helper.c @@ -0,0 +1,175 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include + +#include "logging.h" + +#include "dbus-helper.h" + +struct generic_data { + void *user_data; + DBusObjectPathUnregisterFunction unregister_function; + const char *interface; + DBusMethodVTable *methods; + char *introspect; +}; + +DBusHandlerResult dbus_connection_send_and_unref(DBusConnection *connection, + DBusMessage *message) +{ + if (message) { + dbus_connection_send(connection, message, NULL); + dbus_message_unref(message); + } + + return DBUS_HANDLER_RESULT_HANDLED; +} + +static DBusHandlerResult introspect(DBusConnection *connection, + DBusMessage *message, struct generic_data *data) +{ + DBusMessage *reply; + + if (dbus_message_has_signature(message, + DBUS_TYPE_INVALID_AS_STRING) == FALSE) { + error("Unexpected signature to introspect call"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (!data->introspect) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + reply = dbus_message_new_method_return(message); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + dbus_message_append_args(reply, DBUS_TYPE_STRING, &data->introspect, + DBUS_TYPE_INVALID); + + return dbus_connection_send_and_unref(connection, reply); +} + +static void generic_unregister(DBusConnection *connection, void *user_data) +{ + struct generic_data *data = user_data; + + if (data->unregister_function) + data->unregister_function(connection, data->user_data); + + free(data); +} + +static DBusHandlerResult generic_message(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + struct generic_data *data = user_data; + DBusMethodVTable *current; + + if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, + "Introspect") == TRUE) + return introspect(connection, message, data); + + for (current = data->methods; + current->name && current->message_function; current++) { + if (dbus_message_is_method_call(message, + data->interface, current->name) == FALSE) + continue; + + if (dbus_message_has_signature(message, + current->signature) == TRUE) + return current->message_function(connection, + message, data->user_data); + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusObjectPathVTable generic_table = { + .unregister_function = generic_unregister, + .message_function = generic_message, +}; + +dbus_bool_t dbus_connection_create_object_path(DBusConnection *connection, + const char *path, void *user_data, + DBusObjectPathUnregisterFunction function) +{ + struct generic_data *data; + + data = malloc(sizeof(*data)); + if (!data) + return FALSE; + + memset(data, 0, sizeof(*data)); + + data->user_data = user_data; + data->unregister_function = function; + + if (dbus_connection_register_object_path(connection, path, + &generic_table, data) == FALSE) { + free(data); + return FALSE; + } + + return TRUE; +} + +dbus_bool_t dbus_connection_destroy_object_path(DBusConnection *connection, + const char *path) +{ + return dbus_connection_unregister_object_path(connection, path); +} + +static char simple_xml[] = DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE ""; + +dbus_bool_t dbus_connection_register_interface(DBusConnection *connection, + const char *path, const char *interface, + DBusMethodVTable *methods, + DBusPropertyVTable *properties) +{ + struct generic_data *data; + DBusMethodVTable *current; + + if (dbus_connection_get_object_path_data(connection, path, + (void *) &data) == FALSE) + return FALSE; + + data->interface = interface; + data->methods = methods; + + for (current = data->methods; current->name; current++) { + debug("Adding introspection data for %s.%s", + interface, current->name); + } + + data->introspect = simple_xml; + + return TRUE; +} diff --git a/common/dbus-helper.h b/common/dbus-helper.h new file mode 100644 index 00000000..a4e405ff --- /dev/null +++ b/common/dbus-helper.h @@ -0,0 +1,51 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +DBusHandlerResult dbus_connection_send_and_unref(DBusConnection *connection, + DBusMessage *message); + +dbus_bool_t dbus_connection_create_object_path(DBusConnection *connection, + const char *path, void *user_data, + DBusObjectPathUnregisterFunction function); + +dbus_bool_t dbus_connection_destroy_object_path(DBusConnection *connection, + const char *path); + +typedef struct DBusMethodVTable DBusMethodVTable; + +struct DBusMethodVTable { + const char *name; + DBusObjectPathMessageFunction message_function; + const char *signature; + const char *reply; +}; + +typedef struct DBusPropertyVTable DBusPropertyVTable; + +struct DBusPropertyVTable { +}; + +dbus_bool_t dbus_connection_register_interface(DBusConnection *connection, + const char *path, const char *interface, + DBusMethodVTable *methods, + DBusPropertyVTable *properties); -- cgit From f7c027662d2066b3862f41dbae3b68e5c1bafce7 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 18 Jan 2007 23:39:27 +0000 Subject: Add support for multiple interfaces at a path --- common/dbus-helper.c | 61 ++++++++++++++++++++++++++++++++++++++++++++-------- common/dbus-helper.h | 3 +++ 2 files changed, 55 insertions(+), 9 deletions(-) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index bb6e7102..71d1eeb7 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -30,6 +30,7 @@ #include +#include "glib-ectomy.h" #include "logging.h" #include "dbus-helper.h" @@ -37,9 +38,13 @@ struct generic_data { void *user_data; DBusObjectPathUnregisterFunction unregister_function; + GSList *interfaces; + char *introspect; +}; + +struct interface_data { const char *interface; DBusMethodVTable *methods; - char *introspect; }; DBusHandlerResult dbus_connection_send_and_unref(DBusConnection *connection, @@ -87,20 +92,42 @@ static void generic_unregister(DBusConnection *connection, void *user_data) free(data); } +static struct interface_data *find_interface(GSList *interfaces, + const char *interface) +{ + GSList *list; + + for (list = interfaces; list; list = list->next) { + struct interface_data *iface = list->data; + if (!strcmp(interface, iface->interface)) + return iface; + } + + return NULL; +} + static DBusHandlerResult generic_message(DBusConnection *connection, DBusMessage *message, void *user_data) { struct generic_data *data = user_data; + struct interface_data *iface; DBusMethodVTable *current; + const char *interface; if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, "Introspect") == TRUE) return introspect(connection, message, data); - for (current = data->methods; + interface = dbus_message_get_interface(message); + + iface = find_interface(data->interfaces, interface); + if (!iface) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + for (current = iface->methods; current->name && current->message_function; current++) { if (dbus_message_is_method_call(message, - data->interface, current->name) == FALSE) + iface->interface, current->name) == FALSE) continue; if (dbus_message_has_signature(message, @@ -117,6 +144,8 @@ static DBusObjectPathVTable generic_table = { .message_function = generic_message, }; +static char simple_xml[] = DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE ""; + dbus_bool_t dbus_connection_create_object_path(DBusConnection *connection, const char *path, void *user_data, DBusObjectPathUnregisterFunction function) @@ -132,6 +161,9 @@ dbus_bool_t dbus_connection_create_object_path(DBusConnection *connection, data->user_data = user_data; data->unregister_function = function; + data->interfaces = NULL; + data->introspect = simple_xml; + if (dbus_connection_register_object_path(connection, path, &generic_table, data) == FALSE) { free(data); @@ -147,29 +179,40 @@ dbus_bool_t dbus_connection_destroy_object_path(DBusConnection *connection, return dbus_connection_unregister_object_path(connection, path); } -static char simple_xml[] = DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE ""; - dbus_bool_t dbus_connection_register_interface(DBusConnection *connection, const char *path, const char *interface, DBusMethodVTable *methods, DBusPropertyVTable *properties) { struct generic_data *data; + struct interface_data *iface; DBusMethodVTable *current; if (dbus_connection_get_object_path_data(connection, path, (void *) &data) == FALSE) return FALSE; - data->interface = interface; - data->methods = methods; + iface = malloc(sizeof(*iface)); + if (!iface) + return FALSE; + + memset(iface, 0, sizeof(*iface)); + + iface->interface = interface; + iface->methods = methods; - for (current = data->methods; current->name; current++) { + for (current = iface->methods; current->name; current++) { debug("Adding introspection data for %s.%s", interface, current->name); } - data->introspect = simple_xml; + data->interfaces = g_slist_append(data->interfaces, iface); return TRUE; } + +dbus_bool_t dbus_connection_unregister_interface(DBusConnection *connection, + const char *path, const char *interface) +{ + return TRUE; +} diff --git a/common/dbus-helper.h b/common/dbus-helper.h index a4e405ff..0e7162f2 100644 --- a/common/dbus-helper.h +++ b/common/dbus-helper.h @@ -49,3 +49,6 @@ dbus_bool_t dbus_connection_register_interface(DBusConnection *connection, const char *path, const char *interface, DBusMethodVTable *methods, DBusPropertyVTable *properties); + +dbus_bool_t dbus_connection_unregister_interface(DBusConnection *connection, + const char *path, const char *interface); -- cgit From 8aa2613760bbe766d53f3f4b0683c3920aeff005 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 18 Jan 2007 23:46:00 +0000 Subject: Add string array and byte array definitions --- common/dbus-helper.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'common') diff --git a/common/dbus-helper.h b/common/dbus-helper.h index 0e7162f2..0c33a04f 100644 --- a/common/dbus-helper.h +++ b/common/dbus-helper.h @@ -21,6 +21,9 @@ * */ +#define DBUS_TYPE_STRING_ARRAY_AS_STRING (DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING) +#define DBUS_TYPE_BYTE_ARRAY_AS_STRING (DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING) + DBusHandlerResult dbus_connection_send_and_unref(DBusConnection *connection, DBusMessage *message); -- cgit From f2c07fc5c3b2be43421544a5edfc27d6f9b9a5d9 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 19 Jan 2007 01:05:01 +0000 Subject: Remove not needed generic message handling --- common/dbus.c | 26 -------------------------- common/dbus.h | 12 ------------ 2 files changed, 38 deletions(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index 63e5e38f..3b211851 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -635,29 +635,3 @@ DBusHandlerResult simple_introspect(DBusConnection *conn, return send_message_and_unref(conn, reply); } - -static DBusHandlerResult generic_message_function(DBusConnection *conn, - DBusMessage *msg, void *user_data) -{ - struct message_table *table = user_data; - struct message_table *current; - const char *member; - - if (dbus_message_is_method_call(msg, DBUS_INTERFACE_INTROSPECTABLE, - "Introspect") == TRUE) - return simple_introspect(conn, msg, user_data); - - member = dbus_message_get_member(msg); - - for (current = table; current->handler; current++) { - if (dbus_message_is_method_call(msg, current->interface, current->member) == TRUE && - dbus_message_has_signature(msg, current->signature) == TRUE) - return current->handler(conn, msg, user_data); - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -DBusObjectPathVTable generic_object_path = { - .message_function = generic_message_function, -}; diff --git a/common/dbus.h b/common/dbus.h index d050237d..801d90c6 100644 --- a/common/dbus.h +++ b/common/dbus.h @@ -28,18 +28,6 @@ DBusConnection *init_dbus(const char *name, void (*disconnect_cb)(void *), void *user_data); -typedef DBusHandlerResult (*message_func_t) (DBusConnection *conn, - DBusMessage *msg, void *user_data); - -struct message_table { - const char *interface; - const char *member; - const char *signature; - message_func_t handler; -}; - -extern DBusObjectPathVTable generic_object_path; - DBusHandlerResult simple_introspect(DBusConnection *conn, DBusMessage *msg, void *user_data); -- cgit From 8cc5595d9091b484b9a4abe314c0f3ec055e0581 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 20 Jan 2007 05:26:15 +0000 Subject: Make it possible to support an embedded GLib --- common/Makefile.am | 15 +++------------ common/dbus-helper.c | 3 ++- common/dbus.c | 3 ++- common/notify-inotify.c | 3 ++- 4 files changed, 9 insertions(+), 15 deletions(-) (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index a92ff9a3..412786c9 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -11,30 +11,21 @@ else notify_sources = notify-dummy.c endif -if GLIB -glib_sources = -glib_cflags = @GLIB_CFLAGS@ -else -glib_sources = glib-ectomy.c -glib_cflags = -endif - noinst_LIBRARIES = libhelper.a libhelper_a_SOURCES = oui.h oui.c dbus.h dbus.c \ textfile.h textfile.c logging.h logging.c \ dbus-helper.h dbus-helper.c \ sdp-xml.h sdp-xml.c $(sdp_sources) \ - notify.h $(notify_sources) \ - glib-ectomy.h $(glib_sources) + notify.h $(notify_sources) noinst_PROGRAMS = test_textfile test_textfile_LDADD = libhelper.a -AM_CFLAGS = @DBUS_CFLAGS@ $(glib_cflags) +AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ EXTRA_DIST = ppoll.h sdp-dummy.c sdp-expat.c \ - notify-dummy.c notify-inotify.c glib-ectomy.c + notify-dummy.c notify-inotify.c MAINTAINERCLEANFILES = Makefile.in diff --git a/common/dbus-helper.c b/common/dbus-helper.c index 71d1eeb7..64b00cd8 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -28,9 +28,10 @@ #include #include +#include + #include -#include "glib-ectomy.h" #include "logging.h" #include "dbus-helper.h" diff --git a/common/dbus.c b/common/dbus.c index 3b211851..bdcb1684 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -32,13 +32,14 @@ #include #include +#include + #include #ifdef HAVE_DBUS_GLIB #include #endif -#include "glib-ectomy.h" #include "dbus.h" #include "logging.h" diff --git a/common/notify-inotify.c b/common/notify-inotify.c index 27719dbf..a35cf745 100644 --- a/common/notify-inotify.c +++ b/common/notify-inotify.c @@ -34,7 +34,8 @@ #define IN_ONLYDIR 0x01000000 #endif -#include "glib-ectomy.h" +#include + #include "logging.h" #include "notify.h" -- cgit From 76e6160da25b72dc8d73a508e9efc4a487cfd8d0 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 20 Jan 2007 05:28:36 +0000 Subject: Remove no longer needed files --- common/glib-ectomy.c | 819 --------------------------------------------------- common/glib-ectomy.h | 147 --------- 2 files changed, 966 deletions(-) delete mode 100644 common/glib-ectomy.c delete mode 100644 common/glib-ectomy.h (limited to 'common') diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c deleted file mode 100644 index b45d26f4..00000000 --- a/common/glib-ectomy.c +++ /dev/null @@ -1,819 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "glib-ectomy.h" - -struct timeout { - guint id; - guint interval; - struct timeval expiration; - gpointer data; - GSourceFunc function; -}; - -struct _GIOChannel { - int fd; - gboolean closed; - gboolean close_on_unref; -}; - -struct _GMainContext { - guint next_id; - glong next_timeout; - - GSList *timeouts; - GSList *proc_timeouts; - gboolean timeout_lock; - - GSList *watches; - GSList *proc_watches; - gboolean watch_lock; -}; - -struct _GMainLoop { - gboolean is_running; - GMainContext *context; -}; - -GIOError g_io_channel_read(GIOChannel *channel, gchar *buf, gsize count, gsize *bytes_read) -{ - int fd = channel->fd; - gssize result; - - if (channel->closed) - return G_IO_STATUS_ERROR; - - /* At least according to the Debian manpage for read */ - if (count > SSIZE_MAX) - count = SSIZE_MAX; - -retry: - result = read (fd, buf, count); - - if (result < 0) { - *bytes_read = 0; - - switch (errno) { -#ifdef EINTR - case EINTR: - goto retry; -#endif -#ifdef EAGAIN - case EAGAIN: - return G_IO_STATUS_AGAIN; -#endif - default: - return G_IO_STATUS_ERROR; - } - } - - *bytes_read = result; - - return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF; -} - -void g_io_channel_close(GIOChannel *channel) -{ - if (!channel || channel->closed) - return; - - close(channel->fd); - - channel->closed = TRUE; -} - -void g_io_channel_unref(GIOChannel *channel) -{ - if (!channel) - return; - - if (channel->close_on_unref && channel->fd >= 0) - g_io_channel_close(channel); - - free(channel); -} - -GIOChannel *g_io_channel_unix_new(int fd) -{ - GIOChannel *channel; - - channel = malloc(sizeof(GIOChannel)); - if (!channel) - return NULL; - - memset(channel, 0, sizeof(GIOChannel)); - - channel->fd = fd; - - return channel; -} - -void g_io_channel_set_close_on_unref(GIOChannel *channel, gboolean do_close) -{ - channel->close_on_unref = do_close; -} - -gint g_io_channel_unix_get_fd(GIOChannel *channel) -{ - if (channel->closed) - return -1; - - return channel->fd; -} - -struct watch { - guint id; - GIOChannel *channel; - gint priority; - GIOCondition condition; - short *revents; - GIOFunc func; - gpointer user_data; - GDestroyNotify destroy; -}; - -static GMainContext *default_context = NULL; - -static void watch_free(struct watch *watch) -{ - if (watch->destroy) - watch->destroy(watch->user_data); - free(watch); -} - -static GMainContext *g_main_context_default() -{ - if (default_context) - return default_context; - - default_context = malloc(sizeof(GMainContext)); - if (!default_context) - return NULL; - - memset(default_context, 0, sizeof(GMainContext)); - - default_context->next_timeout = -1; - default_context->next_id = 1; - - return default_context; -} - -void g_io_remove_watch(guint id) -{ - GMainContext *context = g_main_context_default(); - GSList *l; - struct watch *w; - - if (!context) - return; - - for (l = context->watches; l != NULL; l = l->next) { - w = l->data; - - if (w->id != id) - continue; - - context->watches = g_slist_remove(context->watches, w); - watch_free(w); - - return; - } - - for (l = context->proc_watches; l != NULL; l = l->next) { - w = l->data; - - if (w->id != id) - continue; - - context->proc_watches = g_slist_remove(context->proc_watches, w); - watch_free(w); - - return; - } -} - -int watch_prio_cmp(struct watch *w1, struct watch *w2) -{ - return w1->priority - w2->priority; -} - -#define watch_list_add(l, w) g_slist_insert_sorted((l), (w), (GCompareFunc) watch_prio_cmp) - -guint g_io_add_watch_full(GIOChannel *channel, gint priority, - GIOCondition condition, GIOFunc func, - gpointer user_data, GDestroyNotify notify) -{ - struct watch *watch; - GMainContext *context = g_main_context_default(); - - if (!context) - return 0; - - watch = malloc(sizeof(struct watch)); - if (!watch) - return 0; - - watch->id = context->next_id++; - watch->channel = channel; - watch->priority = priority; - watch->condition = condition; - watch->func = func; - watch->user_data = user_data; - watch->destroy = notify; - - if (context->watch_lock) - context->proc_watches = watch_list_add(context->proc_watches, watch); - else - context->watches = watch_list_add(context->watches, watch); - - return watch->id; -} - -guint g_io_add_watch(GIOChannel *channel, GIOCondition condition, - GIOFunc func, gpointer user_data) -{ - return g_io_add_watch_full(channel, 0, condition, - func, user_data, NULL); -} - -GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running) -{ - GMainLoop *ml; - - if (!context) - context = g_main_context_default(); - - if (!context) - return NULL; - - ml = malloc(sizeof(GMainLoop)); - if (!ml) - return NULL; - - memset(ml, 0, sizeof(GMainLoop)); - - ml->context = context; - ml->is_running = is_running; - - return ml; -} - -static void timeout_handlers_prepare(GMainContext *context) -{ - GSList *l; - struct timeval tv; - glong msec, timeout = LONG_MAX; - - gettimeofday(&tv, NULL); - - for (l = context->timeouts; l != NULL; l = l->next) { - struct timeout *t = l->data; - - /* calculate the remainning time */ - msec = (t->expiration.tv_sec - tv.tv_sec) * 1000 + - (t->expiration.tv_usec - tv.tv_usec) / 1000; - if (msec < 0) - msec = 0; - - timeout = MIN_TIMEOUT(timeout, msec); - } - - /* set to min value found or NO timeout */ - context->next_timeout = (timeout != LONG_MAX ? timeout : -1); -} - -static int ptr_cmp(const void *t1, const void *t2) -{ - return t1 - t2; -} - -static void timeout_handlers_check(GMainContext *context) -{ - struct timeval tv; - - gettimeofday(&tv, NULL); - - context->timeout_lock = TRUE; - - while (context->timeouts) { - struct timeout *t = context->timeouts->data; - glong secs, msecs; - gboolean ret; - - if (timercmp(&tv, &t->expiration, <)) { - context->timeouts = g_slist_remove(context->timeouts, t); - context->proc_timeouts = g_slist_append(context->proc_timeouts, t); - continue; - } - - ret = t->function(t->data); - - /* Check if the handler was removed/freed by the callback - * function */ - if (!g_slist_find_custom(context->timeouts, t, ptr_cmp)) - continue; - - context->timeouts = g_slist_remove(context->timeouts, t); - - if (!ret) { - free(t); - continue; - } - - /* update the next expiration time */ - secs = t->interval / 1000; - msecs = t->interval - secs * 1000; - - t->expiration.tv_sec = tv.tv_sec + secs; - t->expiration.tv_usec = tv.tv_usec + msecs * 1000; - if (t->expiration.tv_usec >= 1000000) { - t->expiration.tv_usec -= 1000000; - t->expiration.tv_sec++; - } - - context->proc_timeouts = g_slist_append(context->proc_timeouts, t); - } - - context->timeouts = context->proc_timeouts; - context->proc_timeouts = NULL; - context->timeout_lock = FALSE; -} - -void g_main_loop_run(GMainLoop *loop) -{ - int open_max = sysconf(_SC_OPEN_MAX); - struct pollfd *ufds; - GMainContext *context = loop->context; - - ufds = malloc(open_max * sizeof(struct pollfd)); - if (!ufds) - return; - - loop->is_running = TRUE; - - while (loop->is_running) { - int nfds; - GSList *l; - struct watch *w; - - for (nfds = 0, l = context->watches; l != NULL; l = l->next, nfds++) { - w = l->data; - ufds[nfds].fd = w->channel->fd; - ufds[nfds].events = w->condition; - ufds[nfds].revents = 0; - w->revents = &ufds[nfds].revents; - } - - /* calculate the next timeout */ - timeout_handlers_prepare(context); - - if (poll(ufds, nfds, context->next_timeout) < 0) - continue; - - context->watch_lock = TRUE; - - while (context->watches) { - gboolean ret; - - w = context->watches->data; - - if (!*w->revents) { - context->watches = g_slist_remove(context->watches, w); - context->proc_watches = watch_list_add(context->proc_watches, w); - continue; - } - - ret = w->func(w->channel, *w->revents, w->user_data); - - /* Check if the watch was removed/freed by the callback - * function */ - if (!g_slist_find_custom(context->watches, w, ptr_cmp)) - continue; - - context->watches = g_slist_remove(context->watches, w); - - if (!ret) { - watch_free(w); - continue; - } - - context->proc_watches = watch_list_add(context->proc_watches, w); - } - - context->watches = context->proc_watches; - context->proc_watches = NULL; - context->watch_lock = FALSE; - - /* check expired timers */ - timeout_handlers_check(loop->context); - } - - free(ufds); -} - -void g_main_loop_quit(GMainLoop *loop) -{ - loop->is_running = FALSE; -} - -void g_main_loop_unref(GMainLoop *loop) -{ - if (!loop->context) - return; - - g_slist_foreach(loop->context->watches, (GFunc)watch_free, NULL); - g_slist_free(loop->context->watches); - - g_slist_foreach(loop->context->timeouts, (GFunc)free, NULL); - g_slist_free(loop->context->timeouts); - - free(loop->context); - loop->context = NULL; -} - -guint g_timeout_add(guint interval, GSourceFunc function, gpointer data) -{ - GMainContext *context = g_main_context_default(); - struct timeval tv; - guint secs; - guint msecs; - struct timeout *t; - - if (!context || !function) - return 0; - - t = malloc(sizeof(*t)); - - if (!t) - return 0; - - memset(t, 0, sizeof(*t)); - t->interval = interval; - t->function = function; - t->data = data; - - gettimeofday(&tv, NULL); - - secs = interval /1000; - msecs = interval - secs * 1000; - - t->expiration.tv_sec = tv.tv_sec + secs; - t->expiration.tv_usec = tv.tv_usec + msecs * 1000; - - if (t->expiration.tv_usec >= 1000000) { - t->expiration.tv_usec -= 1000000; - t->expiration.tv_sec++; - } - - /* attach the timeout the default context */ - t->id = context->next_id++; - - if (context->timeout_lock) - context->proc_timeouts = g_slist_prepend(context->proc_timeouts, t); - else - context->timeouts = g_slist_prepend(context->timeouts, t); - - return t->id; -} - -gint g_timeout_remove(const guint id) -{ - GMainContext *context = g_main_context_default(); - GSList *l; - struct timeout *t; - - if (!context) - return -1; - - l = context->timeouts; - - while (l) { - t = l->data; - l = l->next; - - if (t->id != id) - continue; - - context->timeouts = g_slist_remove(context->timeouts, t); - free(t); - - return 0; - } - - l = context->proc_timeouts; - - while (l) { - t = l->data; - l = l->next; - - if (t->id != id) - continue; - - context->proc_timeouts = g_slist_remove(context->proc_timeouts, t); - free(t); - - return 0; - } - - return -1; -} - -/* UTF-8 Validation: approximate copy/paste from glib2. */ - -#define UNICODE_VALID(c) \ - ((c) < 0x110000 && \ - (((c) & 0xFFFFF800) != 0xD800) && \ - ((c) < 0xFDD0 || (c) > 0xFDEF) && \ - ((c) & 0xFFFE) != 0xFFFE) - -#define CONTINUATION_CHAR(c, val) \ - do { \ - if (((c) & 0xc0) != 0x80) /* 10xxxxxx */ \ - goto failed; \ - (val) <<= 6; \ - (val) |= (c) & 0x3f; \ - } while (0) - -#define INCREMENT_AND_CHECK_MAX(p, i, max_len) \ - do { \ - (i)++; \ - if ((p)[(i)] == '\0' || ((max_len) >= 0 && (i) >= (max_len))) \ - goto failed; \ - } while (0) - - -gboolean g_utf8_validate(const gchar *str, gssize max_len, const gchar **end) -{ - unsigned long val, min, i; - const unsigned char *p, *last; - - min = val = 0; - - for (p = (unsigned char *) str, i = 0; p[i]; i++) { - if (max_len >= 0 && i >= max_len) - break; - - if (p[i] < 128) - continue; - - last = &p[i]; - - if ((p[i] & 0xe0) == 0xc0) { /* 110xxxxx */ - if ((p[i] & 0x1e) == 0) - goto failed; - INCREMENT_AND_CHECK_MAX(p, i, max_len); - if ((p[i] & 0xc0) != 0x80) - goto failed; /* 10xxxxxx */ - } else { - if ((p[i] & 0xf0) == 0xe0) { - /* 1110xxxx */ - min = (1 << 11); - val = p[i] & 0x0f; - goto two_remaining; - } else if ((p[i] & 0xf8) == 0xf0) { - /* 11110xxx */ - min = (1 << 16); - val = p[i] & 0x07; - } else - goto failed; - - INCREMENT_AND_CHECK_MAX(p, i, max_len); - CONTINUATION_CHAR(p[i], val); -two_remaining: - INCREMENT_AND_CHECK_MAX(p, i, max_len); - CONTINUATION_CHAR(p[i], val); - - INCREMENT_AND_CHECK_MAX(p, i, max_len); - CONTINUATION_CHAR(p[i], val); - - if (val < min || !UNICODE_VALID(val)) - goto failed; - } - } - - if (end) - *end = (const gchar *) &p[i]; - - return TRUE; - -failed: - if (end) - *end = (const gchar *) last; - - return FALSE; -} - -/* GSList functions */ - -GSList *g_slist_append(GSList *list, void *data) -{ - GSList *entry, *tail; - - entry = malloc(sizeof(GSList)); - /* FIXME: this currently just silently fails */ - if (!entry) - return list; - - entry->data = data; - entry->next = NULL; - - if (!list) - return entry; - - /* Find the end of the list */ - for (tail = list; tail->next; tail = tail->next); - - tail->next = entry; - - return list; -} - -GSList *g_slist_prepend(GSList *list, void *data) -{ - GSList *entry; - - entry = malloc(sizeof(GSList)); - /* FIXME: this currently just silently fails */ - if (!entry) - return list; - - entry->data = data; - entry->next = list; - - return entry; -} - -GSList *g_slist_insert_sorted(GSList *list, void *data, GCompareFunc cmp_func) -{ - GSList *tmp, *prev, *entry; - int cmp; - - entry = malloc(sizeof(GSList)); - if (!entry) - return list; - - entry->data = data; - entry->next = NULL; - - if (!list) - return entry; - - prev = NULL; - tmp = list; - - cmp = cmp_func(data, tmp->data); - - while (tmp->next && cmp > 0) { - prev = tmp; - tmp = tmp->next; - - cmp = cmp_func(data, tmp->data); - } - - if (!tmp->next && cmp > 0) { - tmp->next = entry; - return list; - } - - if (prev) { - prev->next = entry; - entry->next = tmp; - return list; - } else { - entry->next = list; - return entry; - } -} - -GSList *g_slist_remove(GSList *list, void *data) -{ - GSList *l, *next, *prev = NULL, *match = NULL; - - if (!list) - return NULL; - - for (l = list; l != NULL; l = l->next) { - if (l->data == data) { - match = l; - break; - } - prev = l; - } - - if (!match) - return list; - - next = match->next; - - free(match); - - /* If the head was removed, return the next element */ - if (!prev) - return next; - - prev->next = next; - - return list; -} - -GSList *g_slist_find_custom(GSList *list, const void *data, - GCompareFunc cmp_func) -{ - GSList *l; - - for (l = list; l != NULL; l = l->next) { - if (!cmp_func(l->data, data)) - return l; - } - - return NULL; -} - -static GSList *g_slist_sort_merge(GSList *l1, GSList *l2, - GCompareFunc cmp_func) -{ - GSList list, *l; - int cmp; - - l = &list; - - while (l1 && l2) { - cmp = cmp_func(l1->data, l2->data); - - if (cmp <= 0) { - l = l->next = l1; - l1 = l1->next; - } else { - l = l->next = l2; - l2 = l2->next; - } - } - - l->next = l1 ? l1 : l2; - - return list.next; -} - -GSList *g_slist_sort(GSList *list, GCompareFunc cmp_func) -{ - GSList *l1, *l2; - - if (!list || !list->next) - return list; - - l1 = list; - l2 = list->next; - - while ((l2 = l2->next) != NULL) { - if ((l2 = l2->next) == NULL) - break; - l1 = l1->next; - } - - l2 = l1->next; - l1->next = NULL; - - return g_slist_sort_merge(g_slist_sort(list, cmp_func), - g_slist_sort(l2, cmp_func), cmp_func); -} - -int g_slist_length(GSList *list) -{ - int len; - - for (len = 0; list != NULL; list = list->next) - len++; - - return len; -} - -void g_slist_foreach(GSList *list, GFunc func, void *user_data) -{ - while (list) { - GSList *next = list->next; - func(list->data, user_data); - list = next; - } -} - -void g_slist_free(GSList *list) -{ - GSList *l, *next; - - for (l = list; l != NULL; l = next) { - next = l->next; - free(l); - } -} diff --git a/common/glib-ectomy.h b/common/glib-ectomy.h deleted file mode 100644 index 02fa0230..00000000 --- a/common/glib-ectomy.h +++ /dev/null @@ -1,147 +0,0 @@ -#ifndef __GLIB_ECTOMY_H -#define __GLIB_ECTOMY_H - -#ifdef HAVE_GLIB -#include -#define g_timeout_remove g_source_remove -#define g_io_remove_watch g_source_remove -#else - -#include -#include - -typedef char gchar; -typedef short gshort; -typedef long glong; -typedef int gint; -typedef gint gboolean; - -typedef unsigned char guchar; -typedef unsigned short gushort; -typedef unsigned long gulong; -typedef unsigned int guint; - -typedef float gfloat; -typedef double gdouble; - -typedef void * gpointer; -typedef const void * gconstpointer; - -typedef size_t gsize; -typedef ssize_t gssize; - -#ifndef SSIZE_MAX -#define SSIZE_MAX INT_MAX -#endif - -#define MIN_TIMEOUT(a, b) (((a) < (b)) ? (a) : (b)) - -typedef struct _GIOChannel GIOChannel; - -typedef gboolean (*GSourceFunc) (gpointer data); - -typedef struct _GMainContext GMainContext; - -typedef struct _GMainLoop GMainLoop; - -typedef enum { - G_IO_ERROR_NONE, - G_IO_ERROR_AGAIN, - G_IO_ERROR_INVAL, - G_IO_ERROR_UNKNOWN -} GIOError; - -typedef enum { - G_IO_STATUS_ERROR = -1, - G_IO_STATUS_NORMAL = 0, - G_IO_STATUS_EOF = 1, - G_IO_STATUS_AGAIN = 2 -} GIOStatus; - -#ifndef FALSE -#define FALSE (0) -#endif - -#ifndef TRUE -#define TRUE (!FALSE) -#endif - -typedef enum { - G_IO_IN = POLLIN, - G_IO_OUT = POLLOUT, - G_IO_PRI = POLLPRI, - G_IO_ERR = POLLERR, - G_IO_HUP = POLLHUP, - G_IO_NVAL = POLLNVAL -} GIOCondition; - -#define G_PRIORITY_HIGH -100 -#define G_PRIORITY_DEFAULT 0 -#define G_PRIORITY_HIGH_IDLE 100 -#define G_PRIORITY_DEFAULT_IDLE 200 -#define G_PRIORITY_LOW 300 - -typedef void (*GDestroyNotify) (gpointer data); -typedef gboolean (*GIOFunc) (GIOChannel *source, GIOCondition condition, gpointer data); - -GIOError g_io_channel_read(GIOChannel *channel, gchar *buf, gsize count, gsize *bytes_read); -void g_io_channel_close(GIOChannel *channel); - -GIOChannel *g_io_channel_unix_new(int fd); -void g_io_channel_unref(GIOChannel *channel); -void g_io_channel_set_close_on_unref(GIOChannel *channel, gboolean do_close); -gint g_io_channel_unix_get_fd(GIOChannel *channel); -guint g_io_add_watch(GIOChannel *channel, GIOCondition condition, - GIOFunc func, gpointer user_data); -guint g_io_add_watch_full(GIOChannel *channel, gint priority, - GIOCondition condition, GIOFunc func, - gpointer user_data, GDestroyNotify notify); -void g_io_remove_watch(guint id); - -GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running); -void g_main_loop_run(GMainLoop *loop); -void g_main_loop_quit(GMainLoop *loop); -void g_main_loop_unref(GMainLoop *loop); -guint g_timeout_add(guint interval, GSourceFunc function, gpointer data); -gint g_timeout_remove(const guint id); - -gboolean g_utf8_validate(const gchar *str, gssize max_len, const gchar **end); - -#define g_main_new(is_running) g_main_loop_new(NULL, is_running); -#define g_main_run(loop) g_main_loop_run(loop) -#define g_main_quit(loop) g_main_loop_quit(loop) -#define g_main_unref(loop) g_main_loop_unref(loop) - -/* Begin GSList declarations */ - -typedef struct _GSList { - void *data; - struct _GSList *next; -} GSList; - -typedef int (*GCompareFunc)(const void *a, const void *b); -typedef void (*GFunc)(void *data, void *user_data); - -GSList *g_slist_append(GSList *list, void *data); - -GSList *g_slist_prepend(GSList *list, void *data); - -GSList *g_slist_insert_sorted(GSList *list, void *data, GCompareFunc cmp_func); - -GSList *g_slist_remove(GSList *list, void *data); - -GSList *g_slist_find_custom(GSList *list, const void *data, - GCompareFunc cmp_func); - -GSList *g_slist_sort(GSList *list, GCompareFunc cmp_func); - -int g_slist_length(GSList *list); - -void g_slist_foreach(GSList *list, GFunc func, void *user_data); -void g_slist_free(GSList *list); - -/* End GSList declarations */ - -#endif - -#endif /* __GLIB_ECTOMY_H */ -- cgit From f2fdd9fee9109cb0fa7f37a26acd0b1eaf2f40f2 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sat, 20 Jan 2007 14:43:59 +0000 Subject: Get rid of g_timeout_remove and g_io_remove_watch in favor for g_source_remove --- common/dbus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index bdcb1684..b6d852c3 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -453,7 +453,7 @@ static void remove_watch(DBusWatch *watch, void *data) dbus_watch_set_data(watch, NULL, NULL); if (info) { - g_io_remove_watch(info->watch_id); + g_source_remove(info->watch_id); g_io_channel_unref(info->io); dbus_connection_unref(info->conn); free(info); @@ -489,7 +489,7 @@ static void timeout_handler_free(void *data) if (!handler) return; - g_timeout_remove(handler->id); + g_source_remove(handler->id); free(handler); } -- cgit From bb3cd7888177a4d0e23a5790d3fe26f008345164 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 20 Jan 2007 16:31:12 +0000 Subject: Preparation for using the XML parser from GLib --- common/Makefile.am | 8 ++++++-- common/sdp-glib.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 common/sdp-glib.c (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index 412786c9..d9bd00ce 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -1,9 +1,13 @@ +if GLIB +sdp_sources = sdp-glib.c +else if EXPAT sdp_sources = sdp-expat.c else sdp_sources = sdp-dummy.c endif +endif if INOTIFY notify_sources = notify-inotify.c @@ -25,7 +29,7 @@ test_textfile_LDADD = libhelper.a AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ -EXTRA_DIST = ppoll.h sdp-dummy.c sdp-expat.c \ - notify-dummy.c notify-inotify.c +EXTRA_DIST = ppoll.h notify-dummy.c notify-inotify.c \ + sdp-dummy.c sdp-expat.c sdp-glib.c MAINTAINERCLEANFILES = Makefile.in diff --git a/common/sdp-glib.c b/common/sdp-glib.c new file mode 100644 index 00000000..15212994 --- /dev/null +++ b/common/sdp-glib.c @@ -0,0 +1,35 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "sdp-xml.h" + +sdp_record_t *sdp_xml_parse_record(const char *data, int size) +{ + return NULL; +} -- cgit From 5e43e2ef30c178c13a81aaafeacd06b3e8cd7a65 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 20 Jan 2007 16:56:52 +0000 Subject: Add example of GLib based parser --- common/sdp-glib.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'common') diff --git a/common/sdp-glib.c b/common/sdp-glib.c index 15212994..fa0e8a17 100644 --- a/common/sdp-glib.c +++ b/common/sdp-glib.c @@ -27,9 +27,37 @@ #include +#include "logging.h" #include "sdp-xml.h" +static void element_start(GMarkupParseContext *context, + const gchar *element_name, const gchar **attribute_names, + const gchar **attribute_values, gpointer user_data, GError **error) +{ + debug("<%s>", element_name); +} + +static void element_end(GMarkupParseContext *context, + const gchar *element_name, gpointer user_data, GError **error) +{ + debug("", element_name); +} + +static GMarkupParser parser = { + element_start, element_end, NULL, NULL, NULL +}; + sdp_record_t *sdp_xml_parse_record(const char *data, int size) { + GMarkupParseContext *ctx; + + ctx = g_markup_parse_context_new(&parser, 0, NULL, NULL); + + if (g_markup_parse_context_parse(ctx, data, size, NULL) == FALSE) { + error("XML parsing error"); + } + + g_markup_parse_context_free(ctx); + return NULL; } -- cgit From 84471a6158acc384fc0a2df8aea99d1b7be03b75 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 20 Jan 2007 17:36:32 +0000 Subject: Coding style cleanup --- common/sdp-expat.c | 68 ++++++++++++++++++------------------------------------ 1 file changed, 23 insertions(+), 45 deletions(-) (limited to 'common') diff --git a/common/sdp-expat.c b/common/sdp-expat.c index 1b87c397..7c8867a5 100644 --- a/common/sdp-expat.c +++ b/common/sdp-expat.c @@ -25,9 +25,7 @@ #include #endif -#include -#include -#include +#include #include #include @@ -186,21 +184,17 @@ static void convert_xml_to_sdp_start(void *data, const char *el, const char **at /* Parse value, name, encoding */ for (i = 0; attr[i]; i += 2) { if (!strcmp(attr[i], "value")) { - int curlen = - strlen(context->stack_head->text); + 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); + 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'; + attr[i + 1], attrlen); + context->stack_head->text[curlen + attrlen] = '\0'; } if (!strcmp(attr[i], "encoding")) { @@ -209,13 +203,11 @@ static void convert_xml_to_sdp_start(void *data, const char *el, const char **at } if (!strcmp(attr[i], "name")) { - context->stack_head->name = - strdup(attr[i + 1]); + context->stack_head->name = strdup(attr[i + 1]); } } - context->stack_head->data = - sdp_xml_parse_datatype(type, context); + context->stack_head->data = sdp_xml_parse_datatype(type, context); /* Could not parse an entry */ if (context->stack_head->data == NULL) @@ -244,9 +236,8 @@ static void convert_xml_to_sdp_end(void *data, const char *el) 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); + int ret = sdp_attr_add(context->sdprec, context->attrId, + context->stack_head->data); if (ret == -1) debug("Trouble adding attribute\n"); @@ -254,42 +245,33 @@ static void convert_xml_to_sdp_end(void *data, const char *el) sdp_xml_data_free(context->stack_head); context->stack_head = 0; } else { - debug("No Data for attribute: %d\n", - context->attrId); + 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); + 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->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->unitSize += sizeof(uint16_t); context->stack_head->data->dtd = SDP_SEQ16; } else { - context->stack_head->data->unitSize += - sizeof(uint8_t); + 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); + 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->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->unitSize += sizeof(uint16_t); context->stack_head->data->dtd = SDP_ALT16; } else { - context->stack_head->data->unitSize += - sizeof(uint8_t); + context->stack_head->data->unitSize += sizeof(uint8_t); } } @@ -305,13 +287,9 @@ static void convert_xml_to_sdp_end(void *data, const char *el) 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->next->data->val.dataseq = + sdp_seq_append(context->stack_head->next->data->val.dataseq, + context->stack_head->data); context->stack_head->data = 0; break; } @@ -338,7 +316,7 @@ static struct sdp_xml_context *sdp_xml_init_context() context->parser = XML_ParserCreate(NULL); XML_SetElementHandler(context->parser, convert_xml_to_sdp_start, - convert_xml_to_sdp_end); + convert_xml_to_sdp_end); XML_SetUserData(context->parser, context); if (!context->parser) -- cgit From 92a3abc2920877b67162afe028cc8420ddbc18c0 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 20 Jan 2007 18:00:24 +0000 Subject: Another coding style fix --- common/sdp-expat.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'common') diff --git a/common/sdp-expat.c b/common/sdp-expat.c index 7c8867a5..8c68278e 100644 --- a/common/sdp-expat.c +++ b/common/sdp-expat.c @@ -156,8 +156,7 @@ static void convert_xml_to_sdp_start(void *data, const char *el, const char **at /* Get the ID */ for (i = 0; attr[i]; i += 1) { if (!strcmp(attr[i], "id")) { - context->attrId = - strtol(attr[i + 1], 0, 0); + context->attrId = strtol(attr[i + 1], 0, 0); break; } } -- cgit From e21806ba296e3062960ad4f85e216d81753c5b7a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 20 Jan 2007 18:10:17 +0000 Subject: Extract common function from expat based parser --- common/sdp-expat.c | 124 ++++++----------------------------------------------- common/sdp-xml.c | 89 ++++++++++++++++++++++++++++++++++++++ common/sdp-xml.h | 18 +++++++- 3 files changed, 118 insertions(+), 113 deletions(-) (limited to 'common') diff --git a/common/sdp-expat.c b/common/sdp-expat.c index 8c68278e..469f3a72 100644 --- a/common/sdp-expat.c +++ b/common/sdp-expat.c @@ -35,17 +35,18 @@ #include "logging.h" #include "sdp-xml.h" -/* Expat specific implementation of the context struct */ +static int compute_seq_size(sdp_data_t *data) +{ + int unit_size = data->unitSize; + sdp_data_t *seq = data->val.dataseq; -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 */ - struct sdp_xml_data *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? */ -}; + for (; seq; seq = seq->next) + unit_size += seq->unitSize; + + return unit_size; +} + +/* Expat specific implementation of the context struct */ struct sdp_xml_context { XML_Parser parser; /* Parser object being used */ @@ -54,96 +55,6 @@ struct sdp_xml_context { int attrId; /* Id of the most recently processed attribute */ }; -#define DEFAULT_XML_DATA_SIZE 1024 - -static struct sdp_xml_data *sdp_xml_data_alloc() -{ - struct sdp_xml_data *elem; - - elem = malloc(sizeof(struct sdp_xml_data)); - - /* Null terminate the text */ - elem->size = DEFAULT_XML_DATA_SIZE; - elem->text = malloc(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(struct sdp_xml_data *elem) -{ - if (elem->data) - sdp_data_free(elem->data); - - if (elem->name) - free(elem->name); - - free(elem->text); - free(elem); -} - -static struct sdp_xml_data *sdp_xml_data_expand(struct sdp_xml_data *elem) -{ - char *newbuf; - - newbuf = 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, - struct sdp_xml_context *context) -{ - const char *data = context->stack_head->text; - - if (!strcmp(el, "boolean")) - return sdp_xml_parse_int(data, SDP_BOOL); - else if (!strcmp(el, "uint8")) - return sdp_xml_parse_int(data, SDP_UINT8); - else if (!strcmp(el, "uint16")) - return sdp_xml_parse_int(data, SDP_UINT16); - else if (!strcmp(el, "uint32")) - return sdp_xml_parse_int(data, SDP_UINT32); - else if (!strcmp(el, "uint64")) - return sdp_xml_parse_int(data, SDP_UINT64); - else if (!strcmp(el, "uint128")) - return sdp_xml_parse_int(data, SDP_UINT128); - else if (!strcmp(el, "int8")) - return sdp_xml_parse_int(data, SDP_INT8); - else if (!strcmp(el, "int16")) - return sdp_xml_parse_int(data, SDP_INT16); - else if (!strcmp(el, "int32")) - return sdp_xml_parse_int(data, SDP_INT32); - else if (!strcmp(el, "int64")) - return sdp_xml_parse_int(data, SDP_INT64); - else if (!strcmp(el, "int128")) - return sdp_xml_parse_int(data, SDP_INT128); - else if (!strcmp(el, "uuid")) - return sdp_xml_parse_uuid(data); - else if (!strcmp(el, "url")) - return sdp_xml_parse_url(data); - else if (!strcmp(el, "text")) - return sdp_xml_parse_text(data, context->stack_head->type); - else if (!strcmp(el, "nil")) - return sdp_xml_parse_nil(data); - - return NULL; -} - static void convert_xml_to_sdp_start(void *data, const char *el, const char **attr) { struct sdp_xml_context *context = data; @@ -206,7 +117,7 @@ static void convert_xml_to_sdp_start(void *data, const char *el, const char **at } } - context->stack_head->data = sdp_xml_parse_datatype(type, context); + context->stack_head->data = sdp_xml_parse_datatype(type, context->stack_head); /* Could not parse an entry */ if (context->stack_head->data == NULL) @@ -214,17 +125,6 @@ static void convert_xml_to_sdp_start(void *data, const char *el, const char **at } } -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) { struct sdp_xml_context *context = data; diff --git a/common/sdp-xml.c b/common/sdp-xml.c index 43c96319..87200908 100644 --- a/common/sdp-xml.c +++ b/common/sdp-xml.c @@ -703,3 +703,92 @@ sdp_data_t *sdp_xml_parse_nil(const char *data) { return sdp_data_alloc(SDP_DATA_NIL, 0); } + +#define DEFAULT_XML_DATA_SIZE 1024 + +struct sdp_xml_data *sdp_xml_data_alloc() +{ + struct sdp_xml_data *elem; + + elem = malloc(sizeof(struct sdp_xml_data)); + + /* Null terminate the text */ + elem->size = DEFAULT_XML_DATA_SIZE; + elem->text = malloc(DEFAULT_XML_DATA_SIZE); + elem->text[0] = '\0'; + + elem->next = 0; + elem->data = 0; + + elem->type = 0; + elem->name = 0; + + return elem; +} + +void sdp_xml_data_free(struct sdp_xml_data *elem) +{ + if (elem->data) + sdp_data_free(elem->data); + + if (elem->name) + free(elem->name); + + free(elem->text); + free(elem); +} + +struct sdp_xml_data *sdp_xml_data_expand(struct sdp_xml_data *elem) +{ + char *newbuf; + + newbuf = 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; +} + +sdp_data_t *sdp_xml_parse_datatype(const char *el, struct sdp_xml_data *elem) +{ + const char *data = elem->text; + + if (!strcmp(el, "boolean")) + return sdp_xml_parse_int(data, SDP_BOOL); + else if (!strcmp(el, "uint8")) + return sdp_xml_parse_int(data, SDP_UINT8); + else if (!strcmp(el, "uint16")) + return sdp_xml_parse_int(data, SDP_UINT16); + else if (!strcmp(el, "uint32")) + return sdp_xml_parse_int(data, SDP_UINT32); + else if (!strcmp(el, "uint64")) + return sdp_xml_parse_int(data, SDP_UINT64); + else if (!strcmp(el, "uint128")) + return sdp_xml_parse_int(data, SDP_UINT128); + else if (!strcmp(el, "int8")) + return sdp_xml_parse_int(data, SDP_INT8); + else if (!strcmp(el, "int16")) + return sdp_xml_parse_int(data, SDP_INT16); + else if (!strcmp(el, "int32")) + return sdp_xml_parse_int(data, SDP_INT32); + else if (!strcmp(el, "int64")) + return sdp_xml_parse_int(data, SDP_INT64); + else if (!strcmp(el, "int128")) + return sdp_xml_parse_int(data, SDP_INT128); + else if (!strcmp(el, "uuid")) + return sdp_xml_parse_uuid(data); + else if (!strcmp(el, "url")) + return sdp_xml_parse_url(data); + else if (!strcmp(el, "text")) + return sdp_xml_parse_text(data, elem->type); + else if (!strcmp(el, "nil")) + return sdp_xml_parse_nil(data); + + return NULL; +} diff --git a/common/sdp-xml.h b/common/sdp-xml.h index ab8ed09b..2d4d7d79 100644 --- a/common/sdp-xml.h +++ b/common/sdp-xml.h @@ -39,6 +39,22 @@ sdp_data_t *sdp_xml_parse_url(const char *data); sdp_data_t *sdp_xml_parse_int(const char *data, uint8_t dtd); sdp_data_t *sdp_xml_parse_uuid(const char *data); +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 */ + struct sdp_xml_data *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_data *sdp_xml_data_alloc(); +void sdp_xml_data_free(struct sdp_xml_data *elem); +struct sdp_xml_data *sdp_xml_data_expand(struct sdp_xml_data *elem); + +sdp_data_t *sdp_xml_parse_datatype(const char *el, struct sdp_xml_data *elem); + sdp_record_t *sdp_xml_parse_record(const char *data, int size); - + #endif /* __SDP_XML_H */ -- cgit From 200bca5921ca8bd040b0644e1918e7a42e2bda96 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 20 Jan 2007 18:42:15 +0000 Subject: Update expat and GLib based parsers --- common/sdp-expat.c | 15 ++--- common/sdp-glib.c | 187 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 187 insertions(+), 15 deletions(-) (limited to 'common') diff --git a/common/sdp-expat.c b/common/sdp-expat.c index 469f3a72..b591bbcc 100644 --- a/common/sdp-expat.c +++ b/common/sdp-expat.c @@ -82,7 +82,7 @@ static void convert_xml_to_sdp_start(void *data, const char *el, const char **at context->stack_head = newelem; } else { context->stack_head = sdp_xml_data_alloc(); - context->stack_head->next = 0; + context->stack_head->next = NULL; } if (!strcmp(el, "sequence")) @@ -90,7 +90,6 @@ static void convert_xml_to_sdp_start(void *data, const char *el, const char **at 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")) { @@ -117,7 +116,7 @@ static void convert_xml_to_sdp_start(void *data, const char *el, const char **at } } - context->stack_head->data = sdp_xml_parse_datatype(type, context->stack_head); + context->stack_head->data = sdp_xml_parse_datatype(el, context->stack_head); /* Could not parse an entry */ if (context->stack_head->data == NULL) @@ -140,9 +139,9 @@ static void convert_xml_to_sdp_end(void *data, const char *el) if (ret == -1) debug("Trouble adding attribute\n"); - context->stack_head->data = 0; + context->stack_head->data = NULL; sdp_xml_data_free(context->stack_head); - context->stack_head = 0; + context->stack_head = NULL; } else { debug("No Data for attribute: %d\n", context->attrId); } @@ -177,8 +176,8 @@ static void convert_xml_to_sdp_end(void *data, const char *el) /* 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) { + 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: @@ -189,7 +188,7 @@ static void convert_xml_to_sdp_end(void *data, const char *el) 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; + context->stack_head->data = NULL; break; } diff --git a/common/sdp-glib.c b/common/sdp-glib.c index fa0e8a17..37c8580f 100644 --- a/common/sdp-glib.c +++ b/common/sdp-glib.c @@ -25,22 +25,176 @@ #include #endif +#include + +#include +#include + #include #include "logging.h" #include "sdp-xml.h" +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; +} + +struct context_data { + sdp_record_t *record; + sdp_data_t attr_data; + struct sdp_xml_data *stack_head; + uint16_t attr_id; +}; + static void element_start(GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, - const gchar **attribute_values, gpointer user_data, GError **error) + const gchar **attribute_values, gpointer user_data, GError **err) { - debug("<%s>", element_name); + struct context_data *ctx_data = user_data; + + if (!strcmp(element_name, "record")) + return; + + if (!strcmp(element_name, "attribute")) { + int i; + for (i = 0; attribute_names[i]; i++) { + if (!strcmp(attribute_names[i], "id")) { + ctx_data->attr_id = strtol(attribute_values[i], 0, 0); + break; + } + } + debug("New attribute 0x%04x", ctx_data->attr_id); + return; + } + + if (ctx_data->stack_head) { + struct sdp_xml_data *newelem = sdp_xml_data_alloc(); + newelem->next = ctx_data->stack_head; + ctx_data->stack_head = newelem; + } else { + ctx_data->stack_head = sdp_xml_data_alloc(); + ctx_data->stack_head->next = NULL; + } + + if (!strcmp(element_name, "sequence")) + ctx_data->stack_head->data = sdp_data_alloc(SDP_SEQ8, NULL); + else if (!strcmp(element_name, "alternate")) + ctx_data->stack_head->data = sdp_data_alloc(SDP_ALT8, NULL); + else { + int i; + /* Parse value, name, encoding */ + for (i = 0; attribute_names[i]; i++) { + if (!strcmp(attribute_names[i], "value")) { + int curlen = strlen(ctx_data->stack_head->text); + int attrlen = strlen(attribute_values[i]); + + /* Ensure we're big enough */ + while ((curlen + 1 + attrlen) > ctx_data->stack_head->size) { + sdp_xml_data_expand(ctx_data->stack_head); + } + + memcpy(ctx_data->stack_head->text + curlen, + attribute_values[i], attrlen); + ctx_data->stack_head->text[curlen + attrlen] = '\0'; + } + + if (!strcmp(attribute_names[i], "encoding")) { + if (!strcmp(attribute_values[i], "hex")) + ctx_data->stack_head->type = 1; + } + + if (!strcmp(attribute_names[i], "name")) { + ctx_data->stack_head->name = strdup(attribute_values[i]); + } + } + + ctx_data->stack_head->data = + sdp_xml_parse_datatype(element_name, ctx_data->stack_head); + + if (ctx_data->stack_head->data == NULL) + error("Can't parse element %s", element_name); + } } static void element_end(GMarkupParseContext *context, - const gchar *element_name, gpointer user_data, GError **error) + const gchar *element_name, gpointer user_data, GError **err) { - debug("", element_name); + struct context_data *ctx_data = user_data; + struct sdp_xml_data *elem; + + if (!strcmp(element_name, "record")) + return; + + if (!strcmp(element_name, "attribute")) { + if (ctx_data->stack_head && ctx_data->stack_head->data) { + int ret = sdp_attr_add(ctx_data->record, ctx_data->attr_id, + ctx_data->stack_head->data); + if (ret == -1) + debug("Trouble adding attribute\n"); + + ctx_data->stack_head->data = NULL; + sdp_xml_data_free(ctx_data->stack_head); + ctx_data->stack_head = NULL; + } else { + debug("No data for attribute 0x%04x\n", ctx_data->attr_id); + } + return; + } + + if (!strcmp(element_name, "sequence")) { + ctx_data->stack_head->data->unitSize = compute_seq_size(ctx_data->stack_head->data); + + if (ctx_data->stack_head->data->unitSize > USHRT_MAX) { + ctx_data->stack_head->data->unitSize += sizeof(uint32_t); + ctx_data->stack_head->data->dtd = SDP_SEQ32; + } else if (ctx_data->stack_head->data->unitSize > UCHAR_MAX) { + ctx_data->stack_head->data->unitSize += sizeof(uint16_t); + ctx_data->stack_head->data->dtd = SDP_SEQ16; + } else { + ctx_data->stack_head->data->unitSize += sizeof(uint8_t); + } + } else if (!strcmp(element_name, "alternate")) { + ctx_data->stack_head->data->unitSize = compute_seq_size(ctx_data->stack_head->data); + + if (ctx_data->stack_head->data->unitSize > USHRT_MAX) { + ctx_data->stack_head->data->unitSize += sizeof(uint32_t); + ctx_data->stack_head->data->dtd = SDP_ALT32; + } else if (ctx_data->stack_head->data->unitSize > UCHAR_MAX) { + ctx_data->stack_head->data->unitSize += sizeof(uint16_t); + ctx_data->stack_head->data->dtd = SDP_ALT16; + } else { + ctx_data->stack_head->data->unitSize += sizeof(uint8_t); + } + } + + if (ctx_data->stack_head->next && ctx_data->stack_head->data && + ctx_data->stack_head->next->data) { + switch (ctx_data->stack_head->next->data->dtd) { + case SDP_SEQ8: + case SDP_SEQ16: + case SDP_SEQ32: + case SDP_ALT8: + case SDP_ALT16: + case SDP_ALT32: + ctx_data->stack_head->next->data->val.dataseq = + sdp_seq_append(ctx_data->stack_head->next->data->val.dataseq, + ctx_data->stack_head->data); + ctx_data->stack_head->data = NULL; + break; + } + + elem = ctx_data->stack_head; + ctx_data->stack_head = ctx_data->stack_head->next; + + sdp_xml_data_free(elem); + } } static GMarkupParser parser = { @@ -50,14 +204,33 @@ static GMarkupParser parser = { sdp_record_t *sdp_xml_parse_record(const char *data, int size) { GMarkupParseContext *ctx; + struct context_data *ctx_data; + sdp_record_t *record; + + ctx_data = malloc(sizeof(*ctx_data)); + if (!ctx_data) + return NULL; + + record = sdp_record_alloc(); + if (!record) { + sdp_record_free(record); + return NULL; + } + + memset(ctx_data, 0, sizeof(*ctx_data)); + ctx_data->record = record; - ctx = g_markup_parse_context_new(&parser, 0, NULL, NULL); + ctx = g_markup_parse_context_new(&parser, 0, ctx_data, NULL); if (g_markup_parse_context_parse(ctx, data, size, NULL) == FALSE) { error("XML parsing error"); + g_markup_parse_context_free(ctx); + sdp_record_free(record); + free(ctx_data); + return NULL; } - g_markup_parse_context_free(ctx); + free(ctx_data); - return NULL; + return record; } -- cgit From 9a975ad512c9f5632738ebc5fec473aff2b08087 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 20 Jan 2007 21:28:02 +0000 Subject: Fix memory leaks in XML parser for SDP --- common/sdp-glib.c | 2 ++ common/sdp-xml.c | 18 +++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) (limited to 'common') diff --git a/common/sdp-glib.c b/common/sdp-glib.c index 37c8580f..a24464ce 100644 --- a/common/sdp-glib.c +++ b/common/sdp-glib.c @@ -230,6 +230,8 @@ sdp_record_t *sdp_xml_parse_record(const char *data, int size) return NULL; } + g_markup_parse_context_free(ctx); + free(ctx_data); return record; diff --git a/common/sdp-xml.c b/common/sdp-xml.c index 87200908..abebc652 100644 --- a/common/sdp-xml.c +++ b/common/sdp-xml.c @@ -676,6 +676,8 @@ static sdp_data_t *sdp_xml_parse_text_with_size(const char *data, char encoding, debug("Unit size %d length %d: -->%s<--\n", ret->unitSize, length, text); + free(text); + return ret; } #endif @@ -696,6 +698,8 @@ sdp_data_t *sdp_xml_parse_text(const char *data, char encoding) debug("Unit size %d length %d: -->%s<--\n", ret->unitSize, length, text); + free(text); + return ret; } @@ -711,18 +715,16 @@ struct sdp_xml_data *sdp_xml_data_alloc() struct sdp_xml_data *elem; elem = malloc(sizeof(struct sdp_xml_data)); + if (!elem) + return NULL; + + memset(elem, 0, sizeof(struct sdp_xml_data)); /* Null terminate the text */ elem->size = DEFAULT_XML_DATA_SIZE; elem->text = malloc(DEFAULT_XML_DATA_SIZE); elem->text[0] = '\0'; - elem->next = 0; - elem->data = 0; - - elem->type = 0; - elem->name = 0; - return elem; } @@ -734,7 +736,9 @@ void sdp_xml_data_free(struct sdp_xml_data *elem) if (elem->name) free(elem->name); - free(elem->text); + if (elem->text) + + free(elem->text); free(elem); } -- cgit From ce45df47b1a9a80f46cbb0ff1ae00308bf5046fa Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 20 Jan 2007 22:32:04 +0000 Subject: Handle multiple inotify event correctly --- common/notify-inotify.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'common') diff --git a/common/notify-inotify.c b/common/notify-inotify.c index a35cf745..5672a4ed 100644 --- a/common/notify-inotify.c +++ b/common/notify-inotify.c @@ -50,30 +50,37 @@ static notify_func callback = NULL; static gboolean io_event(GIOChannel *chan, GIOCondition cond, gpointer data) { - unsigned char buf[129]; - struct inotify_event *evt = (struct inotify_event *) buf; - int len; + unsigned char buf[129], *ptr = buf; + gsize len; + GIOError err; if (cond & (G_IO_HUP | G_IO_ERR)) return FALSE; memset(buf, 0, sizeof(buf)); - len = read(fd, buf, sizeof(buf) - 1); - if (len < sizeof(struct inotify_event)) + err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf) - 1, &len); + if (err == G_IO_ERROR_AGAIN) return TRUE; - if (evt->wd != wd || !callback) - return TRUE; + while (len >= sizeof(struct inotify_event)) { + struct inotify_event *evt = (struct inotify_event *) ptr; + + if (evt->wd != wd || !callback) + continue; - if (evt->mask & (IN_CREATE | IN_MOVED_TO)) - callback(NOTIFY_CREATE, evt->name, NULL); + if (evt->mask & (IN_CREATE | IN_MOVED_TO)) + callback(NOTIFY_CREATE, evt->name, NULL); - if (evt->mask & (IN_DELETE | IN_MOVED_FROM)) - callback(NOTIFY_DELETE, evt->name, NULL); + if (evt->mask & (IN_DELETE | IN_MOVED_FROM)) + callback(NOTIFY_DELETE, evt->name, NULL); - if (evt->mask & IN_MODIFY) - callback(NOTIFY_MODIFY, evt->name, NULL); + if (evt->mask & IN_MODIFY) + callback(NOTIFY_MODIFY, evt->name, NULL); + + len -= sizeof(struct inotify_event) + evt->len; + ptr += sizeof(struct inotify_event) + evt->len; + } return TRUE; } -- cgit From 6561447cafc0b9a857094c8aa43c0aeb0aa7adb2 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 21 Jan 2007 18:01:39 +0000 Subject: Check if value has changed before writing it --- common/test_textfile.c | 10 ++++++++++ common/textfile.c | 7 ++++++- 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'common') diff --git a/common/test_textfile.c b/common/test_textfile.c index 814c806b..1c001f46 100644 --- a/common/test_textfile.c +++ b/common/test_textfile.c @@ -62,6 +62,16 @@ int main(int argc, char *argv[]) else free(str); + snprintf(value, sizeof(value), "Test"); + if (textfile_put(filename, key, value) < 0) + fprintf(stderr, "%s (%d)\n", strerror(errno), errno); + + if (textfile_put(filename, key, value) < 0) + fprintf(stderr, "%s (%d)\n", strerror(errno), errno); + + if (textfile_put(filename, key, value) < 0) + fprintf(stderr, "%s (%d)\n", strerror(errno), errno); + if (textfile_del(filename, key) < 0) fprintf(stderr, "%s (%d)\n", strerror(errno), errno); diff --git a/common/textfile.c b/common/textfile.c index 36bde03f..895e3f3d 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -168,7 +168,8 @@ static int write_key(const char *pathname, const char *key, const char *value, i goto unlock; } - off = find_key(map, key, strlen(key), icase); + len = strlen(key); + off = find_key(map, key, len, icase); if (!off) { if (value) { munmap(map, size); @@ -186,6 +187,10 @@ static int write_key(const char *pathname, const char *key, const char *value, i goto unmap; } + if (value && (strlen(value) == end - off - len - 1) && + !strncmp(off + len + 1, value, end - off - len - 1)) + goto unmap; + len = strspn(end, "\r\n"); end += len; -- cgit From 3193afa28ace9972e36a418b22e83aa2ef9c08d1 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 21 Jan 2007 21:55:12 +0000 Subject: More accurate error reporting for GetConnectionUnixProcessID --- common/dbus.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index b6d852c3..7837aeba 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -319,6 +319,7 @@ dbus_bool_t dbus_bus_get_unix_process_id(DBusConnection *conn, const char *name, unsigned long *pid) { DBusMessage *msg, *reply; + DBusError err; dbus_uint32_t pid_arg; msg = dbus_message_new_method_call("org.freedesktop.DBus", @@ -337,16 +338,22 @@ dbus_bool_t dbus_bus_get_unix_process_id(DBusConnection *conn, const char *name, return FALSE; } - reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, NULL); - if (!reply) { - error("Sending GetConnectionUnixProcessID failed"); + dbus_error_init(&err); + reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err); + if (dbus_error_is_set(&err)) { + error("Sending GetConnectionUnixProcessID failed: %s", err.message); + dbus_error_free(&err); dbus_message_unref(msg); return FALSE; } - if (!dbus_message_get_args(reply, NULL, DBUS_TYPE_UINT32, &pid_arg, - DBUS_TYPE_INVALID)) { - error("Getting GetConnectionUnixProcessID args failed"); + dbus_error_init(&err); + dbus_message_get_args(reply, &err, DBUS_TYPE_UINT32, &pid_arg, + DBUS_TYPE_INVALID); + if (dbus_error_is_set(&err)) { + error("Getting GetConnectionUnixProcessID args failed: %s", + err.message); + dbus_error_free(&err); dbus_message_unref(msg); dbus_message_unref(reply); return FALSE; -- cgit From a0aeaf15caa9e967f6be1a7b3a3087ff9122c7a9 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 24 Jan 2007 19:47:56 +0000 Subject: Moved set_nonblocking to common/dbus.c --- common/dbus.c | 29 +++++++++++++++++++++++++++++ common/dbus.h | 2 ++ 2 files changed, 31 insertions(+) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index 7837aeba..92a86e73 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -643,3 +644,31 @@ DBusHandlerResult simple_introspect(DBusConnection *conn, return send_message_and_unref(conn, reply); } + +int set_nonblocking(int fd, int *err) +{ + long arg; + + arg = fcntl(fd, F_GETFL); + if (arg < 0) { + if (err) + *err = errno; + error("fcntl(F_GETFL): %s (%d)", strerror(errno), errno); + return -1; + } + + /* Return if already nonblocking */ + if (arg & O_NONBLOCK) + return 0; + + arg |= O_NONBLOCK; + if (fcntl(fd, F_SETFL, arg) < 0) { + if (err) + *err = errno; + error("fcntl(F_SETFL, O_NONBLOCK): %s (%d)", + strerror(errno), errno); + return -1; + } + + return 0; +} diff --git a/common/dbus.h b/common/dbus.h index 801d90c6..d59903ee 100644 --- a/common/dbus.h +++ b/common/dbus.h @@ -51,4 +51,6 @@ static inline DBusHandlerResult send_message_and_unref(DBusConnection *conn, DBu return DBUS_HANDLER_RESULT_HANDLED; } +int set_nonblocking(int fd, int *err); + #endif /* __H_BLUEZ_DBUS_H__ */ -- cgit From 97e3051ec51ac5bdcb37a371249360163eaf5709 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 25 Jan 2007 17:27:52 +0000 Subject: set_nonblocking: removed err argument --- common/dbus.c | 10 +++------- common/dbus.h | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index 92a86e73..bc1125fa 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -645,16 +645,14 @@ DBusHandlerResult simple_introspect(DBusConnection *conn, return send_message_and_unref(conn, reply); } -int set_nonblocking(int fd, int *err) +int set_nonblocking(int fd) { long arg; arg = fcntl(fd, F_GETFL); if (arg < 0) { - if (err) - *err = errno; error("fcntl(F_GETFL): %s (%d)", strerror(errno), errno); - return -1; + return -errno; } /* Return if already nonblocking */ @@ -663,11 +661,9 @@ int set_nonblocking(int fd, int *err) arg |= O_NONBLOCK; if (fcntl(fd, F_SETFL, arg) < 0) { - if (err) - *err = errno; error("fcntl(F_SETFL, O_NONBLOCK): %s (%d)", strerror(errno), errno); - return -1; + return -errno; } return 0; diff --git a/common/dbus.h b/common/dbus.h index d59903ee..f2bf45af 100644 --- a/common/dbus.h +++ b/common/dbus.h @@ -51,6 +51,6 @@ static inline DBusHandlerResult send_message_and_unref(DBusConnection *conn, DBu return DBUS_HANDLER_RESULT_HANDLED; } -int set_nonblocking(int fd, int *err); +int set_nonblocking(int fd); #endif /* __H_BLUEZ_DBUS_H__ */ -- cgit From e0dc99d9645f0fbbb73b53b010a9def48f285486 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 12 Feb 2007 19:48:09 +0000 Subject: Fix minor issues in SDP XML support --- common/sdp-xml.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'common') diff --git a/common/sdp-xml.c b/common/sdp-xml.c index abebc652..db07f03b 100644 --- a/common/sdp-xml.c +++ b/common/sdp-xml.c @@ -265,7 +265,7 @@ static void convert_raw_data_to_xml(sdp_data_t *value, int indent_level, if (hex) { appender(data, "encoding=\"hex\" "); strBuf = (char *) malloc(sizeof(char) - * (value->unitSize * 2 + 1)); + * ((value->unitSize-1) * 2 + 1)); /* Unit Size seems to include the size for dtd It is thus off by 1 @@ -276,7 +276,7 @@ static void convert_raw_data_to_xml(sdp_data_t *value, int indent_level, "%02x", (unsigned char) value->val.str[i]); - strBuf[value->unitSize * 2] = '\0'; + strBuf[(value->unitSize-1) * 2] = '\0'; } else { int j; @@ -603,7 +603,7 @@ sdp_data_t *sdp_xml_parse_int(const char * data, uint8_t dtd) buf[0] = data[i]; buf[1] = data[i + 1]; - val.data[i] = strtoul(buf, 0, 16); + val.data[i >> 1] = strtoul(buf, 0, 16); } ret = sdp_data_alloc(dtd, &val); -- cgit From 186bc5576263c712773b875bcafa256b3978b6e6 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 13 Feb 2007 14:49:07 +0000 Subject: Add common uinput.h include file --- common/Makefile.am | 3 +- common/uinput.h | 581 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 583 insertions(+), 1 deletion(-) create mode 100644 common/uinput.h (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index d9bd00ce..77a77322 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -29,7 +29,8 @@ test_textfile_LDADD = libhelper.a AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ -EXTRA_DIST = ppoll.h notify-dummy.c notify-inotify.c \ +EXTRA_DIST = ppoll.h uinput.h \ + notify-dummy.c notify-inotify.c \ sdp-dummy.c sdp-expat.c sdp-glib.c MAINTAINERCLEANFILES = Makefile.in diff --git a/common/uinput.h b/common/uinput.h new file mode 100644 index 00000000..277f843b --- /dev/null +++ b/common/uinput.h @@ -0,0 +1,581 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2003-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __UINPUT_H +#define __UINPUT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/* Events */ + +#define EV_SYN 0x00 +#define EV_KEY 0x01 +#define EV_REL 0x02 +#define EV_ABS 0x03 +#define EV_MSC 0x04 +#define EV_LED 0x11 +#define EV_SND 0x12 +#define EV_REP 0x14 +#define EV_FF 0x15 +#define EV_PWR 0x16 +#define EV_FF_STATUS 0x17 +#define EV_MAX 0x1f + +/* Synchronization events */ + +#define SYN_REPORT 0 +#define SYN_CONFIG 1 + +/* Keys and buttons */ + +#define KEY_RESERVED 0 +#define KEY_ESC 1 +#define KEY_1 2 +#define KEY_2 3 +#define KEY_3 4 +#define KEY_4 5 +#define KEY_5 6 +#define KEY_6 7 +#define KEY_7 8 +#define KEY_8 9 +#define KEY_9 10 +#define KEY_0 11 +#define KEY_MINUS 12 +#define KEY_EQUAL 13 +#define KEY_BACKSPACE 14 +#define KEY_TAB 15 +#define KEY_Q 16 +#define KEY_W 17 +#define KEY_E 18 +#define KEY_R 19 +#define KEY_T 20 +#define KEY_Y 21 +#define KEY_U 22 +#define KEY_I 23 +#define KEY_O 24 +#define KEY_P 25 +#define KEY_LEFTBRACE 26 +#define KEY_RIGHTBRACE 27 +#define KEY_ENTER 28 +#define KEY_LEFTCTRL 29 +#define KEY_A 30 +#define KEY_S 31 +#define KEY_D 32 +#define KEY_F 33 +#define KEY_G 34 +#define KEY_H 35 +#define KEY_J 36 +#define KEY_K 37 +#define KEY_L 38 +#define KEY_SEMICOLON 39 +#define KEY_APOSTROPHE 40 +#define KEY_GRAVE 41 +#define KEY_LEFTSHIFT 42 +#define KEY_BACKSLASH 43 +#define KEY_Z 44 +#define KEY_X 45 +#define KEY_C 46 +#define KEY_V 47 +#define KEY_B 48 +#define KEY_N 49 +#define KEY_M 50 +#define KEY_COMMA 51 +#define KEY_DOT 52 +#define KEY_SLASH 53 +#define KEY_RIGHTSHIFT 54 +#define KEY_KPASTERISK 55 +#define KEY_LEFTALT 56 +#define KEY_SPACE 57 +#define KEY_CAPSLOCK 58 +#define KEY_F1 59 +#define KEY_F2 60 +#define KEY_F3 61 +#define KEY_F4 62 +#define KEY_F5 63 +#define KEY_F6 64 +#define KEY_F7 65 +#define KEY_F8 66 +#define KEY_F9 67 +#define KEY_F10 68 +#define KEY_NUMLOCK 69 +#define KEY_SCROLLLOCK 70 +#define KEY_KP7 71 +#define KEY_KP8 72 +#define KEY_KP9 73 +#define KEY_KPMINUS 74 +#define KEY_KP4 75 +#define KEY_KP5 76 +#define KEY_KP6 77 +#define KEY_KPPLUS 78 +#define KEY_KP1 79 +#define KEY_KP2 80 +#define KEY_KP3 81 +#define KEY_KP0 82 +#define KEY_KPDOT 83 +#define KEY_103RD 84 +#define KEY_F13 85 +#define KEY_102ND 86 +#define KEY_F11 87 +#define KEY_F12 88 +#define KEY_F14 89 +#define KEY_F15 90 +#define KEY_F16 91 +#define KEY_F17 92 +#define KEY_F18 93 +#define KEY_F19 94 +#define KEY_F20 95 +#define KEY_KPENTER 96 +#define KEY_RIGHTCTRL 97 +#define KEY_KPSLASH 98 +#define KEY_SYSRQ 99 +#define KEY_RIGHTALT 100 +#define KEY_LINEFEED 101 +#define KEY_HOME 102 +#define KEY_UP 103 +#define KEY_PAGEUP 104 +#define KEY_LEFT 105 +#define KEY_RIGHT 106 +#define KEY_END 107 +#define KEY_DOWN 108 +#define KEY_PAGEDOWN 109 +#define KEY_INSERT 110 +#define KEY_DELETE 111 +#define KEY_MACRO 112 +#define KEY_MUTE 113 +#define KEY_VOLUMEDOWN 114 +#define KEY_VOLUMEUP 115 +#define KEY_POWER 116 +#define KEY_KPEQUAL 117 +#define KEY_KPPLUSMINUS 118 +#define KEY_PAUSE 119 +#define KEY_F21 120 +#define KEY_F22 121 +#define KEY_F23 122 +#define KEY_F24 123 +#define KEY_KPCOMMA 124 +#define KEY_LEFTMETA 125 +#define KEY_RIGHTMETA 126 +#define KEY_COMPOSE 127 + +#define KEY_STOP 128 +#define KEY_AGAIN 129 +#define KEY_PROPS 130 +#define KEY_UNDO 131 +#define KEY_FRONT 132 +#define KEY_COPY 133 +#define KEY_OPEN 134 +#define KEY_PASTE 135 +#define KEY_FIND 136 +#define KEY_CUT 137 +#define KEY_HELP 138 +#define KEY_MENU 139 +#define KEY_CALC 140 +#define KEY_SETUP 141 +#define KEY_SLEEP 142 +#define KEY_WAKEUP 143 +#define KEY_FILE 144 +#define KEY_SENDFILE 145 +#define KEY_DELETEFILE 146 +#define KEY_XFER 147 +#define KEY_PROG1 148 +#define KEY_PROG2 149 +#define KEY_WWW 150 +#define KEY_MSDOS 151 +#define KEY_COFFEE 152 +#define KEY_DIRECTION 153 +#define KEY_CYCLEWINDOWS 154 +#define KEY_MAIL 155 +#define KEY_BOOKMARKS 156 +#define KEY_COMPUTER 157 +#define KEY_BACK 158 +#define KEY_FORWARD 159 +#define KEY_CLOSECD 160 +#define KEY_EJECTCD 161 +#define KEY_EJECTCLOSECD 162 +#define KEY_NEXTSONG 163 +#define KEY_PLAYPAUSE 164 +#define KEY_PREVIOUSSONG 165 +#define KEY_STOPCD 166 +#define KEY_RECORD 167 +#define KEY_REWIND 168 +#define KEY_PHONE 169 +#define KEY_ISO 170 +#define KEY_CONFIG 171 +#define KEY_HOMEPAGE 172 +#define KEY_REFRESH 173 +#define KEY_EXIT 174 +#define KEY_MOVE 175 +#define KEY_EDIT 176 +#define KEY_SCROLLUP 177 +#define KEY_SCROLLDOWN 178 +#define KEY_KPLEFTPAREN 179 +#define KEY_KPRIGHTPAREN 180 + +#define KEY_INTL1 181 +#define KEY_INTL2 182 +#define KEY_INTL3 183 +#define KEY_INTL4 184 +#define KEY_INTL5 185 +#define KEY_INTL6 186 +#define KEY_INTL7 187 +#define KEY_INTL8 188 +#define KEY_INTL9 189 +#define KEY_LANG1 190 +#define KEY_LANG2 191 +#define KEY_LANG3 192 +#define KEY_LANG4 193 +#define KEY_LANG5 194 +#define KEY_LANG6 195 +#define KEY_LANG7 196 +#define KEY_LANG8 197 +#define KEY_LANG9 198 + +#define KEY_PLAYCD 200 +#define KEY_PAUSECD 201 +#define KEY_PROG3 202 +#define KEY_PROG4 203 +#define KEY_SUSPEND 205 +#define KEY_CLOSE 206 + +#define KEY_UNKNOWN 220 + +#define KEY_BRIGHTNESSDOWN 224 +#define KEY_BRIGHTNESSUP 225 + +#define BTN_MISC 0x100 +#define BTN_0 0x100 +#define BTN_1 0x101 +#define BTN_2 0x102 +#define BTN_3 0x103 +#define BTN_4 0x104 +#define BTN_5 0x105 +#define BTN_6 0x106 +#define BTN_7 0x107 +#define BTN_8 0x108 +#define BTN_9 0x109 + +#define BTN_MOUSE 0x110 +#define BTN_LEFT 0x110 +#define BTN_RIGHT 0x111 +#define BTN_MIDDLE 0x112 +#define BTN_SIDE 0x113 +#define BTN_EXTRA 0x114 +#define BTN_FORWARD 0x115 +#define BTN_BACK 0x116 +#define BTN_TASK 0x117 + +#define BTN_JOYSTICK 0x120 +#define BTN_TRIGGER 0x120 +#define BTN_THUMB 0x121 +#define BTN_THUMB2 0x122 +#define BTN_TOP 0x123 +#define BTN_TOP2 0x124 +#define BTN_PINKIE 0x125 +#define BTN_BASE 0x126 +#define BTN_BASE2 0x127 +#define BTN_BASE3 0x128 +#define BTN_BASE4 0x129 +#define BTN_BASE5 0x12a +#define BTN_BASE6 0x12b +#define BTN_DEAD 0x12f + +#define BTN_GAMEPAD 0x130 +#define BTN_A 0x130 +#define BTN_B 0x131 +#define BTN_C 0x132 +#define BTN_X 0x133 +#define BTN_Y 0x134 +#define BTN_Z 0x135 +#define BTN_TL 0x136 +#define BTN_TR 0x137 +#define BTN_TL2 0x138 +#define BTN_TR2 0x139 +#define BTN_SELECT 0x13a +#define BTN_START 0x13b +#define BTN_MODE 0x13c +#define BTN_THUMBL 0x13d +#define BTN_THUMBR 0x13e + +#define BTN_DIGI 0x140 +#define BTN_TOOL_PEN 0x140 +#define BTN_TOOL_RUBBER 0x141 +#define BTN_TOOL_BRUSH 0x142 +#define BTN_TOOL_PENCIL 0x143 +#define BTN_TOOL_AIRBRUSH 0x144 +#define BTN_TOOL_FINGER 0x145 +#define BTN_TOOL_MOUSE 0x146 +#define BTN_TOOL_LENS 0x147 +#define BTN_TOUCH 0x14a +#define BTN_STYLUS 0x14b +#define BTN_STYLUS2 0x14c +#define BTN_TOOL_DOUBLETAP 0x14d +#define BTN_TOOL_TRIPLETAP 0x14e + +#define BTN_WHEEL 0x150 +#define BTN_GEAR_DOWN 0x150 +#define BTN_GEAR_UP 0x151 + +#define KEY_OK 0x160 +#define KEY_SELECT 0x161 +#define KEY_GOTO 0x162 +#define KEY_CLEAR 0x163 +#define KEY_POWER2 0x164 +#define KEY_OPTION 0x165 +#define KEY_INFO 0x166 +#define KEY_TIME 0x167 +#define KEY_VENDOR 0x168 +#define KEY_ARCHIVE 0x169 +#define KEY_PROGRAM 0x16a +#define KEY_CHANNEL 0x16b +#define KEY_FAVORITES 0x16c +#define KEY_EPG 0x16d +#define KEY_PVR 0x16e +#define KEY_MHP 0x16f +#define KEY_LANGUAGE 0x170 +#define KEY_TITLE 0x171 +#define KEY_SUBTITLE 0x172 +#define KEY_ANGLE 0x173 +#define KEY_ZOOM 0x174 +#define KEY_MODE 0x175 +#define KEY_KEYBOARD 0x176 +#define KEY_SCREEN 0x177 +#define KEY_PC 0x178 +#define KEY_TV 0x179 +#define KEY_TV2 0x17a +#define KEY_VCR 0x17b +#define KEY_VCR2 0x17c +#define KEY_SAT 0x17d +#define KEY_SAT2 0x17e +#define KEY_CD 0x17f +#define KEY_TAPE 0x180 +#define KEY_RADIO 0x181 +#define KEY_TUNER 0x182 +#define KEY_PLAYER 0x183 +#define KEY_TEXT 0x184 +#define KEY_DVD 0x185 +#define KEY_AUX 0x186 +#define KEY_MP3 0x187 +#define KEY_AUDIO 0x188 +#define KEY_VIDEO 0x189 +#define KEY_DIRECTORY 0x18a +#define KEY_LIST 0x18b +#define KEY_MEMO 0x18c +#define KEY_CALENDAR 0x18d +#define KEY_RED 0x18e +#define KEY_GREEN 0x18f +#define KEY_YELLOW 0x190 +#define KEY_BLUE 0x191 +#define KEY_CHANNELUP 0x192 +#define KEY_CHANNELDOWN 0x193 +#define KEY_FIRST 0x194 +#define KEY_LAST 0x195 +#define KEY_AB 0x196 +#define KEY_NEXT 0x197 +#define KEY_RESTART 0x198 +#define KEY_SLOW 0x199 +#define KEY_SHUFFLE 0x19a +#define KEY_BREAK 0x19b +#define KEY_PREVIOUS 0x19c +#define KEY_DIGITS 0x19d +#define KEY_TEEN 0x19e +#define KEY_TWEN 0x19f + +#define KEY_MAX 0x1ff + +/* Relative axes */ + +#define REL_X 0x00 +#define REL_Y 0x01 +#define REL_Z 0x02 +#define REL_RX 0x03 +#define REL_RY 0x04 +#define REL_RZ 0x05 +#define REL_HWHEEL 0x06 +#define REL_DIAL 0x07 +#define REL_WHEEL 0x08 +#define REL_MISC 0x09 +#define REL_MAX 0x0f + +/* Absolute axes */ + +#define ABS_X 0x00 +#define ABS_Y 0x01 +#define ABS_Z 0x02 +#define ABS_RX 0x03 +#define ABS_RY 0x04 +#define ABS_RZ 0x05 +#define ABS_THROTTLE 0x06 +#define ABS_RUDDER 0x07 +#define ABS_WHEEL 0x08 +#define ABS_GAS 0x09 +#define ABS_BRAKE 0x0a +#define ABS_HAT0X 0x10 +#define ABS_HAT0Y 0x11 +#define ABS_HAT1X 0x12 +#define ABS_HAT1Y 0x13 +#define ABS_HAT2X 0x14 +#define ABS_HAT2Y 0x15 +#define ABS_HAT3X 0x16 +#define ABS_HAT3Y 0x17 +#define ABS_PRESSURE 0x18 +#define ABS_DISTANCE 0x19 +#define ABS_TILT_X 0x1a +#define ABS_TILT_Y 0x1b +#define ABS_TOOL_WIDTH 0x1c +#define ABS_VOLUME 0x20 +#define ABS_MISC 0x28 +#define ABS_MAX 0x3f + +/* Switch events */ + +#define SW_0 0x00 +#define SW_1 0x01 +#define SW_2 0x02 +#define SW_3 0x03 +#define SW_4 0x04 +#define SW_5 0x05 +#define SW_6 0x06 +#define SW_7 0x07 +#define SW_MAX 0x0f + +/* Misc events */ + +#define MSC_SERIAL 0x00 +#define MSC_PULSELED 0x01 +#define MSC_GESTURE 0x02 +#define MSC_RAW 0x03 +#define MSC_SCAN 0x04 +#define MSC_MAX 0x07 + +/* LEDs */ + +#define LED_NUML 0x00 +#define LED_CAPSL 0x01 +#define LED_SCROLLL 0x02 +#define LED_COMPOSE 0x03 +#define LED_KANA 0x04 +#define LED_SLEEP 0x05 +#define LED_SUSPEND 0x06 +#define LED_MUTE 0x07 +#define LED_MISC 0x08 +#define LED_MAIL 0x09 +#define LED_CHARGING 0x0a +#define LED_MAX 0x0f + +/* Autorepeat values */ + +#define REP_DELAY 0x00 +#define REP_PERIOD 0x01 +#define REP_MAX 0x01 + +/* Sounds */ + +#define SND_CLICK 0x00 +#define SND_BELL 0x01 +#define SND_TONE 0x02 +#define SND_MAX 0x07 + +/* Identifiers */ + +#define ID_BUS 0 +#define ID_VENDOR 1 +#define ID_PRODUCT 2 +#define ID_VERSION 3 + +#define BUS_PCI 0x01 +#define BUS_ISAPNP 0x02 +#define BUS_USB 0x03 +#define BUS_HIL 0x04 +#define BUS_BLUETOOTH 0x05 + +#define BUS_ISA 0x10 +#define BUS_I8042 0x11 +#define BUS_XTKBD 0x12 +#define BUS_RS232 0x13 +#define BUS_GAMEPORT 0x14 +#define BUS_PARPORT 0x15 +#define BUS_AMIGA 0x16 +#define BUS_ADB 0x17 +#define BUS_I2C 0x18 +#define BUS_HOST 0x19 +#define BUS_GSC 0x1A + +/* User input interface */ + +#define UINPUT_IOCTL_BASE 'U' + +#define UI_DEV_CREATE _IO(UINPUT_IOCTL_BASE, 1) +#define UI_DEV_DESTROY _IO(UINPUT_IOCTL_BASE, 2) + +#define UI_SET_EVBIT _IOW(UINPUT_IOCTL_BASE, 100, int) +#define UI_SET_KEYBIT _IOW(UINPUT_IOCTL_BASE, 101, int) +#define UI_SET_RELBIT _IOW(UINPUT_IOCTL_BASE, 102, int) +#define UI_SET_ABSBIT _IOW(UINPUT_IOCTL_BASE, 103, int) +#define UI_SET_MSCBIT _IOW(UINPUT_IOCTL_BASE, 104, int) +#define UI_SET_LEDBIT _IOW(UINPUT_IOCTL_BASE, 105, int) +#define UI_SET_SNDBIT _IOW(UINPUT_IOCTL_BASE, 106, int) +#define UI_SET_FFBIT _IOW(UINPUT_IOCTL_BASE, 107, int) +#define UI_SET_PHYS _IOW(UINPUT_IOCTL_BASE, 108, char*) +#define UI_SET_SWBIT _IOW(UINPUT_IOCTL_BASE, 109, int) + +#ifndef NBITS +#define NBITS(x) ((((x) - 1) / (sizeof(long) * 8)) + 1) +#endif + +#define UINPUT_MAX_NAME_SIZE 80 + +struct uinput_id { + uint16_t bustype; + uint16_t vendor; + uint16_t product; + uint16_t version; +}; + +struct uinput_dev { + char name[UINPUT_MAX_NAME_SIZE]; + struct uinput_id id; + int ff_effects_max; + int absmax[ABS_MAX + 1]; + int absmin[ABS_MAX + 1]; + int absfuzz[ABS_MAX + 1]; + int absflat[ABS_MAX + 1]; +}; + +struct uinput_event { + struct timeval time; + uint16_t type; + uint16_t code; + int32_t value; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __UINPUT_H */ -- cgit From 559a9a2ef363a2d9e81581f5846c59b0209c3575 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 16 Feb 2007 20:18:37 +0000 Subject: Add missing flags to g_io_add_watch calls --- common/notify-inotify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common') diff --git a/common/notify-inotify.c b/common/notify-inotify.c index 5672a4ed..281d4179 100644 --- a/common/notify-inotify.c +++ b/common/notify-inotify.c @@ -102,7 +102,7 @@ void notify_init(void) return; } - g_io_add_watch(io, G_IO_IN, io_event, NULL); + g_io_add_watch(io, G_IO_IN | G_IO_ERR | G_IO_HUP, io_event, NULL); } void notify_close(void) -- cgit From 3d16152fd30f2570ad8e9bb2427045e6fd317ce3 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 26 Feb 2007 13:44:45 +0000 Subject: More changes do use glib memory allocation --- common/dbus-helper.c | 16 ++++----------- common/dbus.c | 58 ++++++++++++++-------------------------------------- 2 files changed, 19 insertions(+), 55 deletions(-) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index 64b00cd8..7c14952b 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -90,7 +90,7 @@ static void generic_unregister(DBusConnection *connection, void *user_data) if (data->unregister_function) data->unregister_function(connection, data->user_data); - free(data); + g_free(data); } static struct interface_data *find_interface(GSList *interfaces, @@ -153,11 +153,7 @@ dbus_bool_t dbus_connection_create_object_path(DBusConnection *connection, { struct generic_data *data; - data = malloc(sizeof(*data)); - if (!data) - return FALSE; - - memset(data, 0, sizeof(*data)); + data = g_new0(struct generic_data, 1); data->user_data = user_data; data->unregister_function = function; @@ -167,7 +163,7 @@ dbus_bool_t dbus_connection_create_object_path(DBusConnection *connection, if (dbus_connection_register_object_path(connection, path, &generic_table, data) == FALSE) { - free(data); + g_free(data); return FALSE; } @@ -193,11 +189,7 @@ dbus_bool_t dbus_connection_register_interface(DBusConnection *connection, (void *) &data) == FALSE) return FALSE; - iface = malloc(sizeof(*iface)); - if (!iface) - return FALSE; - - memset(iface, 0, sizeof(*iface)); + iface = g_new0(struct interface_data, 1); iface->interface = interface; iface->methods = methods; diff --git a/common/dbus.c b/common/dbus.c index bc1125fa..6cf4b192 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -110,14 +110,11 @@ static void name_data_free(struct name_data *data) GSList *l; for (l = data->callbacks; l != NULL; l = l->next) - free(l->data); + g_free(l->data); g_slist_free(data->callbacks); - - if (data->name) - free(data->name); - - free(data); + g_free(data->name); + g_free(data); } static int name_data_add(const char *name, name_cb_t func, void *user_data) @@ -126,9 +123,7 @@ static int name_data_add(const char *name, name_cb_t func, void *user_data) struct name_data *data = NULL; struct name_callback *cb = NULL; - cb = malloc(sizeof(struct name_callback)); - if (!cb) - goto failed; + cb = g_new(struct name_callback, 1); cb->func = func; cb->user_data = user_data; @@ -139,30 +134,15 @@ static int name_data_add(const char *name, name_cb_t func, void *user_data) goto done; } - data = malloc(sizeof(struct name_data)); - if (!data) - goto failed; - - memset(data, 0, sizeof(struct name_data)); + data = g_new0(struct name_data, 1); - data->name = strdup(name); - if (!data->name) - goto failed; + data->name = g_strdup(name); name_listeners = g_slist_append(name_listeners, data); done: data->callbacks = g_slist_append(data->callbacks, cb); return first; - -failed: - if (data) - name_data_free(data); - - if (cb) - free(cb); - - return 0; } static void name_data_remove(const char *name, name_cb_t func, void *user_data) @@ -177,7 +157,7 @@ static void name_data_remove(const char *name, name_cb_t func, void *user_data) cb = name_callback_find(data->callbacks, func, user_data); if (cb) { data->callbacks = g_slist_remove(data->callbacks, cb); - free(cb); + g_free(cb); } if (!data->callbacks) { @@ -291,7 +271,7 @@ int name_listener_remove(DBusConnection *connection, const char *name, } data->callbacks = g_slist_remove(data->callbacks, cb); - free(cb); + g_free(cb); /* Don't remove the filter if other callbacks exist */ if (data->callbacks) @@ -434,9 +414,7 @@ static dbus_bool_t add_watch(DBusWatch *watch, void *data) if (!dbus_watch_get_enabled(watch)) return TRUE; - info = malloc(sizeof(struct watch_info)); - if (info == NULL) - return FALSE; + info = g_new(struct watch_info, 1); fd = dbus_watch_get_fd(watch); info->io = g_io_channel_unix_new(fd); @@ -464,7 +442,7 @@ static void remove_watch(DBusWatch *watch, void *data) g_source_remove(info->watch_id); g_io_channel_unref(info->io); dbus_connection_unref(info->conn); - free(info); + g_free(info); } } @@ -498,7 +476,7 @@ static void timeout_handler_free(void *data) return; g_source_remove(handler->id); - free(handler); + g_free(handler); } static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) @@ -508,8 +486,7 @@ static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) if (!dbus_timeout_get_enabled (timeout)) return TRUE; - handler = malloc(sizeof(timeout_handler_t)); - memset(handler, 0, sizeof(timeout_handler_t)); + handler = g_new0(timeout_handler_t, 1); handler->timeout = timeout; handler->id = g_timeout_add(dbus_timeout_get_interval(timeout), @@ -595,12 +572,7 @@ DBusConnection *init_dbus(const char *name, void (*disconnect_cb)(void *), void if (!disconnect_cb) return conn; - dc_data = malloc(sizeof(struct disconnect_data)); - if (!dc_data) { - error("Allocating disconnect data failed"); - dbus_connection_unref(conn); - return NULL; - } + dc_data = g_new(struct disconnect_data, 1); dc_data->disconnect_cb = disconnect_cb; dc_data->user_data = user_data; @@ -608,9 +580,9 @@ DBusConnection *init_dbus(const char *name, void (*disconnect_cb)(void *), void dbus_connection_set_exit_on_disconnect(conn, FALSE); if (!dbus_connection_add_filter(conn, disconnect_filter, - dc_data, free)) { + dc_data, g_free)) { error("Can't add D-Bus disconnect filter"); - free(dc_data); + g_free(dc_data); dbus_connection_unref(conn); return NULL; } -- cgit From d9aa4a2058eace37d5c2d15508b4c4d9962c2bb5 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 26 Feb 2007 20:48:15 +0000 Subject: Add textfile_caseput function --- common/textfile.c | 5 +++++ common/textfile.h | 1 + 2 files changed, 6 insertions(+) (limited to 'common') diff --git a/common/textfile.c b/common/textfile.c index 895e3f3d..ea7e80bb 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -320,6 +320,11 @@ int textfile_put(const char *pathname, const char *key, const char *value) return write_key(pathname, key, value, 0); } +int textfile_caseput(const char *pathname, const char *key, const char *value) +{ + return write_key(pathname, key, value, 1); +} + int textfile_del(const char *pathname, const char *key) { return write_key(pathname, key, NULL, 0); diff --git a/common/textfile.h b/common/textfile.h index 11d42d1e..f6559fea 100644 --- a/common/textfile.h +++ b/common/textfile.h @@ -30,6 +30,7 @@ int create_name(char *buf, size_t size, const char *path, const char *address, const char *name); int textfile_put(const char *pathname, const char *key, const char *value); +int textfile_caseput(const char *pathname, const char *key, const char *value); int textfile_del(const char *pathname, const char *key); int textfile_casedel(const char *pathname, const char *key); char *textfile_get(const char *pathname, const char *key); -- cgit From 6e2ea33ba70a7d6b6ffa614a8fe57fe7662b7c70 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 20 Mar 2007 14:48:00 +0000 Subject: Create a common HAL abstraction layer --- common/Makefile.am | 10 ++++-- common/hal-dummy.c | 37 ++++++++++++++++++++++ common/hal-libhal.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++ common/hal.h | 27 ++++++++++++++++ 4 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 common/hal-dummy.c create mode 100644 common/hal-libhal.c create mode 100644 common/hal.h (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index 77a77322..a2e50354 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -9,6 +9,12 @@ sdp_sources = sdp-dummy.c endif endif +if HAL +hal_sources = hal-libhal.c +else +hal_sources = hal-dummy.c +endif + if INOTIFY notify_sources = notify-inotify.c else @@ -21,7 +27,7 @@ libhelper_a_SOURCES = oui.h oui.c dbus.h dbus.c \ textfile.h textfile.c logging.h logging.c \ dbus-helper.h dbus-helper.c \ sdp-xml.h sdp-xml.c $(sdp_sources) \ - notify.h $(notify_sources) + hal.h $(hal_sources) notify.h $(notify_sources) noinst_PROGRAMS = test_textfile @@ -29,7 +35,7 @@ test_textfile_LDADD = libhelper.a AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ -EXTRA_DIST = ppoll.h uinput.h \ +EXTRA_DIST = ppoll.h uinput.h hal-dummy.c hal-libhal.c \ notify-dummy.c notify-inotify.c \ sdp-dummy.c sdp-expat.c sdp-glib.c diff --git a/common/hal-dummy.c b/common/hal-dummy.c new file mode 100644 index 00000000..e16a6b67 --- /dev/null +++ b/common/hal-dummy.c @@ -0,0 +1,37 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2006-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "hal.h" + +int hal_init(DBusConnection *conn) +{ + return 0; +} + +void hal_cleanup(void) +{ +} diff --git a/common/hal-libhal.c b/common/hal-libhal.c new file mode 100644 index 00000000..d3fe9717 --- /dev/null +++ b/common/hal-libhal.c @@ -0,0 +1,90 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2006-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include + +#include "logging.h" +#include "dbus.h" + +#include "hal.h" + +static LibHalContext *hal_ctx = NULL; + +int hal_init(DBusConnection *conn) +{ + char str[64], *udi; + + hal_ctx = libhal_ctx_new(); + if (!hal_ctx) + return -ENOMEM; + + conn = init_dbus(NULL, NULL, NULL); + + if (libhal_ctx_set_dbus_connection(hal_ctx, conn) == FALSE) { + error("Failed to connect HAL via system bus"); + libhal_ctx_free(hal_ctx); + hal_ctx = NULL; + return -EIO; + } + + if (libhal_ctx_init(hal_ctx, NULL) == FALSE) { + error("Unable to init HAL context"); + libhal_ctx_free(hal_ctx); + hal_ctx = NULL; + return -EIO; + } + + udi = libhal_new_device(hal_ctx, NULL); + + if (libhal_device_add_capability(hal_ctx, udi, "net", NULL) == FALSE) { + error("Failed to add device capability"); + } + + sprintf(str, "/org/freedesktop/Hal/devices/bluetooth_pan"); + + if (libhal_device_commit_to_gdl(hal_ctx, udi, str, NULL) == FALSE) { + error("Failed to add new HAL device"); + } + + return 0; +} + +void hal_cleanup(void) +{ + if (!hal_ctx) + return; + + libhal_ctx_shutdown(hal_ctx, NULL); + + libhal_ctx_free(hal_ctx); + + hal_ctx = NULL; +} diff --git a/common/hal.h b/common/hal.h new file mode 100644 index 00000000..5ff86a8a --- /dev/null +++ b/common/hal.h @@ -0,0 +1,27 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2006-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include + +int hal_init(DBusConnection *conn); +void hal_cleanup(void); -- cgit From 833ce8edc2b4cde819a2aa7efb8e562958c48acd Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 21 Mar 2007 14:24:15 +0000 Subject: Implement generic HAL device helpers --- common/hal-dummy.c | 5 +++++ common/hal-libhal.c | 49 +++++++++++++++++++++++++++++++++++-------------- common/hal.h | 7 +++++++ 3 files changed, 47 insertions(+), 14 deletions(-) (limited to 'common') diff --git a/common/hal-dummy.c b/common/hal-dummy.c index e16a6b67..8d6be05f 100644 --- a/common/hal-dummy.c +++ b/common/hal-dummy.c @@ -35,3 +35,8 @@ int hal_init(DBusConnection *conn) void hal_cleanup(void) { } + +int hal_add_device(struct hal_device *device) +{ + return 0; +} diff --git a/common/hal-libhal.c b/common/hal-libhal.c index d3fe9717..4ae97098 100644 --- a/common/hal-libhal.c +++ b/common/hal-libhal.c @@ -40,8 +40,6 @@ static LibHalContext *hal_ctx = NULL; int hal_init(DBusConnection *conn) { - char str[64], *udi; - hal_ctx = libhal_ctx_new(); if (!hal_ctx) return -ENOMEM; @@ -62,18 +60,6 @@ int hal_init(DBusConnection *conn) return -EIO; } - udi = libhal_new_device(hal_ctx, NULL); - - if (libhal_device_add_capability(hal_ctx, udi, "net", NULL) == FALSE) { - error("Failed to add device capability"); - } - - sprintf(str, "/org/freedesktop/Hal/devices/bluetooth_pan"); - - if (libhal_device_commit_to_gdl(hal_ctx, udi, str, NULL) == FALSE) { - error("Failed to add new HAL device"); - } - return 0; } @@ -88,3 +74,38 @@ void hal_cleanup(void) hal_ctx = NULL; } + +int hal_add_device(struct hal_device *device) +{ + char udi[128], *dev; + char *str = "00000000-0000-1000-8000-00805f9b34fb"; + + dev = libhal_new_device(hal_ctx, NULL); + + if (libhal_device_add_capability(hal_ctx, dev, + "bluetooth", NULL) == FALSE) { + error("Failed to add device capability"); + } + + if (libhal_device_set_property_string(hal_ctx, dev, + "bluetooth.uuid", str, NULL) == FALSE) { + error("Failed to add UUID property"); + } + + if (libhal_device_set_property_bool(hal_ctx, dev, + "bluetooth.is_connected", FALSE, NULL) == FALSE) { + error("Failed to add connected state property"); + } + + sprintf(udi, "/org/freedesktop/Hal/devices/bluetooth_network_connection_aabbccddeeff"); + + if (libhal_remove_device(hal_ctx, udi, NULL) == FALSE) { + error("Can't remove old HAL device"); + } + + if (libhal_device_commit_to_gdl(hal_ctx, dev, udi, NULL) == FALSE) { + error("Failed to add new HAL device"); + } + + return 0; +} diff --git a/common/hal.h b/common/hal.h index 5ff86a8a..f2afacad 100644 --- a/common/hal.h +++ b/common/hal.h @@ -25,3 +25,10 @@ int hal_init(DBusConnection *conn); void hal_cleanup(void); + +struct hal_device { + char *udi; + char uuid[37]; +}; + +int hal_add_device(struct hal_device *); -- cgit From 4128274b3b8c47a58f6895e1dbe5b1949887b9e1 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 21 Mar 2007 19:35:35 +0000 Subject: Add functions for creating and removing HAL devices --- common/hal-dummy.c | 7 ++++++- common/hal-libhal.c | 56 +++++++++++++++++++++++++++++++++++++++++++---------- common/hal.h | 3 ++- 3 files changed, 54 insertions(+), 12 deletions(-) (limited to 'common') diff --git a/common/hal-dummy.c b/common/hal-dummy.c index 8d6be05f..a516ed1b 100644 --- a/common/hal-dummy.c +++ b/common/hal-dummy.c @@ -36,7 +36,12 @@ void hal_cleanup(void) { } -int hal_add_device(struct hal_device *device) +int hal_create_device(struct hal_device *device) +{ + return 0; +} + +int hal_remove_device(struct hal_device *device) { return 0; } diff --git a/common/hal-libhal.c b/common/hal-libhal.c index 4ae97098..cf8ece1f 100644 --- a/common/hal-libhal.c +++ b/common/hal-libhal.c @@ -38,6 +38,19 @@ static LibHalContext *hal_ctx = NULL; +static DBusHandlerResult filter_function(DBusConnection *connection, + DBusMessage *message, void *userdata) +{ + info("filter_function: sender=%s destination=%s obj_path=%s interface=%s method=%s", + dbus_message_get_sender (message), + dbus_message_get_destination (message), + dbus_message_get_path (message), + dbus_message_get_interface (message), + dbus_message_get_member (message)); + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + int hal_init(DBusConnection *conn) { hal_ctx = libhal_ctx_new(); @@ -46,6 +59,8 @@ int hal_init(DBusConnection *conn) conn = init_dbus(NULL, NULL, NULL); + dbus_connection_add_filter(conn, filter_function, NULL, NULL); + if (libhal_ctx_set_dbus_connection(hal_ctx, conn) == FALSE) { error("Failed to connect HAL via system bus"); libhal_ctx_free(hal_ctx); @@ -75,18 +90,14 @@ void hal_cleanup(void) hal_ctx = NULL; } -int hal_add_device(struct hal_device *device) +int hal_create_device(struct hal_device *device) { + DBusError err; char udi[128], *dev; char *str = "00000000-0000-1000-8000-00805f9b34fb"; dev = libhal_new_device(hal_ctx, NULL); - if (libhal_device_add_capability(hal_ctx, dev, - "bluetooth", NULL) == FALSE) { - error("Failed to add device capability"); - } - if (libhal_device_set_property_string(hal_ctx, dev, "bluetooth.uuid", str, NULL) == FALSE) { error("Failed to add UUID property"); @@ -97,14 +108,39 @@ int hal_add_device(struct hal_device *device) error("Failed to add connected state property"); } - sprintf(udi, "/org/freedesktop/Hal/devices/bluetooth_network_connection_aabbccddeeff"); + if (libhal_device_add_capability(hal_ctx, dev, + "bluetooth", NULL) == FALSE) { + error("Failed to add device capability"); + } - if (libhal_remove_device(hal_ctx, udi, NULL) == FALSE) { - error("Can't remove old HAL device"); + sprintf(udi, "/org/freedesktop/Hal/devices/bluetooth_test"); + + dbus_error_init(&err); + if (libhal_device_claim_interface(hal_ctx, dev, + "org.freedesktop.Hal.Device.MyBluetooth", + " \n" + " \n" + " \n" + " \n", + &err) == FALSE) { + error("Failed to claim to interface: ", err.message); } if (libhal_device_commit_to_gdl(hal_ctx, dev, udi, NULL) == FALSE) { - error("Failed to add new HAL device"); + error("Failed to create HAL device"); + } + + return 0; +} + +int hal_remove_device(struct hal_device *device) +{ + char udi[128]; + + sprintf(udi, "/org/freedesktop/Hal/devices/bluetooth_test"); + + if (libhal_remove_device(hal_ctx, udi, NULL) == FALSE) { + error("Failed to remove HAL device"); } return 0; diff --git a/common/hal.h b/common/hal.h index f2afacad..5f80fb92 100644 --- a/common/hal.h +++ b/common/hal.h @@ -31,4 +31,5 @@ struct hal_device { char uuid[37]; }; -int hal_add_device(struct hal_device *); +int hal_create_device(struct hal_device *); +int hal_remove_device(struct hal_device *); -- cgit From 0fb47243d42d7d945d78f468bc3c403ec79c2c2d Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 27 Mar 2007 09:59:49 +0000 Subject: Provide additional D-Bus setup helper function --- common/dbus.c | 15 ++++++++++----- common/dbus.h | 6 +++++- 2 files changed, 15 insertions(+), 6 deletions(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index 6cf4b192..6a7eeb0f 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -483,7 +483,7 @@ static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) { timeout_handler_t *handler; - if (!dbus_timeout_get_enabled (timeout)) + if (!dbus_timeout_get_enabled(timeout)) return TRUE; handler = g_new0(timeout_handler_t, 1); @@ -499,7 +499,6 @@ static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) static void remove_timeout(DBusTimeout *timeout, void *data) { - } static void timeout_toggled(DBusTimeout *timeout, void *data) @@ -511,8 +510,7 @@ static void timeout_toggled(DBusTimeout *timeout, void *data) } static void dispatch_status_cb(DBusConnection *conn, - DBusDispatchStatus new_status, - void *data) + DBusDispatchStatus new_status, void *data) { if (!dbus_connection_get_is_connected(conn)) return; @@ -522,7 +520,8 @@ static void dispatch_status_cb(DBusConnection *conn, } #endif -DBusConnection *init_dbus(const char *name, void (*disconnect_cb)(void *), void *user_data) +DBusConnection *init_dbus(const char *name, + void (*disconnect_cb)(void *), void *user_data) { struct disconnect_data *dc_data; DBusConnection *conn; @@ -590,6 +589,12 @@ DBusConnection *init_dbus(const char *name, void (*disconnect_cb)(void *), void return conn; } +DBusConnection *dbus_bus_system_setup_with_main_loop(const char *name, + void (*disconnect_cb)(void *), void *user_data) +{ + return init_dbus(name, disconnect_cb, user_data); +} + static char simple_xml[] = DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE ""; DBusHandlerResult simple_introspect(DBusConnection *conn, diff --git a/common/dbus.h b/common/dbus.h index f2bf45af..4e4ed487 100644 --- a/common/dbus.h +++ b/common/dbus.h @@ -26,7 +26,11 @@ #include -DBusConnection *init_dbus(const char *name, void (*disconnect_cb)(void *), void *user_data); +DBusConnection *init_dbus(const char *name, + void (*disconnect_cb)(void *), void *user_data); + +DBusConnection *dbus_bus_system_setup_with_main_loop(const char *name, + void (*disconnect_cb)(void *), void *user_data); DBusHandlerResult simple_introspect(DBusConnection *conn, DBusMessage *msg, void *user_data); -- cgit From fe864ec0e6fe3e9be945cf1c02e5f343593c883f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 27 Mar 2007 10:13:55 +0000 Subject: Add register_service() helper function --- common/dbus.c | 30 ++++++++++++++++++++++++++++++ common/dbus.h | 3 +++ 2 files changed, 33 insertions(+) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index 6a7eeb0f..e4bcbba5 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -645,3 +645,33 @@ int set_nonblocking(int fd) return 0; } + +void register_service(DBusConnection *conn, const char *identifier, + const char *name, const char *description) +{ + DBusMessage *msg, *reply; + + info("Registering service"); + + msg = dbus_message_new_method_call("org.bluez", "/org/bluez", + "org.bluez.Database", "RegisterService"); + if (!msg) { + error("Can't create service register method"); + return; + } + + dbus_message_append_args(msg, DBUS_TYPE_STRING, &identifier, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_STRING, &description, DBUS_TYPE_INVALID); + + reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, NULL); + if (!reply) { + error("Can't register service"); + return; + } + + dbus_message_unref(msg); + dbus_message_unref(reply); + + dbus_connection_flush(conn); +} diff --git a/common/dbus.h b/common/dbus.h index 4e4ed487..692db0ac 100644 --- a/common/dbus.h +++ b/common/dbus.h @@ -57,4 +57,7 @@ static inline DBusHandlerResult send_message_and_unref(DBusConnection *conn, DBu int set_nonblocking(int fd); +void register_service(DBusConnection *conn, const char *identifier, + const char *name, const char *description); + #endif /* __H_BLUEZ_DBUS_H__ */ -- cgit From d93651492d899c8fb4692207f44e44ac1e2049f5 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 27 Mar 2007 10:18:44 +0000 Subject: Rename register_service() function to avoid conflicts --- common/dbus.c | 2 +- common/dbus.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index e4bcbba5..db50fcc9 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -646,7 +646,7 @@ int set_nonblocking(int fd) return 0; } -void register_service(DBusConnection *conn, const char *identifier, +void register_external_service(DBusConnection *conn, const char *identifier, const char *name, const char *description) { DBusMessage *msg, *reply; diff --git a/common/dbus.h b/common/dbus.h index 692db0ac..26ccb6e0 100644 --- a/common/dbus.h +++ b/common/dbus.h @@ -57,7 +57,7 @@ static inline DBusHandlerResult send_message_and_unref(DBusConnection *conn, DBu int set_nonblocking(int fd); -void register_service(DBusConnection *conn, const char *identifier, +void register_external_service(DBusConnection *conn, const char *identifier, const char *name, const char *description); #endif /* __H_BLUEZ_DBUS_H__ */ -- cgit From 3e3f6b041fd5a9f876c9a2fd87be366cc5621c17 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 27 Mar 2007 10:20:41 +0000 Subject: Remove D-Bus connection workaround --- common/hal-libhal.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'common') diff --git a/common/hal-libhal.c b/common/hal-libhal.c index cf8ece1f..3787e73d 100644 --- a/common/hal-libhal.c +++ b/common/hal-libhal.c @@ -57,8 +57,6 @@ int hal_init(DBusConnection *conn) if (!hal_ctx) return -ENOMEM; - conn = init_dbus(NULL, NULL, NULL); - dbus_connection_add_filter(conn, filter_function, NULL, NULL); if (libhal_ctx_set_dbus_connection(hal_ctx, conn) == FALSE) { -- cgit From 28a77bb7c841ce428071f6b6edd3539e1f8dc16a Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Mon, 16 Apr 2007 21:34:08 +0000 Subject: Move append_dict_entry to utils/common and change the name to dbus_message_iter_append_dict_entry. --- common/dbus-helper.c | 35 +++++++++++++++++++++++++++++++++++ common/dbus-helper.h | 3 +++ 2 files changed, 38 insertions(+) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index 7c14952b..d0082451 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -209,3 +209,38 @@ dbus_bool_t dbus_connection_unregister_interface(DBusConnection *connection, { return TRUE; } + +void dbus_message_iter_append_dict_entry(DBusMessageIter *dict, + const char *key, int type, void *val) +{ + DBusMessageIter entry; + DBusMessageIter value; + char *sig; + + dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, NULL, &entry); + + dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key); + + switch (type) { + case DBUS_TYPE_STRING: + sig = DBUS_TYPE_STRING_AS_STRING; + break; + case DBUS_TYPE_UINT32: + sig = DBUS_TYPE_UINT32_AS_STRING; + break; + case DBUS_TYPE_BOOLEAN: + sig = DBUS_TYPE_BOOLEAN_AS_STRING; + break; + default: + sig = DBUS_TYPE_VARIANT_AS_STRING; + break; + } + + dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, sig, &value); + + dbus_message_iter_append_basic(&value, type, val); + + dbus_message_iter_close_container(&entry, &value); + + dbus_message_iter_close_container(dict, &entry); +} diff --git a/common/dbus-helper.h b/common/dbus-helper.h index 0c33a04f..312ab9b5 100644 --- a/common/dbus-helper.h +++ b/common/dbus-helper.h @@ -55,3 +55,6 @@ dbus_bool_t dbus_connection_register_interface(DBusConnection *connection, dbus_bool_t dbus_connection_unregister_interface(DBusConnection *connection, const char *path, const char *interface); +void dbus_message_iter_append_dict_entry(DBusMessageIter *dict, + const char *key, int type, void *val); + -- cgit From 30957bc2890f3db99907178304046610e77c7efa Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 3 May 2007 10:58:08 +0000 Subject: generic introspection cleanup & small additions --- common/dbus-helper.c | 39 ++++++++++++++++++++++++++++----------- common/dbus-helper.h | 13 +++++++++++-- 2 files changed, 39 insertions(+), 13 deletions(-) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index d0082451..b5a4ccc7 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -44,8 +44,10 @@ struct generic_data { }; struct interface_data { - const char *interface; + char *name; DBusMethodVTable *methods; + DBusSignalVTable *signals; + DBusPropertyVTable *properties; }; DBusHandlerResult dbus_connection_send_and_unref(DBusConnection *connection, @@ -94,13 +96,13 @@ static void generic_unregister(DBusConnection *connection, void *user_data) } static struct interface_data *find_interface(GSList *interfaces, - const char *interface) + const char *name) { GSList *list; for (list = interfaces; list; list = list->next) { struct interface_data *iface = list->data; - if (!strcmp(interface, iface->interface)) + if (!strcmp(name, iface->name)) return iface; } @@ -128,7 +130,7 @@ static DBusHandlerResult generic_message(DBusConnection *connection, for (current = iface->methods; current->name && current->message_function; current++) { if (dbus_message_is_method_call(message, - iface->interface, current->name) == FALSE) + iface->name, current->name) == FALSE) continue; if (dbus_message_has_signature(message, @@ -177,13 +179,16 @@ dbus_bool_t dbus_connection_destroy_object_path(DBusConnection *connection, } dbus_bool_t dbus_connection_register_interface(DBusConnection *connection, - const char *path, const char *interface, + const char *path, const char *name, DBusMethodVTable *methods, + DBusSignalVTable *signals, DBusPropertyVTable *properties) { struct generic_data *data; struct interface_data *iface; - DBusMethodVTable *current; + DBusMethodVTable *method; + DBusSignalVTable *signal; + DBusPropertyVTable *property; if (dbus_connection_get_object_path_data(connection, path, (void *) &data) == FALSE) @@ -191,12 +196,24 @@ dbus_bool_t dbus_connection_register_interface(DBusConnection *connection, iface = g_new0(struct interface_data, 1); - iface->interface = interface; + iface->name = g_strdup(name); iface->methods = methods; + iface->signals = signals; + iface->properties = properties; + + for (method = iface->methods; method && method->name; method++) { + debug("Adding introspection data for method %s.%s", + iface->name, method->name); + } + + for (signal = iface->signals; signal && signal->name; signal++) { + debug("Adding introspection data for signal %s.%s", + iface->name, signal->name); + } - for (current = iface->methods; current->name; current++) { - debug("Adding introspection data for %s.%s", - interface, current->name); + for (property = iface->properties; property && property->name; property++) { + debug("Adding introspection data for property %s.%s", + iface->name, property->name); } data->interfaces = g_slist_append(data->interfaces, iface); @@ -205,7 +222,7 @@ dbus_bool_t dbus_connection_register_interface(DBusConnection *connection, } dbus_bool_t dbus_connection_unregister_interface(DBusConnection *connection, - const char *path, const char *interface) + const char *path, const char *name) { return TRUE; } diff --git a/common/dbus-helper.h b/common/dbus-helper.h index 312ab9b5..1c3809d7 100644 --- a/common/dbus-helper.h +++ b/common/dbus-helper.h @@ -43,18 +43,27 @@ struct DBusMethodVTable { const char *reply; }; +typedef struct DBusSignalVTable DBusSignalVTable; + +struct DBusSignalVTable { + const char *name; + const char *signature; +}; + typedef struct DBusPropertyVTable DBusPropertyVTable; struct DBusPropertyVTable { + const char *name; }; dbus_bool_t dbus_connection_register_interface(DBusConnection *connection, - const char *path, const char *interface, + const char *path, const char *name, DBusMethodVTable *methods, + DBusSignalVTable *signals, DBusPropertyVTable *properties); dbus_bool_t dbus_connection_unregister_interface(DBusConnection *connection, - const char *path, const char *interface); + const char *path, const char *name); void dbus_message_iter_append_dict_entry(DBusMessageIter *dict, const char *key, int type, void *val); -- cgit From d370964fbe6a9e32837037dcf193a216a0a75077 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 3 May 2007 14:19:09 +0000 Subject: More generic introspection implementation (doesn't work with eglib yet) --- common/dbus-helper.c | 110 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 89 insertions(+), 21 deletions(-) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index b5a4ccc7..a1bafb59 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -92,6 +92,7 @@ static void generic_unregister(DBusConnection *connection, void *user_data) if (data->unregister_function) data->unregister_function(connection, data->user_data); + g_free(data->introspect); g_free(data); } @@ -147,7 +148,70 @@ static DBusObjectPathVTable generic_table = { .message_function = generic_message, }; -static char simple_xml[] = DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE ""; +static void print_arguments(GString *gstr, const char *sig, const char *direction) +{ + int i; + + for (i = 0; sig[i]; i++) { + if (direction) + g_string_append_printf(gstr, + "\t\t\t\n", + sig[i], direction); + else + g_string_append_printf(gstr, + "\t\t\t\n", + sig[i]); + } +} + +static void update_introspection_data(struct generic_data *data, const char *path) +{ + GSList *list; + GString *gstr; + + g_free(data->introspect); + + gstr = g_string_new(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE); + + g_string_append_printf(gstr, "\n", path); + + for (list = data->interfaces; list; list = list->next) { + struct interface_data *iface = list->data; + DBusMethodVTable *method; + DBusSignalVTable *signal; + DBusPropertyVTable *property; + + g_string_append_printf(gstr, "\t\n", iface->name); + + for (method = iface->methods; method && method->name; method++) { + debug("Adding introspection data for method %s.%s", + iface->name, method->name); + g_string_append_printf(gstr, "\t\t\n", method->name); + print_arguments(gstr, method->signature, "in"); + print_arguments(gstr, method->reply, "out"); + g_string_append_printf(gstr, "\t\t\n"); + } + + for (signal = iface->signals; signal && signal->name; signal++) { + debug("Adding introspection data for signal %s.%s", + iface->name, signal->name); + g_string_append_printf(gstr, "\t\t\n", signal->name); + print_arguments(gstr, signal->signature, NULL); + g_string_append_printf(gstr, "\t\t\n"); + } + + for (property = iface->properties; property && property->name; property++) { + debug("Adding introspection data for property %s.%s", + iface->name, property->name); + } + + g_string_append_printf(gstr, "\t\n"); + } + + g_string_append_printf(gstr, "\n"); + + data->introspect = g_string_free(gstr, FALSE); +} dbus_bool_t dbus_connection_create_object_path(DBusConnection *connection, const char *path, void *user_data, @@ -160,8 +224,7 @@ dbus_bool_t dbus_connection_create_object_path(DBusConnection *connection, data->user_data = user_data; data->unregister_function = function; - data->interfaces = NULL; - data->introspect = simple_xml; + data->introspect = g_strdup(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE ""); if (dbus_connection_register_object_path(connection, path, &generic_table, data) == FALSE) { @@ -186,14 +249,14 @@ dbus_bool_t dbus_connection_register_interface(DBusConnection *connection, { struct generic_data *data; struct interface_data *iface; - DBusMethodVTable *method; - DBusSignalVTable *signal; - DBusPropertyVTable *property; if (dbus_connection_get_object_path_data(connection, path, (void *) &data) == FALSE) return FALSE; + if (find_interface(data->interfaces, name)) + return FALSE; + iface = g_new0(struct interface_data, 1); iface->name = g_strdup(name); @@ -201,29 +264,34 @@ dbus_bool_t dbus_connection_register_interface(DBusConnection *connection, iface->signals = signals; iface->properties = properties; - for (method = iface->methods; method && method->name; method++) { - debug("Adding introspection data for method %s.%s", - iface->name, method->name); - } - - for (signal = iface->signals; signal && signal->name; signal++) { - debug("Adding introspection data for signal %s.%s", - iface->name, signal->name); - } - - for (property = iface->properties; property && property->name; property++) { - debug("Adding introspection data for property %s.%s", - iface->name, property->name); - } - data->interfaces = g_slist_append(data->interfaces, iface); + update_introspection_data(data, path); + return TRUE; } dbus_bool_t dbus_connection_unregister_interface(DBusConnection *connection, const char *path, const char *name) { + struct generic_data *data; + struct interface_data *iface; + + if (dbus_connection_get_object_path_data(connection, path, + (void *) &data) == FALSE) + return FALSE; + + iface = find_interface(data->interfaces, name); + if (!iface) + return FALSE; + + data->interfaces = g_slist_remove(data->interfaces, iface); + + g_free(iface->name); + g_free(iface); + + update_introspection_data(data, path); + return TRUE; } -- cgit From 223aa9581953c03f371a10b3f0555f7fa132f690 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 3 May 2007 21:08:32 +0000 Subject: Properly split the signature string into single complete types --- common/dbus-helper.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 4 deletions(-) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index a1bafb59..38174aa3 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -153,14 +153,56 @@ static void print_arguments(GString *gstr, const char *sig, const char *directio int i; for (i = 0; sig[i]; i++) { + char type[32]; + int len, struct_level, dict_level; + gboolean complete; + + complete = FALSE; + struct_level = dict_level = 0; + memset(type, 0, sizeof(type)); + + /* Gather enough data to have a single complete type */ + for (len = 0; len < (sizeof(type) - 1) && sig[i]; len++, i++) { + switch (sig[i]){ + case '(': + struct_level++; + break; + case ')': + struct_level--; + if (struct_level <= 0 && dict_level <= 0) + complete = TRUE; + break; + case '{': + dict_level++; + break; + case '}': + dict_level--; + if (struct_level <= 0 && dict_level <= 0) + complete = TRUE; + break; + case 'a': + break; + default: + if (struct_level <= 0 && dict_level <= 0) + complete = TRUE; + break; + } + + type[len] = sig[i]; + + if (complete) + break; + } + + if (direction) g_string_append_printf(gstr, - "\t\t\t\n", - sig[i], direction); + "\t\t\t\n", + type, direction); else g_string_append_printf(gstr, - "\t\t\t\n", - sig[i]); + "\t\t\t\n", + type); } } -- cgit From 16dceb4c2f7a8ed91c88b1c1353b6bd5ccc68cbf Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 4 May 2007 15:04:41 +0000 Subject: Add dbus_connection_get_object_user_data function to retreive the real user data --- common/dbus-helper.c | 15 +++++++++++++++ common/dbus-helper.h | 4 ++++ 2 files changed, 19 insertions(+) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index 38174aa3..dd14f3c9 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -283,6 +283,21 @@ dbus_bool_t dbus_connection_destroy_object_path(DBusConnection *connection, return dbus_connection_unregister_object_path(connection, path); } +dbus_bool_t dbus_connection_get_object_user_data(DBusConnection *connection, + const char *path, + void **data_p) +{ + struct generic_data *data; + + if (dbus_connection_get_object_path_data(connection, path, + (void *) &data) == FALSE) + return FALSE; + + *data_p = data->user_data; + + return TRUE; +} + dbus_bool_t dbus_connection_register_interface(DBusConnection *connection, const char *path, const char *name, DBusMethodVTable *methods, diff --git a/common/dbus-helper.h b/common/dbus-helper.h index 1c3809d7..49db1c58 100644 --- a/common/dbus-helper.h +++ b/common/dbus-helper.h @@ -34,6 +34,10 @@ dbus_bool_t dbus_connection_create_object_path(DBusConnection *connection, dbus_bool_t dbus_connection_destroy_object_path(DBusConnection *connection, const char *path); +dbus_bool_t dbus_connection_get_object_user_data(DBusConnection *connection, + const char *path, + void **data_p); + typedef struct DBusMethodVTable DBusMethodVTable; struct DBusMethodVTable { -- cgit From 46564396bfb21f61f839aa7f8fe9cb954c10af14 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 4 May 2007 15:51:27 +0000 Subject: Improve formating of introspection data reporting --- common/dbus-helper.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index dd14f3c9..7dbb2dc0 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -226,25 +226,37 @@ static void update_introspection_data(struct generic_data *data, const char *pat g_string_append_printf(gstr, "\t\n", iface->name); for (method = iface->methods; method && method->name; method++) { - debug("Adding introspection data for method %s.%s", - iface->name, method->name); - g_string_append_printf(gstr, "\t\t\n", method->name); - print_arguments(gstr, method->signature, "in"); - print_arguments(gstr, method->reply, "out"); - g_string_append_printf(gstr, "\t\t\n"); + debug("%s: adding method %s.%s", + path, iface->name, method->name); + if (!strlen(method->signature) && !strlen(method->reply)) + g_string_append_printf(gstr, "\t\t\n", + method->name); + else { + g_string_append_printf(gstr, "\t\t\n", + method->name); + print_arguments(gstr, method->signature, "in"); + print_arguments(gstr, method->reply, "out"); + g_string_append_printf(gstr, "\t\t\n"); + } } for (signal = iface->signals; signal && signal->name; signal++) { - debug("Adding introspection data for signal %s.%s", - iface->name, signal->name); - g_string_append_printf(gstr, "\t\t\n", signal->name); - print_arguments(gstr, signal->signature, NULL); - g_string_append_printf(gstr, "\t\t\n"); + debug("%s: adding signal %s.%s", + path, iface->name, signal->name); + if (!strlen(signal->signature)) + g_string_append_printf(gstr, "\t\t\n", + signal->name); + else { + g_string_append_printf(gstr, "\t\t\n", + signal->name); + print_arguments(gstr, signal->signature, NULL); + g_string_append_printf(gstr, "\t\t\n"); + } } for (property = iface->properties; property && property->name; property++) { - debug("Adding introspection data for property %s.%s", - iface->name, property->name); + debug("%s: adding property %s.%s", + path, iface->name, property->name); } g_string_append_printf(gstr, "\t\n"); -- cgit From 5cf1ae29510f5ec975080c793c692fedc10d86d8 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 4 May 2007 16:31:44 +0000 Subject: Include child nodes in the introspection data --- common/dbus-helper.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 4 deletions(-) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index 7dbb2dc0..639b6d3f 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -206,10 +206,12 @@ static void print_arguments(GString *gstr, const char *sig, const char *directio } } -static void update_introspection_data(struct generic_data *data, const char *path) +static void update_introspection_data(DBusConnection *conn, struct generic_data *data, const char *path) { GSList *list; GString *gstr; + char **children; + int i; g_free(data->introspect); @@ -262,11 +264,47 @@ static void update_introspection_data(struct generic_data *data, const char *pat g_string_append_printf(gstr, "\t\n"); } + if (!dbus_connection_list_registered(conn, path, &children)) + goto done; + + for (i = 0; children[i]; i++) + g_string_append_printf(gstr, "\t\n", children[i]); + + dbus_free_string_array(children); + +done: g_string_append_printf(gstr, "\n"); data->introspect = g_string_free(gstr, FALSE); } +static void update_parent_data(DBusConnection *conn, const char *child_path) +{ + struct generic_data *data; + char *parent_path, *slash; + + parent_path = g_strdup(child_path); + slash = strrchr(parent_path, '/'); + if (!slash) + goto done; + + *slash = '\0'; + if (!strlen(parent_path)) + goto done; + + if (!dbus_connection_get_object_path_data(conn, parent_path, + (void *) &data)) + goto done; + + if (!data) + goto done; + + update_introspection_data(conn, data, parent_path); + +done: + g_free(parent_path); +} + dbus_bool_t dbus_connection_create_object_path(DBusConnection *connection, const char *path, void *user_data, DBusObjectPathUnregisterFunction function) @@ -286,13 +324,20 @@ dbus_bool_t dbus_connection_create_object_path(DBusConnection *connection, return FALSE; } + update_parent_data(connection, path); + return TRUE; } dbus_bool_t dbus_connection_destroy_object_path(DBusConnection *connection, const char *path) { - return dbus_connection_unregister_object_path(connection, path); + if (!dbus_connection_unregister_object_path(connection, path)) + return FALSE; + + update_parent_data(connection, path); + + return TRUE; } dbus_bool_t dbus_connection_get_object_user_data(DBusConnection *connection, @@ -335,7 +380,7 @@ dbus_bool_t dbus_connection_register_interface(DBusConnection *connection, data->interfaces = g_slist_append(data->interfaces, iface); - update_introspection_data(data, path); + update_introspection_data(connection, data, path); return TRUE; } @@ -359,7 +404,7 @@ dbus_bool_t dbus_connection_unregister_interface(DBusConnection *connection, g_free(iface->name); g_free(iface); - update_introspection_data(data, path); + update_introspection_data(connection, data, path); return TRUE; } -- cgit From 251f743f1501e99176c4071487b93567e94fefaa Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 4 May 2007 23:47:27 +0000 Subject: A more efficient strategy for introspection XML generation (only when it is requested and the object information has changed since the last generation) --- common/dbus-helper.c | 188 ++++++++++++++++++++++++++------------------------- 1 file changed, 97 insertions(+), 91 deletions(-) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index 639b6d3f..40cd3eac 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -61,93 +61,6 @@ DBusHandlerResult dbus_connection_send_and_unref(DBusConnection *connection, return DBUS_HANDLER_RESULT_HANDLED; } -static DBusHandlerResult introspect(DBusConnection *connection, - DBusMessage *message, struct generic_data *data) -{ - DBusMessage *reply; - - if (dbus_message_has_signature(message, - DBUS_TYPE_INVALID_AS_STRING) == FALSE) { - error("Unexpected signature to introspect call"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - - if (!data->introspect) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - reply = dbus_message_new_method_return(message); - if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - - dbus_message_append_args(reply, DBUS_TYPE_STRING, &data->introspect, - DBUS_TYPE_INVALID); - - return dbus_connection_send_and_unref(connection, reply); -} - -static void generic_unregister(DBusConnection *connection, void *user_data) -{ - struct generic_data *data = user_data; - - if (data->unregister_function) - data->unregister_function(connection, data->user_data); - - g_free(data->introspect); - g_free(data); -} - -static struct interface_data *find_interface(GSList *interfaces, - const char *name) -{ - GSList *list; - - for (list = interfaces; list; list = list->next) { - struct interface_data *iface = list->data; - if (!strcmp(name, iface->name)) - return iface; - } - - return NULL; -} - -static DBusHandlerResult generic_message(DBusConnection *connection, - DBusMessage *message, void *user_data) -{ - struct generic_data *data = user_data; - struct interface_data *iface; - DBusMethodVTable *current; - const char *interface; - - if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, - "Introspect") == TRUE) - return introspect(connection, message, data); - - interface = dbus_message_get_interface(message); - - iface = find_interface(data->interfaces, interface); - if (!iface) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - for (current = iface->methods; - current->name && current->message_function; current++) { - if (dbus_message_is_method_call(message, - iface->name, current->name) == FALSE) - continue; - - if (dbus_message_has_signature(message, - current->signature) == TRUE) - return current->message_function(connection, - message, data->user_data); - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static DBusObjectPathVTable generic_table = { - .unregister_function = generic_unregister, - .message_function = generic_message, -}; - static void print_arguments(GString *gstr, const char *sig, const char *direction) { int i; @@ -206,7 +119,9 @@ static void print_arguments(GString *gstr, const char *sig, const char *directio } } -static void update_introspection_data(DBusConnection *conn, struct generic_data *data, const char *path) +static void generate_introspection_xml(DBusConnection *conn, + struct generic_data *data, + const char *path) { GSList *list; GString *gstr; @@ -278,6 +193,94 @@ done: data->introspect = g_string_free(gstr, FALSE); } +static DBusHandlerResult introspect(DBusConnection *connection, + DBusMessage *message, struct generic_data *data) +{ + DBusMessage *reply; + + if (dbus_message_has_signature(message, + DBUS_TYPE_INVALID_AS_STRING) == FALSE) { + error("Unexpected signature to introspect call"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (!data->introspect) + generate_introspection_xml(connection, data, + dbus_message_get_path(message)); + + reply = dbus_message_new_method_return(message); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + dbus_message_append_args(reply, DBUS_TYPE_STRING, &data->introspect, + DBUS_TYPE_INVALID); + + return dbus_connection_send_and_unref(connection, reply); +} + +static void generic_unregister(DBusConnection *connection, void *user_data) +{ + struct generic_data *data = user_data; + + if (data->unregister_function) + data->unregister_function(connection, data->user_data); + + g_free(data->introspect); + g_free(data); +} + +static struct interface_data *find_interface(GSList *interfaces, + const char *name) +{ + GSList *list; + + for (list = interfaces; list; list = list->next) { + struct interface_data *iface = list->data; + if (!strcmp(name, iface->name)) + return iface; + } + + return NULL; +} + +static DBusHandlerResult generic_message(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + struct generic_data *data = user_data; + struct interface_data *iface; + DBusMethodVTable *current; + const char *interface; + + if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, + "Introspect") == TRUE) + return introspect(connection, message, data); + + interface = dbus_message_get_interface(message); + + iface = find_interface(data->interfaces, interface); + if (!iface) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + for (current = iface->methods; + current->name && current->message_function; current++) { + if (dbus_message_is_method_call(message, + iface->name, current->name) == FALSE) + continue; + + if (dbus_message_has_signature(message, + current->signature) == TRUE) + return current->message_function(connection, + message, data->user_data); + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusObjectPathVTable generic_table = { + .unregister_function = generic_unregister, + .message_function = generic_message, +}; + static void update_parent_data(DBusConnection *conn, const char *child_path) { struct generic_data *data; @@ -299,7 +302,8 @@ static void update_parent_data(DBusConnection *conn, const char *child_path) if (!data) goto done; - update_introspection_data(conn, data, parent_path); + g_free(data->introspect); + data->introspect = NULL; done: g_free(parent_path); @@ -380,7 +384,8 @@ dbus_bool_t dbus_connection_register_interface(DBusConnection *connection, data->interfaces = g_slist_append(data->interfaces, iface); - update_introspection_data(connection, data, path); + g_free(data->introspect); + data->introspect = NULL; return TRUE; } @@ -404,7 +409,8 @@ dbus_bool_t dbus_connection_unregister_interface(DBusConnection *connection, g_free(iface->name); g_free(iface); - update_introspection_data(connection, data, path); + g_free(data->introspect); + data->introspect = NULL; return TRUE; } -- cgit From 55466e2f43cf52b563954a9c2d1a722f6c646f7c Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 7 May 2007 10:52:10 +0000 Subject: Implement generic signal sending function which also checks for signal interface, name and paramter type conformance --- common/dbus-helper.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++ common/dbus-helper.h | 11 +++++++ 2 files changed, 101 insertions(+) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index 40cd3eac..fb7bce98 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -449,3 +449,93 @@ void dbus_message_iter_append_dict_entry(DBusMessageIter *dict, dbus_message_iter_close_container(dict, &entry); } + +dbus_bool_t dbus_connection_emit_signal_valist(DBusConnection *conn, + const char *path, + const char *interface, + const char *name, + int first, + va_list var_args) +{ + struct generic_data *data; + struct interface_data *iface; + DBusMessageIter iter; + DBusSignalVTable *sig_data; + DBusMessage *signal; + int type; + const char *args = NULL; + + if (dbus_connection_get_object_path_data(conn, path, + (void *) &data) == FALSE) { + error("dbus_connection_emit_signal: path %s isn't registered", path); + return FALSE; + } + + iface = find_interface(data->interfaces, interface); + + if (!iface) { + error("dbus_connection_emit_signal: %s does not implement %s", + path, interface); + return FALSE; + } + + for (sig_data = iface->signals; sig_data && sig_data->name; sig_data++) { + if (!strcmp(sig_data->name, name)) { + args = sig_data->signature; + break; + } + } + + if (!args) { + error("No signal named %s on interface %s", name, interface); + return FALSE; + } + + signal = dbus_message_new_signal(path, interface, name); + if (!signal) { + error("Unable to allocate new %s.%s signal", interface, name); + return FALSE; + } + + dbus_message_iter_init_append(signal, &iter); + + for (type = first; type != DBUS_TYPE_INVALID; + type = va_arg(var_args, int), args++) { + void *value; + + if (type != *args) { + error("Expected arg type '%c' but got '%c'", *args, type); + dbus_message_unref(signal); + return FALSE; + } + + value = va_arg(var_args, void *); + + if (!dbus_message_iter_append_basic(&iter, type, value)) { + error("Append property argument error (type %d)", type); + dbus_message_unref(signal); + return FALSE; + } + } + + dbus_connection_send(conn, signal, NULL); + dbus_message_unref(signal); + + return TRUE; +} + +dbus_bool_t dbus_connection_emit_signal(DBusConnection *conn, const char *path, + const char *interface, const char *name, + int first, ...) +{ + dbus_bool_t ret; + va_list var_args; + + va_start(var_args, first); + ret = dbus_connection_emit_signal_valist(conn, path, interface, name, + first, var_args); + va_end(var_args); + + return ret; +} + diff --git a/common/dbus-helper.h b/common/dbus-helper.h index 49db1c58..4dd9d155 100644 --- a/common/dbus-helper.h +++ b/common/dbus-helper.h @@ -20,6 +20,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ +#include #define DBUS_TYPE_STRING_ARRAY_AS_STRING (DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING) #define DBUS_TYPE_BYTE_ARRAY_AS_STRING (DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING) @@ -71,3 +72,13 @@ dbus_bool_t dbus_connection_unregister_interface(DBusConnection *connection, void dbus_message_iter_append_dict_entry(DBusMessageIter *dict, const char *key, int type, void *val); +dbus_bool_t dbus_connection_emit_signal(DBusConnection *conn, const char *path, + const char *interface, const char *name, + int first, ...); + +dbus_bool_t dbus_connection_emit_signal_valist(DBusConnection *conn, + const char *path, + const char *interface, + const char *name, + int first, + va_list var_args); -- cgit From d1c4d1d53a5f153d6c778debe1470fc1f32857e8 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 7 May 2007 14:46:57 +0000 Subject: Coding style updates and a few clarifications to error messages --- common/dbus-helper.c | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index fb7bce98..ba2db4d9 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -198,8 +198,7 @@ static DBusHandlerResult introspect(DBusConnection *connection, { DBusMessage *reply; - if (dbus_message_has_signature(message, - DBUS_TYPE_INVALID_AS_STRING) == FALSE) { + if (!dbus_message_has_signature(message, DBUS_TYPE_INVALID_AS_STRING)) { error("Unexpected signature to introspect call"); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } @@ -251,8 +250,9 @@ static DBusHandlerResult generic_message(DBusConnection *connection, DBusMethodVTable *current; const char *interface; - if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, - "Introspect") == TRUE) + if (dbus_message_is_method_call(message, + DBUS_INTERFACE_INTROSPECTABLE, + "Introspect")) return introspect(connection, message, data); interface = dbus_message_get_interface(message); @@ -263,12 +263,11 @@ static DBusHandlerResult generic_message(DBusConnection *connection, for (current = iface->methods; current->name && current->message_function; current++) { - if (dbus_message_is_method_call(message, - iface->name, current->name) == FALSE) + if (!dbus_message_is_method_call(message, iface->name, + current->name)) continue; - if (dbus_message_has_signature(message, - current->signature) == TRUE) + if (dbus_message_has_signature(message, current->signature)) return current->message_function(connection, message, data->user_data); } @@ -296,7 +295,7 @@ static void update_parent_data(DBusConnection *conn, const char *child_path) goto done; if (!dbus_connection_get_object_path_data(conn, parent_path, - (void *) &data)) + (void *) &data)) goto done; if (!data) @@ -322,8 +321,8 @@ dbus_bool_t dbus_connection_create_object_path(DBusConnection *connection, data->introspect = g_strdup(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE ""); - if (dbus_connection_register_object_path(connection, path, - &generic_table, data) == FALSE) { + if (!dbus_connection_register_object_path(connection, path, + &generic_table, data)) { g_free(data); return FALSE; } @@ -350,8 +349,8 @@ dbus_bool_t dbus_connection_get_object_user_data(DBusConnection *connection, { struct generic_data *data; - if (dbus_connection_get_object_path_data(connection, path, - (void *) &data) == FALSE) + if (!dbus_connection_get_object_path_data(connection, path, + (void *) &data)) return FALSE; *data_p = data->user_data; @@ -368,8 +367,8 @@ dbus_bool_t dbus_connection_register_interface(DBusConnection *connection, struct generic_data *data; struct interface_data *iface; - if (dbus_connection_get_object_path_data(connection, path, - (void *) &data) == FALSE) + if (!dbus_connection_get_object_path_data(connection, path, + (void *) &data)) return FALSE; if (find_interface(data->interfaces, name)) @@ -396,8 +395,8 @@ dbus_bool_t dbus_connection_unregister_interface(DBusConnection *connection, struct generic_data *data; struct interface_data *iface; - if (dbus_connection_get_object_path_data(connection, path, - (void *) &data) == FALSE) + if (!dbus_connection_get_object_path_data(connection, path, + (void *) &data)) return FALSE; iface = find_interface(data->interfaces, name); @@ -465,9 +464,9 @@ dbus_bool_t dbus_connection_emit_signal_valist(DBusConnection *conn, int type; const char *args = NULL; - if (dbus_connection_get_object_path_data(conn, path, - (void *) &data) == FALSE) { - error("dbus_connection_emit_signal: path %s isn't registered", path); + if (!dbus_connection_get_object_path_data(conn, path, (void *) &data)) { + error("dbus_connection_emit_signal: path %s isn't registered", + path); return FALSE; } @@ -504,7 +503,8 @@ dbus_bool_t dbus_connection_emit_signal_valist(DBusConnection *conn, void *value; if (type != *args) { - error("Expected arg type '%c' but got '%c'", *args, type); + error("%s.%s: expected arg type '%c' but got '%c'", + interface, name, *args, type); dbus_message_unref(signal); return FALSE; } @@ -512,7 +512,8 @@ dbus_bool_t dbus_connection_emit_signal_valist(DBusConnection *conn, value = va_arg(var_args, void *); if (!dbus_message_iter_append_basic(&iter, type, value)) { - error("Append property argument error (type %d)", type); + error("%s.%s: appending argument of type '%c' failed", + interface, name, type); dbus_message_unref(signal); return FALSE; } -- cgit From 0bd3de9823bac2481837c0e17b36b60d4b329224 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 9 May 2007 09:06:10 +0000 Subject: Add debug print to get better visibility of what methods are being called --- common/dbus-helper.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index ba2db4d9..4d15f418 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -267,9 +267,12 @@ static DBusHandlerResult generic_message(DBusConnection *connection, current->name)) continue; - if (dbus_message_has_signature(message, current->signature)) + if (dbus_message_has_signature(message, current->signature)) { + debug("%s: %s.%s()", dbus_message_get_path(message), + iface->name, current->name); return current->message_function(connection, message, data->user_data); + } } return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -- cgit From a4bf1139272498ac3058959b60e19b967efc1b73 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 17 May 2007 16:21:31 +0000 Subject: Fix some ppoll issue --- common/ppoll.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'common') diff --git a/common/ppoll.h b/common/ppoll.h index 6d84a2e8..d9096901 100644 --- a/common/ppoll.h +++ b/common/ppoll.h @@ -1,4 +1,10 @@ -static inline int ppoll(struct pollfd *fds, nfds_t nfds, +#ifdef ppoll +#undef ppoll +#endif + +#define ppoll compat_ppoll + +static inline int compat_ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout, const sigset_t *sigmask) { return poll(fds, nfds, timeout ? timeout->tv_sec * 1000 : 500); -- cgit From d87420bcd319c66010fc36061ea0c354ef117d1d Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 18 May 2007 14:49:06 +0000 Subject: dbus-helper: added int16 support to append dict entry --- common/dbus-helper.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index 4d15f418..673ec2b5 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -432,6 +432,9 @@ void dbus_message_iter_append_dict_entry(DBusMessageIter *dict, case DBUS_TYPE_STRING: sig = DBUS_TYPE_STRING_AS_STRING; break; + case DBUS_TYPE_INT16: + sig = DBUS_TYPE_INT16_AS_STRING; + break; case DBUS_TYPE_UINT32: sig = DBUS_TYPE_UINT32_AS_STRING; break; -- cgit From cb5898ff72875b9c24d7fc44cddb005f4495dff3 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 21 May 2007 15:13:50 +0000 Subject: Fix SDP pattern extraction for XML --- common/sdp-expat.c | 3 ++- common/sdp-glib.c | 6 +++--- common/sdp-xml.c | 31 ++++++++++++++++++++----------- common/sdp-xml.h | 5 +++-- 4 files changed, 28 insertions(+), 17 deletions(-) (limited to 'common') diff --git a/common/sdp-expat.c b/common/sdp-expat.c index b591bbcc..b8136528 100644 --- a/common/sdp-expat.c +++ b/common/sdp-expat.c @@ -116,7 +116,8 @@ static void convert_xml_to_sdp_start(void *data, const char *el, const char **at } } - context->stack_head->data = sdp_xml_parse_datatype(el, context->stack_head); + context->stack_head->data = sdp_xml_parse_datatype(el, + context->stack_head, context->sdprec); /* Could not parse an entry */ if (context->stack_head->data == NULL) diff --git a/common/sdp-glib.c b/common/sdp-glib.c index a24464ce..f280d0d1 100644 --- a/common/sdp-glib.c +++ b/common/sdp-glib.c @@ -115,8 +115,8 @@ static void element_start(GMarkupParseContext *context, } } - ctx_data->stack_head->data = - sdp_xml_parse_datatype(element_name, ctx_data->stack_head); + ctx_data->stack_head->data = sdp_xml_parse_datatype(element_name, + ctx_data->stack_head, ctx_data->record); if (ctx_data->stack_head->data == NULL) error("Can't parse element %s", element_name); @@ -213,7 +213,7 @@ sdp_record_t *sdp_xml_parse_record(const char *data, int size) record = sdp_record_alloc(); if (!record) { - sdp_record_free(record); + free(ctx_data); return NULL; } diff --git a/common/sdp-xml.c b/common/sdp-xml.c index db07f03b..12457ea6 100644 --- a/common/sdp-xml.c +++ b/common/sdp-xml.c @@ -440,17 +440,20 @@ static sdp_data_t *sdp_xml_parse_uuid128(const char *data) return sdp_data_alloc(SDP_UUID128, &val); } -sdp_data_t *sdp_xml_parse_uuid(const char *data) +sdp_data_t *sdp_xml_parse_uuid(const char *data, sdp_record_t *record) { - int len; + sdp_data_t *uuid; char *endptr; uint32_t val; uint16_t val2; + int len; len = strlen(data); - if (len == 36) - return sdp_xml_parse_uuid128(data); + if (len == 36) { + uuid = sdp_xml_parse_uuid128(data); + goto result; + } val = strtoll(data, &endptr, 16); @@ -458,15 +461,20 @@ sdp_data_t *sdp_xml_parse_uuid(const char *data) if (*endptr != '\0') return NULL; - if (val > USHRT_MAX) - return sdp_data_alloc(SDP_UUID32, &val); + if (val > USHRT_MAX) { + uuid = sdp_data_alloc(SDP_UUID32, &val); + goto result; + } val2 = val; - return sdp_data_alloc(SDP_UUID16, &val2); + uuid = sdp_data_alloc(SDP_UUID16, &val2); - /* Should never get here */ - return NULL; +result: + if (record && uuid) + sdp_pattern_add_uuid(record, &uuid->val.uuid); + + return uuid; } sdp_data_t *sdp_xml_parse_int(const char * data, uint8_t dtd) @@ -759,7 +767,8 @@ struct sdp_xml_data *sdp_xml_data_expand(struct sdp_xml_data *elem) return elem; } -sdp_data_t *sdp_xml_parse_datatype(const char *el, struct sdp_xml_data *elem) +sdp_data_t *sdp_xml_parse_datatype(const char *el, struct sdp_xml_data *elem, + sdp_record_t *record) { const char *data = elem->text; @@ -786,7 +795,7 @@ sdp_data_t *sdp_xml_parse_datatype(const char *el, struct sdp_xml_data *elem) else if (!strcmp(el, "int128")) return sdp_xml_parse_int(data, SDP_INT128); else if (!strcmp(el, "uuid")) - return sdp_xml_parse_uuid(data); + return sdp_xml_parse_uuid(data, record); else if (!strcmp(el, "url")) return sdp_xml_parse_url(data); else if (!strcmp(el, "text")) diff --git a/common/sdp-xml.h b/common/sdp-xml.h index 2d4d7d79..1ab6bb19 100644 --- a/common/sdp-xml.h +++ b/common/sdp-xml.h @@ -37,7 +37,7 @@ 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_url(const char *data); 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_uuid(const char *data, sdp_record_t *record); struct sdp_xml_data { char *text; /* Pointer to the current buffer */ @@ -53,7 +53,8 @@ struct sdp_xml_data *sdp_xml_data_alloc(); void sdp_xml_data_free(struct sdp_xml_data *elem); struct sdp_xml_data *sdp_xml_data_expand(struct sdp_xml_data *elem); -sdp_data_t *sdp_xml_parse_datatype(const char *el, struct sdp_xml_data *elem); +sdp_data_t *sdp_xml_parse_datatype(const char *el, struct sdp_xml_data *elem, + sdp_record_t *record); sdp_record_t *sdp_xml_parse_record(const char *data, int size); -- cgit From 8e0d20842a9601e45cd191f1d190e18ebee2abb1 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 22 May 2007 05:53:49 +0000 Subject: Use same decoder for text and URL strings --- common/sdp-xml.c | 91 +++++++++++++++++++++++++------------------------------- 1 file changed, 40 insertions(+), 51 deletions(-) (limited to 'common') diff --git a/common/sdp-xml.c b/common/sdp-xml.c index 12457ea6..5aeca405 100644 --- a/common/sdp-xml.c +++ b/common/sdp-xml.c @@ -442,7 +442,7 @@ static sdp_data_t *sdp_xml_parse_uuid128(const char *data) sdp_data_t *sdp_xml_parse_uuid(const char *data, sdp_record_t *record) { - sdp_data_t *uuid; + sdp_data_t *ret; char *endptr; uint32_t val; uint16_t val2; @@ -451,7 +451,7 @@ sdp_data_t *sdp_xml_parse_uuid(const char *data, sdp_record_t *record) len = strlen(data); if (len == 36) { - uuid = sdp_xml_parse_uuid128(data); + ret = sdp_xml_parse_uuid128(data); goto result; } @@ -462,19 +462,19 @@ sdp_data_t *sdp_xml_parse_uuid(const char *data, sdp_record_t *record) return NULL; if (val > USHRT_MAX) { - uuid = sdp_data_alloc(SDP_UUID32, &val); + ret = sdp_data_alloc(SDP_UUID32, &val); goto result; } val2 = val; - uuid = sdp_data_alloc(SDP_UUID16, &val2); + ret = sdp_data_alloc(SDP_UUID16, &val2); result: - if (record && uuid) - sdp_pattern_add_uuid(record, &uuid->val.uuid); + if (record && ret) + sdp_pattern_add_uuid(record, &ret->val.uuid); - return uuid; + return ret; } sdp_data_t *sdp_xml_parse_int(const char * data, uint8_t dtd) @@ -490,14 +490,14 @@ sdp_data_t *sdp_xml_parse_int(const char * data, uint8_t dtd) if (!strcmp("true", data)) { val = 1; } - + else if (!strcmp("false", data)) { val = 0; } else { return NULL; } - + ret = sdp_data_alloc(dtd, &val); break; } @@ -506,9 +506,9 @@ sdp_data_t *sdp_xml_parse_int(const char * data, uint8_t dtd) { int8_t val = strtoul(data, &endptr, 0); - /* Failed to parse */ + /* Failed to parse */ if ((endptr != data) && (*endptr != '\0')) - return NULL; + return NULL; ret = sdp_data_alloc(dtd, &val); break; @@ -521,7 +521,7 @@ sdp_data_t *sdp_xml_parse_int(const char * data, uint8_t dtd) /* Failed to parse */ if ((endptr != data) && (*endptr != '\0')) return NULL; - + ret = sdp_data_alloc(dtd, &val); break; } @@ -533,7 +533,7 @@ sdp_data_t *sdp_xml_parse_int(const char * data, uint8_t dtd) /* Failed to parse */ if ((endptr != data) && (*endptr != '\0')) return NULL; - + ret = sdp_data_alloc(dtd, &val); break; } @@ -542,9 +542,9 @@ sdp_data_t *sdp_xml_parse_int(const char * data, uint8_t dtd) { uint16_t val = strtoul(data, &endptr, 0); - /* Failed to parse */ + /* Failed to parse */ if ((endptr != data) && (*endptr != '\0')) - return NULL; + return NULL; ret = sdp_data_alloc(dtd, &val); break; @@ -554,10 +554,10 @@ sdp_data_t *sdp_xml_parse_int(const char * data, uint8_t dtd) { int32_t val = strtoul(data, &endptr, 0); - /* Failed to parse */ + /* Failed to parse */ if ((endptr != data) && (*endptr != '\0')) - return NULL; - + return NULL; + ret = sdp_data_alloc(dtd, &val); break; } @@ -566,9 +566,9 @@ sdp_data_t *sdp_xml_parse_int(const char * data, uint8_t dtd) { uint32_t val = strtoul(data, &endptr, 0); - /* Failed to parse */ + /* Failed to parse */ if ((endptr != data) && (*endptr != '\0')) - return NULL; + return NULL; ret = sdp_data_alloc(dtd, &val); break; @@ -578,10 +578,10 @@ sdp_data_t *sdp_xml_parse_int(const char * data, uint8_t dtd) { int64_t val = strtoull(data, &endptr, 0); - /* Failed to parse */ + /* Failed to parse */ if ((endptr != data) && (*endptr != '\0')) - return NULL; - + return NULL; + ret = sdp_data_alloc(dtd, &val); break; } @@ -590,9 +590,9 @@ sdp_data_t *sdp_xml_parse_int(const char * data, uint8_t dtd) { uint64_t val = strtoull(data, &endptr, 0); - /* Failed to parse */ + /* Failed to parse */ if ((endptr != data) && (*endptr != '\0')) - return NULL; + return NULL; ret = sdp_data_alloc(dtd, &val); break; @@ -623,22 +623,7 @@ sdp_data_t *sdp_xml_parse_int(const char * data, uint8_t dtd) return ret; } -static 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 char *sdp_xml_parse_text_decode(const char *data, char encoding, uint32_t *length) +static char *sdp_xml_parse_string_decode(const char *data, char encoding, uint32_t *length) { int len = strlen(data); char *text; @@ -672,23 +657,27 @@ static char *sdp_xml_parse_text_decode(const char *data, char encoding, uint32_t return text; } -#if 0 -static 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) { - char *text; + uint8_t dtd = SDP_URL_STR8; + char *url; uint32_t length; sdp_data_t *ret; - text = sdp_xml_parse_text_decode(data, encoding, &length); - ret = sdp_data_alloc_with_length(dtd, text, length); + url = sdp_xml_parse_string_decode(data, + SDP_XML_ENCODING_NORMAL, &length); - debug("Unit size %d length %d: -->%s<--\n", ret->unitSize, length, text); + if (length > UCHAR_MAX) + dtd = SDP_URL_STR16; - free(text); + ret = sdp_data_alloc_with_length(dtd, url, length); + + debug("URL size %d length %d: -->%s<--", ret->unitSize, length, url); + + free(url); return ret; } -#endif sdp_data_t *sdp_xml_parse_text(const char *data, char encoding) { @@ -697,14 +686,14 @@ sdp_data_t *sdp_xml_parse_text(const char *data, char encoding) uint32_t length; sdp_data_t *ret; - text = sdp_xml_parse_text_decode(data, encoding, &length); + text = sdp_xml_parse_string_decode(data, encoding, &length); if (length > UCHAR_MAX) dtd = SDP_TEXT_STR16; ret = sdp_data_alloc_with_length(dtd, text, length); - debug("Unit size %d length %d: -->%s<--\n", ret->unitSize, length, text); + debug("Text size %d length %d: -->%s<--", ret->unitSize, length, text); free(text); -- cgit From 9dca4cf2d579b58c62d0ce98102250a6e0759dae Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 19 Jun 2007 12:59:59 +0000 Subject: dbus-helper: added array type support for dbus_connection_emit_signal function --- common/dbus-helper.c | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index 673ec2b5..e80d49cd 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -464,11 +464,10 @@ dbus_bool_t dbus_connection_emit_signal_valist(DBusConnection *conn, { struct generic_data *data; struct interface_data *iface; - DBusMessageIter iter; DBusSignalVTable *sig_data; DBusMessage *signal; - int type; - const char *args = NULL; + dbus_bool_t ret; + const char *signature, *args = NULL; if (!dbus_connection_get_object_path_data(conn, path, (void *) &data)) { error("dbus_connection_emit_signal: path %s isn't registered", @@ -502,33 +501,23 @@ dbus_bool_t dbus_connection_emit_signal_valist(DBusConnection *conn, return FALSE; } - dbus_message_iter_init_append(signal, &iter); - - for (type = first; type != DBUS_TYPE_INVALID; - type = va_arg(var_args, int), args++) { - void *value; + ret = dbus_message_append_args_valist(signal, first, var_args); + if (!ret) + goto fail; - if (type != *args) { - error("%s.%s: expected arg type '%c' but got '%c'", - interface, name, *args, type); - dbus_message_unref(signal); - return FALSE; - } - - value = va_arg(var_args, void *); - - if (!dbus_message_iter_append_basic(&iter, type, value)) { - error("%s.%s: appending argument of type '%c' failed", - interface, name, type); - dbus_message_unref(signal); - return FALSE; - } + signature = dbus_message_get_signature(signal); + if (strcmp(args, signature) != 0) { + error("%s.%s: expected signature'%s' but got '%s'", + interface, name, args, signature); + ret = FALSE; + goto fail; } - dbus_connection_send(conn, signal, NULL); + ret = dbus_connection_send(conn, signal, NULL); +fail: dbus_message_unref(signal); - return TRUE; + return ret; } dbus_bool_t dbus_connection_emit_signal(DBusConnection *conn, const char *path, -- cgit From fbba4be5b162fdffe8e12e3b1e0fa11629436600 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 19 Jun 2007 17:44:09 +0000 Subject: More work on private D-Bus server --- common/dbus.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- common/dbus.h | 5 ++ 2 files changed, 138 insertions(+), 12 deletions(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index db50fcc9..ef3188d9 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -61,6 +61,12 @@ struct watch_info { GIOChannel *io; DBusConnection *conn; }; + +struct server_info { + guint watch_id; + GIOChannel *io; + DBusServer *server; +}; #endif struct disconnect_data { @@ -371,6 +377,75 @@ static DBusHandlerResult disconnect_filter(DBusConnection *conn, } #ifndef HAVE_DBUS_GLIB +static dbus_int32_t server_slot = -1; + +static gboolean server_func(GIOChannel *chan, GIOCondition cond, gpointer data) +{ + DBusWatch *watch = data; + int flags = 0; + + if (cond & G_IO_IN) flags |= DBUS_WATCH_READABLE; + if (cond & G_IO_OUT) flags |= DBUS_WATCH_WRITABLE; + if (cond & G_IO_HUP) flags |= DBUS_WATCH_HANGUP; + if (cond & G_IO_ERR) flags |= DBUS_WATCH_ERROR; + + dbus_watch_handle(watch, flags); + + return TRUE; +} + +static dbus_bool_t add_server(DBusWatch *watch, void *data) +{ + GIOCondition cond = G_IO_HUP | G_IO_ERR; + DBusServer *server = data; + struct server_info *info; + int fd, flags; + + if (!dbus_watch_get_enabled(watch)) + return TRUE; + + info = g_new(struct server_info, 1); + + fd = dbus_watch_get_fd(watch); + info->io = g_io_channel_unix_new(fd); + info->server = dbus_server_ref(server); + + dbus_watch_set_data(watch, info, NULL); + + flags = dbus_watch_get_flags(watch); + + if (flags & DBUS_WATCH_READABLE) cond |= G_IO_IN; + if (flags & DBUS_WATCH_WRITABLE) cond |= G_IO_OUT; + + info->watch_id = g_io_add_watch(info->io, cond, server_func, watch); + + return TRUE; +} + +static void remove_server(DBusWatch *watch, void *data) +{ + struct server_info *info = dbus_watch_get_data(watch); + + dbus_watch_set_data(watch, NULL, NULL); + + if (info) { + g_source_remove(info->watch_id); + g_io_channel_unref(info->io); + dbus_server_unref(info->server); + g_free(info); + } +} + +static void server_toggled(DBusWatch *watch, void *data) +{ + /* Because we just exit on OOM, enable/disable is + * no different from add/remove */ + if (dbus_watch_get_enabled(watch)) + add_server(watch, data); + else + remove_server(watch, data); +} + static gboolean message_dispatch_cb(void *data) { DBusConnection *connection = data; @@ -520,23 +595,27 @@ static void dispatch_status_cb(DBusConnection *conn, } #endif -DBusConnection *init_dbus(const char *name, - void (*disconnect_cb)(void *), void *user_data) +void setup_dbus_server_with_main_loop(DBusServer *server) { - struct disconnect_data *dc_data; - DBusConnection *conn; - DBusError err; +#ifdef HAVE_DBUS_GLIB + dbus_server_setup_with_g_main(server, NULL); +#else + dbus_server_allocate_data_slot(&server_slot); + if (server_slot < 0) + return; - dbus_error_init(&err); + dbus_server_set_data(server, server_slot, server, NULL); - conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); + dbus_server_set_watch_functions(server, add_server, remove_server, + server_toggled, server, NULL); - if (dbus_error_is_set(&err)) { - error("Can't connect to system message bus: %s", err.message); - dbus_error_free(&err); - return NULL; - } + dbus_server_set_timeout_functions(server, add_timeout, remove_timeout, + timeout_toggled, server, NULL); +#endif +} +void setup_dbus_with_main_loop(DBusConnection *conn) +{ #ifdef HAVE_DBUS_GLIB dbus_connection_setup_with_g_main(conn, NULL); #else @@ -549,6 +628,26 @@ DBusConnection *init_dbus(const char *name, dbus_connection_set_dispatch_status_function(conn, dispatch_status_cb, conn, NULL); #endif +} + +DBusConnection *init_dbus(const char *name, + void (*disconnect_cb)(void *), void *user_data) +{ + struct disconnect_data *dc_data; + DBusConnection *conn; + DBusError err; + + dbus_error_init(&err); + + conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); + + if (dbus_error_is_set(&err)) { + error("Can't connect to system message bus: %s", err.message); + dbus_error_free(&err); + return NULL; + } + + setup_dbus_with_main_loop(conn); if (name) { dbus_error_init(&err); @@ -589,6 +688,28 @@ DBusConnection *init_dbus(const char *name, return conn; } +DBusConnection *init_dbus_direct(const char *address) +{ + DBusConnection *conn; + DBusError err; + + dbus_error_init(&err); + + conn = dbus_connection_open(address, &err); + + if (dbus_error_is_set(&err)) { + error("Can't connect to message server: %s", err.message); + dbus_error_free(&err); + return NULL; + } + + setup_dbus_with_main_loop(conn); + + dbus_connection_set_exit_on_disconnect(conn, FALSE); + + return conn; +} + DBusConnection *dbus_bus_system_setup_with_main_loop(const char *name, void (*disconnect_cb)(void *), void *user_data) { diff --git a/common/dbus.h b/common/dbus.h index 26ccb6e0..23448cf7 100644 --- a/common/dbus.h +++ b/common/dbus.h @@ -26,9 +26,14 @@ #include +void setup_dbus_server_with_main_loop(DBusServer *server); +void setup_dbus_with_main_loop(DBusConnection *conn); + DBusConnection *init_dbus(const char *name, void (*disconnect_cb)(void *), void *user_data); +DBusConnection *init_dbus_direct(const char *address); + DBusConnection *dbus_bus_system_setup_with_main_loop(const char *name, void (*disconnect_cb)(void *), void *user_data); -- cgit From 5fcad6abebf97c6a06d9eb5c206d5c10bcf14eb7 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 21 Jun 2007 21:52:51 +0000 Subject: dbus-helper: avoid seg fault when the object path data is not available(unregistered) --- common/dbus-helper.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index e80d49cd..488b1d2f 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -285,7 +285,7 @@ static DBusObjectPathVTable generic_table = { static void update_parent_data(DBusConnection *conn, const char *child_path) { - struct generic_data *data; + struct generic_data *data = NULL; char *parent_path, *slash; parent_path = g_strdup(child_path); @@ -350,10 +350,10 @@ dbus_bool_t dbus_connection_get_object_user_data(DBusConnection *connection, const char *path, void **data_p) { - struct generic_data *data; + struct generic_data *data = NULL; if (!dbus_connection_get_object_path_data(connection, path, - (void *) &data)) + (void *) &data) || !data) return FALSE; *data_p = data->user_data; @@ -367,11 +367,11 @@ dbus_bool_t dbus_connection_register_interface(DBusConnection *connection, DBusSignalVTable *signals, DBusPropertyVTable *properties) { - struct generic_data *data; + struct generic_data *data = NULL; struct interface_data *iface; if (!dbus_connection_get_object_path_data(connection, path, - (void *) &data)) + (void *) &data) || !data) return FALSE; if (find_interface(data->interfaces, name)) @@ -395,11 +395,11 @@ dbus_bool_t dbus_connection_register_interface(DBusConnection *connection, dbus_bool_t dbus_connection_unregister_interface(DBusConnection *connection, const char *path, const char *name) { - struct generic_data *data; + struct generic_data *data = NULL; struct interface_data *iface; if (!dbus_connection_get_object_path_data(connection, path, - (void *) &data)) + (void *) &data) || !data) return FALSE; iface = find_interface(data->interfaces, name); @@ -462,14 +462,15 @@ dbus_bool_t dbus_connection_emit_signal_valist(DBusConnection *conn, int first, va_list var_args) { - struct generic_data *data; + struct generic_data *data = NULL; struct interface_data *iface; DBusSignalVTable *sig_data; DBusMessage *signal; dbus_bool_t ret; const char *signature, *args = NULL; - if (!dbus_connection_get_object_path_data(conn, path, (void *) &data)) { + if (!dbus_connection_get_object_path_data(conn, path, + (void *) &data) || !data) { error("dbus_connection_emit_signal: path %s isn't registered", path); return FALSE; -- cgit From 1a2e7943da42619730e442d1ff6ab08b9c2c621d Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 22 Jun 2007 01:34:51 +0000 Subject: Fix handling of name_listeners without a sender --- common/dbus.c | 20 ++++++++++++++++++-- common/dbus.h | 1 + 2 files changed, 19 insertions(+), 2 deletions(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index ef3188d9..17f340b6 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -88,7 +88,8 @@ static struct name_data *name_data_find(const char *name) { GSList *current; - for (current = name_listeners; current != NULL; current = current->next) { + for (current = name_listeners; + current != NULL; current = current->next) { struct name_data *data = current->data; if (strcmp(name, data->name) == 0) return data; @@ -98,7 +99,7 @@ static struct name_data *name_data_find(const char *name) } static struct name_callback *name_callback_find(GSList *callbacks, - name_cb_t func, void *user_data) + name_cb_t func, void *user_data) { GSList *current; @@ -228,6 +229,9 @@ int name_listener_add(DBusConnection *connection, const char *name, name_listener_initialized = 1; } + if (!name) + return -1; + first = name_data_add(name, func, user_data); /* The filter is already added if this is not the first callback * registration for the name */ @@ -262,6 +266,9 @@ int name_listener_remove(DBusConnection *connection, const char *name, DBusError err; char match_string[128]; + if (!name) + return -1; + debug("name_listener_remove(%s)", name); data = name_data_find(name); @@ -302,6 +309,11 @@ int name_listener_remove(DBusConnection *connection, const char *name, return 0; } +int name_listener_indicate_disconnect(DBusConnection *connection) +{ + return 0; +} + dbus_bool_t dbus_bus_get_unix_process_id(DBusConnection *conn, const char *name, unsigned long *pid) { @@ -598,6 +610,8 @@ static void dispatch_status_cb(DBusConnection *conn, void setup_dbus_server_with_main_loop(DBusServer *server) { #ifdef HAVE_DBUS_GLIB + debug("Using D-Bus GLib server setup"); + dbus_server_setup_with_g_main(server, NULL); #else dbus_server_allocate_data_slot(&server_slot); @@ -617,6 +631,8 @@ void setup_dbus_server_with_main_loop(DBusServer *server) void setup_dbus_with_main_loop(DBusConnection *conn) { #ifdef HAVE_DBUS_GLIB + debug("Using D-Bus GLib connection setup"); + dbus_connection_setup_with_g_main(conn, NULL); #else dbus_connection_set_watch_functions(conn, add_watch, remove_watch, diff --git a/common/dbus.h b/common/dbus.h index 23448cf7..e91fd3cf 100644 --- a/common/dbus.h +++ b/common/dbus.h @@ -46,6 +46,7 @@ int name_listener_add(DBusConnection *connection, const char *name, name_cb_t func, void *user_data); int name_listener_remove(DBusConnection *connection, const char *name, name_cb_t func, void *user_data); +int name_listener_indicate_disconnect(DBusConnection *connection); dbus_bool_t dbus_bus_get_unix_process_id(DBusConnection *conn, const char *name, unsigned long *pid); -- cgit From 6d581831d9ec16a9f32b436817f775a8a33cbb69 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 22 Jun 2007 03:21:08 +0000 Subject: Track name listeners also via connection --- common/dbus.c | 123 ++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 81 insertions(+), 42 deletions(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index 17f340b6..1b5f7db8 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -80,19 +80,27 @@ struct name_callback { }; struct name_data { + DBusConnection *connection; char *name; GSList *callbacks; }; -static struct name_data *name_data_find(const char *name) +static struct name_data *name_data_find(DBusConnection *connection, + const char *name) { GSList *current; for (current = name_listeners; current != NULL; current = current->next) { struct name_data *data = current->data; - if (strcmp(name, data->name) == 0) - return data; + + if (name == NULL && data->name == NULL) { + if (connection == data->connection) + return data; + } else { + if (strcmp(name, data->name) == 0) + return data; + } } return NULL; @@ -112,6 +120,22 @@ static struct name_callback *name_callback_find(GSList *callbacks, return NULL; } +static void name_data_call_and_free(struct name_data *data) +{ + GSList *l; + + for (l = data->callbacks; l != NULL; l = l->next) { + struct name_callback *cb = l->data; + if (cb->func) + cb->func(data->name, cb->user_data); + g_free(cb); + } + + g_slist_free(data->callbacks); + g_free(data->name); + g_free(data); +} + static void name_data_free(struct name_data *data) { GSList *l; @@ -124,7 +148,8 @@ static void name_data_free(struct name_data *data) g_free(data); } -static int name_data_add(const char *name, name_cb_t func, void *user_data) +static int name_data_add(DBusConnection *connection, + const char *name, name_cb_t func, void *user_data) { int first = 1; struct name_data *data = NULL; @@ -135,7 +160,7 @@ static int name_data_add(const char *name, name_cb_t func, void *user_data) cb->func = func; cb->user_data = user_data; - data = name_data_find(name); + data = name_data_find(connection, name); if (data) { first = 0; goto done; @@ -143,6 +168,7 @@ static int name_data_add(const char *name, name_cb_t func, void *user_data) data = g_new0(struct name_data, 1); + data->connection = connection; data->name = g_strdup(name); name_listeners = g_slist_append(name_listeners, data); @@ -152,12 +178,13 @@ done: return first; } -static void name_data_remove(const char *name, name_cb_t func, void *user_data) +static void name_data_remove(DBusConnection *connection, + const char *name, name_cb_t func, void *user_data) { struct name_data *data; struct name_callback *cb = NULL; - data = name_data_find(name); + data = name_data_find(connection, name); if (!data) return; @@ -197,7 +224,7 @@ static DBusHandlerResult name_exit_filter(DBusConnection *connection, if (*new != '\0') return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - data = name_data_find(name); + data = name_data_find(connection, name); if (!data) { error("Got NameOwnerChanged signal for %s which has no listeners", name); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -222,56 +249,51 @@ int name_listener_add(DBusConnection *connection, const char *name, int first; if (!name_listener_initialized) { - if (!dbus_connection_add_filter(connection, name_exit_filter, NULL, NULL)) { + if (!dbus_connection_add_filter(connection, + name_exit_filter, NULL, NULL)) { error("dbus_connection_add_filter() failed"); return -1; } name_listener_initialized = 1; } - if (!name) - return -1; - - first = name_data_add(name, func, user_data); + first = name_data_add(connection, name, func, user_data); /* The filter is already added if this is not the first callback * registration for the name */ if (!first) return 0; - debug("name_listener_add(%s)", name); + if (name) { + debug("name_listener_add(%s)", name); - snprintf(match_string, sizeof(match_string), - "interface=%s,member=NameOwnerChanged,arg0=%s", - DBUS_INTERFACE_DBUS, name); + snprintf(match_string, sizeof(match_string), + "interface=%s,member=NameOwnerChanged,arg0=%s", + DBUS_INTERFACE_DBUS, name); - dbus_error_init(&err); - dbus_bus_add_match(connection, match_string, &err); + dbus_error_init(&err); + dbus_bus_add_match(connection, match_string, &err); - if (dbus_error_is_set(&err)) { - error("Adding match rule \"%s\" failed: %s", match_string, - err.message); - dbus_error_free(&err); - name_data_remove(name, func, user_data); - return -1; + if (dbus_error_is_set(&err)) { + error("Adding match rule \"%s\" failed: %s", + match_string, err.message); + dbus_error_free(&err); + name_data_remove(connection, name, func, user_data); + return -1; + } } return 0; } int name_listener_remove(DBusConnection *connection, const char *name, - name_cb_t func, void *user_data) + name_cb_t func, void *user_data) { struct name_data *data; struct name_callback *cb; DBusError err; char match_string[128]; - if (!name) - return -1; - - debug("name_listener_remove(%s)", name); - - data = name_data_find(name); + data = name_data_find(connection, name); if (!data) { error("remove_name_listener: no listener for %s", name); return -1; @@ -290,27 +312,44 @@ int name_listener_remove(DBusConnection *connection, const char *name, if (data->callbacks) return 0; - snprintf(match_string, sizeof(match_string), - "interface=%s,member=NameOwnerChanged,arg0=%s", - DBUS_INTERFACE_DBUS, name); + if (name) { + debug("name_listener_remove(%s)", name); - dbus_error_init(&err); - dbus_bus_remove_match(connection, match_string, &err); + snprintf(match_string, sizeof(match_string), + "interface=%s,member=NameOwnerChanged,arg0=%s", + DBUS_INTERFACE_DBUS, name); - if (dbus_error_is_set(&err)) { - error("Removing owner match rule for %s failed: %s", + dbus_error_init(&err); + + dbus_bus_remove_match(connection, match_string, &err); + + if (dbus_error_is_set(&err)) { + error("Removing owner match rule for %s failed: %s", name, err.message); - dbus_error_free(&err); - return -1; + dbus_error_free(&err); + return -1; + } } - name_data_remove(name, func, user_data); + name_data_remove(connection, name, func, user_data); return 0; } int name_listener_indicate_disconnect(DBusConnection *connection) { + struct name_data *data; + + data = name_data_find(connection, NULL); + if (!data) { + error("name_listener_indicate_disconnect: no listener found"); + return -1; + } + + debug("name_listener_indicate_disconnect"); + + name_data_call_and_free(data); + return 0; } -- cgit From fb2c49cfc95ee82f77df6b8242199599f5e9f9ee Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 19 Jul 2007 11:22:06 +0000 Subject: Invalidate parent data before unregistering the child path since the unregister function might free the child path string (if it is part of the object path data) --- common/dbus-helper.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index 488b1d2f..a604f6de 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -283,7 +283,7 @@ static DBusObjectPathVTable generic_table = { .message_function = generic_message, }; -static void update_parent_data(DBusConnection *conn, const char *child_path) +static void invalidate_parent_data(DBusConnection *conn, const char *child_path) { struct generic_data *data = NULL; char *parent_path, *slash; @@ -330,7 +330,7 @@ dbus_bool_t dbus_connection_create_object_path(DBusConnection *connection, return FALSE; } - update_parent_data(connection, path); + invalidate_parent_data(connection, path); return TRUE; } @@ -338,12 +338,9 @@ dbus_bool_t dbus_connection_create_object_path(DBusConnection *connection, dbus_bool_t dbus_connection_destroy_object_path(DBusConnection *connection, const char *path) { - if (!dbus_connection_unregister_object_path(connection, path)) - return FALSE; - - update_parent_data(connection, path); + invalidate_parent_data(connection, path); - return TRUE; + return dbus_connection_unregister_object_path(connection, path); } dbus_bool_t dbus_connection_get_object_user_data(DBusConnection *connection, -- cgit From 47b21533a202883df227a106b2838b172d8a81f5 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 13 Aug 2007 19:04:42 +0000 Subject: append dict: added byte type --- common/dbus-helper.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index a604f6de..1983a8ee 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -429,6 +429,9 @@ void dbus_message_iter_append_dict_entry(DBusMessageIter *dict, case DBUS_TYPE_STRING: sig = DBUS_TYPE_STRING_AS_STRING; break; + case DBUS_TYPE_BYTE: + sig = DBUS_TYPE_BYTE_AS_STRING; + break; case DBUS_TYPE_INT16: sig = DBUS_TYPE_INT16_AS_STRING; break; -- cgit From 6bcb8c0cf5eb1842cc7d04ca34497869547ebefe Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 3 Sep 2007 13:33:52 +0000 Subject: hal common: removed small memory leak --- common/hal-libhal.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'common') diff --git a/common/hal-libhal.c b/common/hal-libhal.c index 3787e73d..479d635e 100644 --- a/common/hal-libhal.c +++ b/common/hal-libhal.c @@ -25,6 +25,7 @@ #include #endif +#include #include #include @@ -122,12 +123,15 @@ int hal_create_device(struct hal_device *device) " \n", &err) == FALSE) { error("Failed to claim to interface: ", err.message); + dbus_error_free(&err); } if (libhal_device_commit_to_gdl(hal_ctx, dev, udi, NULL) == FALSE) { error("Failed to create HAL device"); } + free(dev); + return 0; } -- cgit From ce397ae3d37d13e8665c93515f7f841f41dc32ea Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 4 Oct 2007 14:01:06 +0000 Subject: Handle deprecated dbus_watch_get_fd() function --- common/dbus.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index 1b5f7db8..61307bc0 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -37,6 +37,10 @@ #include +#ifdef NEED_DBUS_WATCH_GET_UNIX_FD +#define dbus_watch_get_unix_fd dbus_watch_get_fd +#endif + #ifdef HAVE_DBUS_GLIB #include #endif @@ -457,7 +461,7 @@ static dbus_bool_t add_server(DBusWatch *watch, void *data) info = g_new(struct server_info, 1); - fd = dbus_watch_get_fd(watch); + fd = dbus_watch_get_unix_fd(watch); info->io = g_io_channel_unix_new(fd); info->server = dbus_server_ref(server); @@ -542,7 +546,7 @@ static dbus_bool_t add_watch(DBusWatch *watch, void *data) info = g_new(struct watch_info, 1); - fd = dbus_watch_get_fd(watch); + fd = dbus_watch_get_unix_fd(watch); info->io = g_io_channel_unix_new(fd); info->conn = dbus_connection_ref(conn); -- cgit From 2d903fdf08308d9b9239343598ee157351e81a2a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 4 Oct 2007 16:00:51 +0000 Subject: Fix potential infinite loop in inotify support --- common/notify-inotify.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'common') diff --git a/common/notify-inotify.c b/common/notify-inotify.c index 281d4179..a7a832da 100644 --- a/common/notify-inotify.c +++ b/common/notify-inotify.c @@ -60,23 +60,27 @@ static gboolean io_event(GIOChannel *chan, GIOCondition cond, gpointer data) memset(buf, 0, sizeof(buf)); err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf) - 1, &len); - if (err == G_IO_ERROR_AGAIN) - return TRUE; + if (err != G_IO_ERROR_NONE) { + if (err == G_IO_ERROR_AGAIN) + return TRUE; + error("Reading from inotify channel failed"); + return FALSE; + } + while (len >= sizeof(struct inotify_event)) { struct inotify_event *evt = (struct inotify_event *) ptr; - if (evt->wd != wd || !callback) - continue; - - if (evt->mask & (IN_CREATE | IN_MOVED_TO)) - callback(NOTIFY_CREATE, evt->name, NULL); + if (evt->wd == wd && callback) { + if (evt->mask & (IN_CREATE | IN_MOVED_TO)) + callback(NOTIFY_CREATE, evt->name, NULL); - if (evt->mask & (IN_DELETE | IN_MOVED_FROM)) - callback(NOTIFY_DELETE, evt->name, NULL); + if (evt->mask & (IN_DELETE | IN_MOVED_FROM)) + callback(NOTIFY_DELETE, evt->name, NULL); - if (evt->mask & IN_MODIFY) - callback(NOTIFY_MODIFY, evt->name, NULL); + if (evt->mask & IN_MODIFY) + callback(NOTIFY_MODIFY, evt->name, NULL); + } len -= sizeof(struct inotify_event) + evt->len; ptr += sizeof(struct inotify_event) + evt->len; -- cgit From 4c6834afabcef620f1f5aff0c56b8994171d57d2 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 25 Oct 2007 14:05:18 +0000 Subject: Comment out introspection debug prints which cause a lot of useless logging --- common/dbus-helper.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index 1983a8ee..881dd2b5 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -143,8 +143,8 @@ static void generate_introspection_xml(DBusConnection *conn, g_string_append_printf(gstr, "\t\n", iface->name); for (method = iface->methods; method && method->name; method++) { - debug("%s: adding method %s.%s", - path, iface->name, method->name); + /* debug("%s: adding method %s.%s", + path, iface->name, method->name); */ if (!strlen(method->signature) && !strlen(method->reply)) g_string_append_printf(gstr, "\t\t\n", method->name); @@ -158,8 +158,8 @@ static void generate_introspection_xml(DBusConnection *conn, } for (signal = iface->signals; signal && signal->name; signal++) { - debug("%s: adding signal %s.%s", - path, iface->name, signal->name); + /* debug("%s: adding signal %s.%s", + path, iface->name, signal->name); */ if (!strlen(signal->signature)) g_string_append_printf(gstr, "\t\t\n", signal->name); -- cgit From 30a03883722aca1ad250550755cbecb0d5f95b5e Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 16 Nov 2007 15:43:29 +0000 Subject: Fix D-Bus match leak for name listeners --- common/dbus.c | 78 ++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 28 deletions(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index 61307bc0..f92ce45f 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -204,6 +204,52 @@ static void name_data_remove(DBusConnection *connection, } } +static gboolean add_match(DBusConnection *connection, const char *name) +{ + DBusError err; + char match_string[128]; + + snprintf(match_string, sizeof(match_string), + "interface=%s,member=NameOwnerChanged,arg0=%s", + DBUS_INTERFACE_DBUS, name); + + dbus_error_init(&err); + + dbus_bus_add_match(connection, match_string, &err); + + if (dbus_error_is_set(&err)) { + error("Adding match rule \"%s\" failed: %s", match_string, + err.message); + dbus_error_free(&err); + return FALSE; + } + + return TRUE; +} + +static gboolean remove_match(DBusConnection *connection, const char *name) +{ + DBusError err; + char match_string[128]; + + snprintf(match_string, sizeof(match_string), + "interface=%s,member=NameOwnerChanged,arg0=%s", + DBUS_INTERFACE_DBUS, name); + + dbus_error_init(&err); + + dbus_bus_remove_match(connection, match_string, &err); + + if (dbus_error_is_set(&err)) { + error("Removing owner match rule for %s failed: %s", + name, err.message); + dbus_error_free(&err); + return FALSE; + } + + return TRUE; +} + static DBusHandlerResult name_exit_filter(DBusConnection *connection, DBusMessage *message, void *user_data) { @@ -242,14 +288,14 @@ static DBusHandlerResult name_exit_filter(DBusConnection *connection, name_listeners = g_slist_remove(name_listeners, data); name_data_free(data); + remove_match(connection, name); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } int name_listener_add(DBusConnection *connection, const char *name, name_cb_t func, void *user_data) { - DBusError err; - char match_string[128]; int first; if (!name_listener_initialized) { @@ -270,17 +316,7 @@ int name_listener_add(DBusConnection *connection, const char *name, if (name) { debug("name_listener_add(%s)", name); - snprintf(match_string, sizeof(match_string), - "interface=%s,member=NameOwnerChanged,arg0=%s", - DBUS_INTERFACE_DBUS, name); - - dbus_error_init(&err); - dbus_bus_add_match(connection, match_string, &err); - - if (dbus_error_is_set(&err)) { - error("Adding match rule \"%s\" failed: %s", - match_string, err.message); - dbus_error_free(&err); + if (!add_match(connection, name)) { name_data_remove(connection, name, func, user_data); return -1; } @@ -294,8 +330,6 @@ int name_listener_remove(DBusConnection *connection, const char *name, { struct name_data *data; struct name_callback *cb; - DBusError err; - char match_string[128]; data = name_data_find(connection, name); if (!data) { @@ -319,20 +353,8 @@ int name_listener_remove(DBusConnection *connection, const char *name, if (name) { debug("name_listener_remove(%s)", name); - snprintf(match_string, sizeof(match_string), - "interface=%s,member=NameOwnerChanged,arg0=%s", - DBUS_INTERFACE_DBUS, name); - - dbus_error_init(&err); - - dbus_bus_remove_match(connection, match_string, &err); - - if (dbus_error_is_set(&err)) { - error("Removing owner match rule for %s failed: %s", - name, err.message); - dbus_error_free(&err); + if (!remove_match(connection, name)) return -1; - } } name_data_remove(connection, name, func, user_data); -- cgit From 48ce703ca92056265f6f036f42c8f8843700d15f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 26 Nov 2007 11:52:16 +0000 Subject: Fix key search function to honor the mmap area size --- common/textfile.c | 54 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 14 deletions(-) (limited to 'common') diff --git a/common/textfile.c b/common/textfile.c index ea7e80bb..88e783a8 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -28,6 +28,7 @@ #define _GNU_SOURCE #include #include +#include #include #include #include @@ -78,7 +79,8 @@ int create_file(const char *filename, const mode_t mode) int fd; umask(S_IWGRP | S_IWOTH); - create_dirs(filename, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + create_dirs(filename, S_IRUSR | S_IWUSR | S_IXUSR | + S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); fd = open(filename, O_RDWR | O_CREAT, mode); if (fd < 0) @@ -94,19 +96,42 @@ int create_name(char *buf, size_t size, const char *path, const char *address, c return snprintf(buf, size, "%s/%s/%s", path, address, name); } -static inline char *find_key(char *map, const char *key, size_t len, int icase) +static inline char *find_key(char *map, size_t size, const char *key, size_t len, int icase) { - char *off = (icase) ? strcasestr(map, key) : strstr(map, key); - - while (off && ((off > map && *(off - 1) != '\r' && - *(off - 1) != '\n') || *(off + len) != ' ')) { - if (icase) - off = strcasestr(off + len, key); - else - off = strstr(off + len, key); + char *ptr = map; + size_t ptrlen = size; + + while (ptrlen > len + 1) { + int cmp = (icase) ? strncasecmp(ptr, key, len) : strncmp(ptr, key, len); + if (cmp == 0) { + if (ptr == map) + return ptr; + + if ((*(ptr - 1) == '\r' || *(ptr - 1) == '\n') && + *(ptr + len) == ' ') + return ptr; + } + + if (icase) { + char *p1 = memchr(ptr + 1, tolower(*key), ptrlen - 1); + char *p2 = memchr(ptr + 1, toupper(*key), ptrlen - 1); + + if (!p1) + ptr = p2; + else if (!p2) + ptr = p1; + else + ptr = (p1 < p2) ? p1 : p2; + } else + ptr = memchr(ptr + 1, *key, ptrlen - 1); + + if (!ptr) + return NULL; + + ptrlen = size - (ptr - map); } - return off; + return NULL; } static inline int write_key_value(int fd, const char *key, const char *value) @@ -162,14 +187,15 @@ static int write_key(const char *pathname, const char *key, const char *value, i goto unlock; } - map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_LOCKED, fd, 0); + map = mmap(NULL, size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_LOCKED, fd, 0); if (!map || map == MAP_FAILED) { err = errno; goto unlock; } len = strlen(key); - off = find_key(map, key, len, icase); + off = find_key(map, size, key, len, icase); if (!off) { if (value) { munmap(map, size); @@ -281,7 +307,7 @@ static char *read_key(const char *pathname, const char *key, int icase) } len = strlen(key); - off = find_key(map, key, len, icase); + off = find_key(map, size, key, len, icase); if (!off) { err = EILSEQ; goto unmap; -- cgit From 0b5513d2ae7ebdebd601fb379f8dcedf4db8ff55 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 26 Nov 2007 12:12:00 +0000 Subject: Add test for files with page size --- common/test_textfile.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'common') diff --git a/common/test_textfile.c b/common/test_textfile.c index 1c001f46..14320c17 100644 --- a/common/test_textfile.c +++ b/common/test_textfile.c @@ -43,11 +43,26 @@ int main(int argc, char *argv[]) { char filename[] = "/tmp/textfile"; char key[18], value[512], *str; - int i, j, fd, max = 10; + int i, j, fd, err, size, max = 10; + + size = getpagesize(); + printf("System uses a page size of %d bytes\n\n", size); fd = creat(filename, 0644); + err = ftruncate(fd, 0); + + memset(value, 0, sizeof(value)); + for (i = 0; i < (size / sizeof(value)); i++) + err = write(fd, value, sizeof(value)); + close(fd); + sprintf(key, "11:11:11:11:11:11"); + str = textfile_get(filename, key); + + err = truncate(filename, 0); + + sprintf(key, "00:00:00:00:00:00"); if (textfile_del(filename, key) < 0) fprintf(stderr, "%s (%d)\n", strerror(errno), errno); -- cgit From 05ba90324ddfd1de724c39f2f9f28ec10930996f Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 26 Nov 2007 13:40:09 +0000 Subject: Add common error helper functions --- common/Makefile.am | 1 + common/dbus-helper.h | 1 + common/error.c | 242 +++++++++++++++++++++++++++++++++++++++++++++++++++ common/error.h | 80 +++++++++++++++++ 4 files changed, 324 insertions(+) create mode 100644 common/error.c create mode 100644 common/error.h (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index a2e50354..ed92765e 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -26,6 +26,7 @@ noinst_LIBRARIES = libhelper.a libhelper_a_SOURCES = oui.h oui.c dbus.h dbus.c \ textfile.h textfile.c logging.h logging.c \ dbus-helper.h dbus-helper.c \ + error.h error.c \ sdp-xml.h sdp-xml.c $(sdp_sources) \ hal.h $(hal_sources) notify.h $(notify_sources) diff --git a/common/dbus-helper.h b/common/dbus-helper.h index 4dd9d155..fa5282d9 100644 --- a/common/dbus-helper.h +++ b/common/dbus-helper.h @@ -21,6 +21,7 @@ * */ #include +#include #define DBUS_TYPE_STRING_ARRAY_AS_STRING (DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING) #define DBUS_TYPE_BYTE_ARRAY_AS_STRING (DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING) diff --git a/common/error.c b/common/error.c new file mode 100644 index 00000000..b00294f7 --- /dev/null +++ b/common/error.c @@ -0,0 +1,242 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2006-2007 Nokia Corporation + * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2007 Fabien Chevalier + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "dbus-helper.h" +#include "error.h" + +/** + org.bluez.Error.DeviceUnreachable: + + The remote device is either powered down or out of range. +*/ +DBusHandlerResult error_device_unreachable(DBusConnection *conn, DBusMessage *msg) +{ + return error_common_reply(conn, msg, ERROR_INTERFACE ".DeviceUnreachable", + "Device Unreachable"); +} + +/** + org.bluez.Error.ConnectionAttemptFailed: + + An unexpected error (other than DeviceUnreachable) error has occured while + attempting a connection to a device +*/ +DBusHandlerResult error_connection_attempt_failed(DBusConnection *conn, DBusMessage *msg, int err) +{ + return error_common_reply(conn, msg, + ERROR_INTERFACE ".ConnectionAttemptFailed", + err ? strerror(err) : "Connection attempt failed"); +} + +/** + org.bluez.Error.AlreadyConnected: + + A connection request has been received on an already connected device. +*/ +DBusHandlerResult error_already_connected(DBusConnection *conn, DBusMessage *msg) +{ + return error_common_reply(conn, msg, + ERROR_INTERFACE ".AlreadyConnected", + "Already connected to a device"); +} + +/** + org.bluez.Error.InProgress: + + Error returned if an operation is in progress. Since + this is a generic error that can be used in various + situations, the error message should be more clear + about what is in progress. For example "Bonding in + progress". + */ +DBusHandlerResult error_in_progress(DBusConnection *conn, DBusMessage *msg, + const char *str) +{ + return error_common_reply(conn, msg, ERROR_INTERFACE ".InProgress", str); +} + +/** + org.bluez.Error.InvalidArguments: + + The DBUS request does not contain the right number of + arguments with the right type, or the arguments are there but + their value is wrong, or does not makes sense in the current context. +*/ +DBusHandlerResult error_invalid_arguments(DBusConnection *conn, DBusMessage *msg, + const char *descr) +{ + return error_common_reply(conn, msg, + ERROR_INTERFACE ".InvalidArguments", + descr ? descr : "Invalid arguments in method call"); +} + +/** + org.bluez.Error.OutOfMemory: + + Not enough memory to execute the request. + Error returned when a memory allocation via malloc() + fails. This error is similar to ENOMEM. +*/ +DBusHandlerResult error_out_of_memory(DBusConnection *conn, DBusMessage *msg) +{ + return error_common_reply(conn, msg, ERROR_INTERFACE ".OutOfMemory", + "Out of memory"); +} + +/** + org.bluez.Error.NotAvailable: + + The requested information is not there. + Examples of use: Adapter object when remote info is not available, or Database + object record is not found +*/ +DBusHandlerResult error_not_available(DBusConnection *conn, DBusMessage *msg) +{ + return error_common_reply(conn, msg, ERROR_INTERFACE ".NotAvailable", + "Not available"); +} + +/** + org.bluez.Error.NotSupported: + + The remote device does not support the expected feature. + Examples of use: trying to connect to audio device while audio is not + declared in device sdp record. +*/ +DBusHandlerResult error_not_supported(DBusConnection *conn, DBusMessage *msg) +{ + return error_common_reply(conn, msg, ERROR_INTERFACE ".NotSupported", + "Not supported"); +} + +/** + org.bluez.Error.NotConnected: + + The remote device is not connected, while the method call + would expect it to be, or is not in the expected state to + perform the action +*/ +DBusHandlerResult error_not_connected(DBusConnection *conn, DBusMessage *msg) +{ + return error_common_reply(conn, msg, ERROR_INTERFACE ".NotConnected", + "Not connected"); +} + +/** + org.bluez.Error.AlreadyExists: + + One of the requested elements already exists + Examples of use: Bonding, record, passkey agent, auth agent, + hid device ... already exists +*/ +DBusHandlerResult error_already_exists(DBusConnection *conn, DBusMessage *msg, + const char *str) +{ + return error_common_reply(conn, msg, ERROR_INTERFACE ".AlreadyExists", str); +} + +/** + org.bluez.Error.DoesNotExist: + + One of the requested elements does not exist + Examples of use: Bonding, record, passkey agent, auth agent, bluetooth device + ... does not exist. +*/ +DBusHandlerResult error_does_not_exist(DBusConnection *conn, DBusMessage *msg, + const char *str) +{ + return error_common_reply(conn, msg, ERROR_INTERFACE ".DoesNotExist", str); +} + +/** + org.bluez.Error.DoesNotExist: + + Same as error_does_not_exist, but with device error message +*/ +DBusHandlerResult error_device_does_not_exist(DBusConnection *conn, + DBusMessage *msg) +{ + return error_does_not_exist(conn, msg, "Device does not exist"); +} + +/** + org.bluez.Error.Canceled: + + The operation was canceled. + Examples of use : autorization process canceled, connection canceled +*/ +DBusHandlerResult error_canceled(DBusConnection *conn, DBusMessage *msg, + const char *str) +{ + return error_common_reply(conn, msg, ERROR_INTERFACE ".Canceled", str); +} + +/** + org.bluez.Error.Failed: + + This is a the most generic error. + desc filed is MANDATORY +*/ +DBusHandlerResult error_failed(DBusConnection *conn, DBusMessage *msg, + const char * desc) +{ + return error_common_reply(conn, msg, ERROR_INTERFACE ".Failed", desc); +} + +/** + org.bluez.Error.Failed: + + This is a the most generic error, instantiated form a UNIX errno number. +*/ +DBusHandlerResult error_failed_errno(DBusConnection *conn, DBusMessage *msg, + int err) +{ + const char *desc = strerror(err); + + return error_failed(conn, msg, desc); +} + +/* Helper function - internal use only */ +DBusHandlerResult error_common_reply(DBusConnection *conn, DBusMessage *msg, + const char *name, const char *descr) +{ + DBusMessage *derr; + + if (!conn || !msg) + return DBUS_HANDLER_RESULT_HANDLED; + + derr = dbus_message_new_error(msg, name, descr); + if (!derr) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + return dbus_connection_send_and_unref(conn, derr); +} diff --git a/common/error.h b/common/error.h new file mode 100644 index 00000000..d6f17f06 --- /dev/null +++ b/common/error.h @@ -0,0 +1,80 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2006-2007 Nokia Corporation + * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2007 Fabien Chevalier + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* + Please update dbus-api.txt in hcid folder when changes are made to this file. + */ + +#include + +#define ERROR_INTERFACE "org.bluez.Error" + +DBusHandlerResult error_device_unreachable(DBusConnection *conn, + DBusMessage *msg); + +DBusHandlerResult error_connection_attempt_failed(DBusConnection *conn, + DBusMessage *msg, + int err); + +DBusHandlerResult error_already_connected(DBusConnection *conn, + DBusMessage *msg); + +DBusHandlerResult error_not_connected(DBusConnection *conn, DBusMessage *msg); + +DBusHandlerResult error_in_progress(DBusConnection *conn, DBusMessage *msg, + const char *str); + +DBusHandlerResult error_invalid_arguments(DBusConnection *conn, + DBusMessage *msg, + const char *str); + +DBusHandlerResult error_out_of_memory(DBusConnection *conn, DBusMessage *msg); + +DBusHandlerResult error_not_available(DBusConnection *conn, DBusMessage *msg); + +DBusHandlerResult error_not_supported(DBusConnection *conn, + DBusMessage *msg); + +DBusHandlerResult error_already_exists(DBusConnection *conn, DBusMessage *msg, + const char *str); + +DBusHandlerResult error_does_not_exist(DBusConnection *conn, DBusMessage *msg, + const char *str); + +DBusHandlerResult error_device_does_not_exist(DBusConnection *conn, + DBusMessage *msg); + +DBusHandlerResult error_canceled(DBusConnection *conn, DBusMessage *msg, + const char *str); + +DBusHandlerResult error_failed(DBusConnection *conn, DBusMessage *msg, + const char *desc); + +DBusHandlerResult error_failed_errno(DBusConnection *conn, DBusMessage *msg, + int err); + +DBusHandlerResult error_common_reply(DBusConnection *conn, DBusMessage *msg, + const char *name, const char *descr); + -- cgit From 79e5dd0c9e917822d0a97a1f803fc7571b253643 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 6 Dec 2007 12:56:11 +0000 Subject: Fix memory leak --- common/dbus-helper.c | 1 + 1 file changed, 1 insertion(+) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index 881dd2b5..0bd1eb06 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -326,6 +326,7 @@ dbus_bool_t dbus_connection_create_object_path(DBusConnection *connection, if (!dbus_connection_register_object_path(connection, path, &generic_table, data)) { + g_free(data->introspect); g_free(data); return FALSE; } -- cgit From 5e50d37b69baa435fe9f35d0addfe42a011465c1 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 9 Dec 2007 01:33:54 +0000 Subject: Use proper function for checking signal name --- common/dbus.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index f92ce45f..dd7a34fc 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -434,17 +434,10 @@ dbus_bool_t dbus_bus_get_unix_process_id(DBusConnection *conn, const char *name, static DBusHandlerResult disconnect_filter(DBusConnection *conn, DBusMessage *msg, void *data) { - const char *iface,*method; struct disconnect_data *dc_data = data; - if (dbus_message_get_type (msg) != DBUS_MESSAGE_TYPE_SIGNAL) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - iface = dbus_message_get_interface(msg); - method = dbus_message_get_member(msg); - - if ((strcmp(iface, DBUS_INTERFACE_LOCAL) == 0) && - (strcmp(method, "Disconnected") == 0)) { + if (dbus_message_is_signal(msg, + DBUS_INTERFACE_LOCAL, "Disconnected") == TRUE) { error("Got disconnected from the system message bus"); dbus_connection_unref(conn); dc_data->disconnect_cb(dc_data->user_data); -- cgit From ba255beb79afb9c00ae5b71821f84f911aa8d1fe Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 28 Jan 2008 10:38:40 +0000 Subject: Whitespace cleanup --- common/sdp-xml.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'common') diff --git a/common/sdp-xml.c b/common/sdp-xml.c index 5aeca405..bf3eb0c3 100644 --- a/common/sdp-xml.c +++ b/common/sdp-xml.c @@ -237,7 +237,7 @@ static void convert_raw_data_to_xml(sdp_data_t *value, int indent_level, hex = 0; int num_chars_to_escape = 0; - + for (i = 0; i < value->unitSize; i++) { if (i == (value->unitSize - 1) && value->val.str[i] == '\0') @@ -246,16 +246,15 @@ static void convert_raw_data_to_xml(sdp_data_t *value, int indent_level, hex = 1; break; } - + /* XML is evil, must do this... */ if ((value->val.str[i] == '<') || - (value->val.str[i] == '>') || - (value->val.str[i] == '"') || - (value->val.str[i] == '&')) - num_chars_to_escape++; - + (value->val.str[i] == '>') || + (value->val.str[i] == '"') || + (value->val.str[i] == '&')) + num_chars_to_escape++; } - + appender(data, indent); appender(data, "val.dataseq, indent_level + 1, data, appender); - + appender(data, indent); appender(data, "\n"); - + break; case SDP_ALT8: @@ -358,7 +357,7 @@ static void convert_raw_data_to_xml(sdp_data_t *value, int indent_level, appender(data, indent); appender(data, "\n"); - + break; } @@ -577,7 +576,7 @@ sdp_data_t *sdp_xml_parse_int(const char * data, uint8_t dtd) case SDP_INT64: { int64_t val = strtoull(data, &endptr, 0); - + /* Failed to parse */ if ((endptr != data) && (*endptr != '\0')) return NULL; -- cgit From e823c15e43a6f924779e466d434c51157002d9ee Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 2 Feb 2008 03:37:05 +0000 Subject: Update copyright information --- common/dbus-helper.c | 2 +- common/dbus-helper.h | 2 +- common/dbus.c | 2 +- common/dbus.h | 2 +- common/error.c | 4 ++-- common/error.h | 8 ++------ common/hal-dummy.c | 2 +- common/hal-libhal.c | 2 +- common/hal.h | 2 +- common/logging.c | 2 +- common/logging.h | 2 +- common/notify-dummy.c | 2 +- common/notify-inotify.c | 2 +- common/notify.h | 2 +- common/oui.c | 2 +- common/oui.h | 2 +- common/sdp-dummy.c | 2 +- common/sdp-expat.c | 2 +- common/sdp-glib.c | 2 +- common/sdp-xml.c | 2 +- common/sdp-xml.h | 2 +- common/test_textfile.c | 2 +- common/textfile.c | 2 +- common/textfile.h | 2 +- common/uinput.h | 2 +- 25 files changed, 27 insertions(+), 31 deletions(-) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index 0bd1eb06..67dd91ed 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/dbus-helper.h b/common/dbus-helper.h index fa5282d9..62810260 100644 --- a/common/dbus-helper.h +++ b/common/dbus-helper.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/dbus.c b/common/dbus.c index dd7a34fc..529caad3 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/dbus.h b/common/dbus.h index e91fd3cf..b65a83c9 100644 --- a/common/dbus.h +++ b/common/dbus.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/error.c b/common/error.c index b00294f7..daabe48d 100644 --- a/common/error.c +++ b/common/error.c @@ -3,8 +3,8 @@ * BlueZ - Bluetooth protocol stack for Linux * * Copyright (C) 2006-2007 Nokia Corporation - * Copyright (C) 2004-2007 Marcel Holtmann - * Copyright (C) 2007 Fabien Chevalier + * Copyright (C) 2004-2008 Marcel Holtmann + * Copyright (C) 2007-2008 Fabien Chevalier * * * This program is free software; you can redistribute it and/or modify diff --git a/common/error.h b/common/error.h index d6f17f06..03d0c182 100644 --- a/common/error.h +++ b/common/error.h @@ -3,8 +3,8 @@ * BlueZ - Bluetooth protocol stack for Linux * * Copyright (C) 2006-2007 Nokia Corporation - * Copyright (C) 2004-2007 Marcel Holtmann - * Copyright (C) 2007 Fabien Chevalier + * Copyright (C) 2004-2008 Marcel Holtmann + * Copyright (C) 2007-2008 Fabien Chevalier * * * This program is free software; you can redistribute it and/or modify @@ -23,10 +23,6 @@ * */ -/* - Please update dbus-api.txt in hcid folder when changes are made to this file. - */ - #include #define ERROR_INTERFACE "org.bluez.Error" diff --git a/common/hal-dummy.c b/common/hal-dummy.c index a516ed1b..a049cda9 100644 --- a/common/hal-dummy.c +++ b/common/hal-dummy.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2006-2007 Marcel Holtmann + * Copyright (C) 2006-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/hal-libhal.c b/common/hal-libhal.c index 479d635e..63b5677e 100644 --- a/common/hal-libhal.c +++ b/common/hal-libhal.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2006-2007 Marcel Holtmann + * Copyright (C) 2006-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/hal.h b/common/hal.h index 5f80fb92..075ceb17 100644 --- a/common/hal.h +++ b/common/hal.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2006-2007 Marcel Holtmann + * Copyright (C) 2006-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/logging.c b/common/logging.c index 52fd8071..28fc9af5 100644 --- a/common/logging.c +++ b/common/logging.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/logging.h b/common/logging.h index c9134425..e99131e5 100644 --- a/common/logging.h +++ b/common/logging.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/notify-dummy.c b/common/notify-dummy.c index 33f7909e..98fdb621 100644 --- a/common/notify-dummy.c +++ b/common/notify-dummy.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2006-2007 Marcel Holtmann + * Copyright (C) 2006-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/notify-inotify.c b/common/notify-inotify.c index a7a832da..a8a6b193 100644 --- a/common/notify-inotify.c +++ b/common/notify-inotify.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2006-2007 Marcel Holtmann + * Copyright (C) 2006-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/notify.h b/common/notify.h index 3a58c508..50555dc1 100644 --- a/common/notify.h +++ b/common/notify.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2006-2007 Marcel Holtmann + * Copyright (C) 2006-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/oui.c b/common/oui.c index 4b60ef16..a9c4af5a 100644 --- a/common/oui.c +++ b/common/oui.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/oui.h b/common/oui.h index 252ce4f3..991e145c 100644 --- a/common/oui.h +++ b/common/oui.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/sdp-dummy.c b/common/sdp-dummy.c index d1afe426..fa93dc33 100644 --- a/common/sdp-dummy.c +++ b/common/sdp-dummy.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2005-2007 Marcel Holtmann + * Copyright (C) 2005-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/sdp-expat.c b/common/sdp-expat.c index b8136528..9026c496 100644 --- a/common/sdp-expat.c +++ b/common/sdp-expat.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2005-2007 Marcel Holtmann + * Copyright (C) 2005-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/sdp-glib.c b/common/sdp-glib.c index f280d0d1..9ed81160 100644 --- a/common/sdp-glib.c +++ b/common/sdp-glib.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/sdp-xml.c b/common/sdp-xml.c index bf3eb0c3..664a1ff5 100644 --- a/common/sdp-xml.c +++ b/common/sdp-xml.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2005-2007 Marcel Holtmann + * Copyright (C) 2005-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/sdp-xml.h b/common/sdp-xml.h index 1ab6bb19..adb173e2 100644 --- a/common/sdp-xml.h +++ b/common/sdp-xml.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2005-2007 Marcel Holtmann + * Copyright (C) 2005-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/test_textfile.c b/common/test_textfile.c index 14320c17..1bb024eb 100644 --- a/common/test_textfile.c +++ b/common/test_textfile.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/textfile.c b/common/textfile.c index 88e783a8..021fc8fb 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/textfile.h b/common/textfile.h index f6559fea..b2276e3a 100644 --- a/common/textfile.h +++ b/common/textfile.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/common/uinput.h b/common/uinput.h index 277f843b..5f11ee24 100644 --- a/common/uinput.h +++ b/common/uinput.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2003-2007 Marcel Holtmann + * Copyright (C) 2003-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify -- cgit From a1ddddc934657aa734ceb4bf581423647cc68060 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 2 Feb 2008 15:06:45 +0000 Subject: Fix compilation issues with UCHAR_MAX, USHRT_MAX and UINT_MAX --- common/sdp-dummy.c | 1 + common/sdp-expat.c | 1 + common/sdp-glib.c | 1 + 3 files changed, 3 insertions(+) (limited to 'common') diff --git a/common/sdp-dummy.c b/common/sdp-dummy.c index fa93dc33..16d1d3bd 100644 --- a/common/sdp-dummy.c +++ b/common/sdp-dummy.c @@ -27,6 +27,7 @@ #include #include +#include #include "logging.h" #include "sdp-xml.h" diff --git a/common/sdp-expat.c b/common/sdp-expat.c index 9026c496..7076261a 100644 --- a/common/sdp-expat.c +++ b/common/sdp-expat.c @@ -26,6 +26,7 @@ #endif #include +#include #include #include diff --git a/common/sdp-glib.c b/common/sdp-glib.c index 9ed81160..bd27d822 100644 --- a/common/sdp-glib.c +++ b/common/sdp-glib.c @@ -26,6 +26,7 @@ #endif #include +#include #include #include -- cgit From 63d22e782f115c2e55a3886cc577b038408f2145 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 12 Feb 2008 03:36:36 +0000 Subject: Update uinput.h with extra key definitions --- common/uinput.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'common') diff --git a/common/uinput.h b/common/uinput.h index 5f11ee24..dca87829 100644 --- a/common/uinput.h +++ b/common/uinput.h @@ -262,6 +262,7 @@ extern "C" { #define KEY_PROG4 203 #define KEY_SUSPEND 205 #define KEY_CLOSE 206 +#define KEY_PLAY 207 #define KEY_UNKNOWN 220 @@ -406,6 +407,10 @@ extern "C" { #define KEY_TEEN 0x19e #define KEY_TWEN 0x19f +#define KEY_FRAMEBACK 0x1b2 +#define KEY_FRAMEFORWARD 0x1b3 +#define KEY_CONTEXT_MENU 0x1fb + #define KEY_MAX 0x1ff /* Relative axes */ -- cgit From cf824c4d12cbbf2f287fdee817b367974d2f8421 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 5 Mar 2008 20:03:08 +0000 Subject: Remove the support for SDP parsing via expat --- common/Makefile.am | 4 - common/sdp-expat.c | 292 ----------------------------------------------------- 2 files changed, 296 deletions(-) delete mode 100644 common/sdp-expat.c (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index ed92765e..a6cab4d2 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -2,12 +2,8 @@ if GLIB sdp_sources = sdp-glib.c else -if EXPAT -sdp_sources = sdp-expat.c -else sdp_sources = sdp-dummy.c endif -endif if HAL hal_sources = hal-libhal.c diff --git a/common/sdp-expat.c b/common/sdp-expat.c deleted file mode 100644 index 7076261a..00000000 --- a/common/sdp-expat.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2005-2008 Marcel Holtmann - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include -#include - -#include - -#include "logging.h" -#include "sdp-xml.h" - -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; -} - -/* Expat specific implementation of the context struct */ - -struct sdp_xml_context { - XML_Parser parser; /* Parser object being used */ - sdp_record_t *sdprec; /* SDP Record being built */ - struct sdp_xml_data *stack_head; /* Top of the stack of attributes */ - int attrId; /* Id of the most recently processed attribute */ -}; - -static void convert_xml_to_sdp_start(void *data, const char *el, const char **attr) -{ - struct sdp_xml_context *context = data; - int i; - - 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) { - struct sdp_xml_data *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 = NULL; - } - - 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 { - /* 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(el, - context->stack_head, context->sdprec); - - /* Could not parse an entry */ - if (context->stack_head->data == NULL) - XML_StopParser(context->parser, 0); - } -} - -static void convert_xml_to_sdp_end(void *data, const char *el) -{ - struct sdp_xml_context *context = data; - struct sdp_xml_data *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 = NULL; - sdp_xml_data_free(context->stack_head); - context->stack_head = NULL; - } 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 = NULL; - break; - } - - elem = context->stack_head; - context->stack_head = context->stack_head->next; - - sdp_xml_data_free(elem); - } -} - -static struct sdp_xml_context *sdp_xml_init_context() -{ - struct sdp_xml_context *context; - - context = malloc(sizeof(struct 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; -} - -static void sdp_xml_free_context(struct sdp_xml_context *context) -{ - struct sdp_xml_data *elem; - - /* Free the stack */ - while (context->stack_head) { - elem = context->stack_head; - context->stack_head = elem->next; - sdp_xml_data_free(elem); - } - - XML_ParserFree(context->parser); - - free(context); -} - -static int sdp_xml_parse_chunk(struct sdp_xml_context *context, - const char *data, int size, int final) -{ - if (!XML_Parse(context->parser, data, size, final)) { - error("Parse error at line %d: %s\n", - XML_GetCurrentLineNumber(context->parser), - XML_ErrorString(XML_GetErrorCode(context->parser))); - return -1; - } - - return 0; -} - -sdp_record_t *sdp_xml_parse_record(const char *data, int size) -{ - struct sdp_xml_context *context; - sdp_record_t *record; - - context = sdp_xml_init_context(); - - if (sdp_xml_parse_chunk(context, data, size, 1) < 0) { - sdp_record_free(context->sdprec); - sdp_xml_free_context(context); - return NULL; - } - - record = context->sdprec; - - sdp_xml_free_context(context); - - return record; -} -- cgit From 6749599bb1a6c04d78cd9e647917022c3a65f603 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 5 Mar 2008 20:59:50 +0000 Subject: Fix distribution build --- common/Makefile.am | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index a6cab4d2..d40d9d1d 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -33,7 +33,6 @@ test_textfile_LDADD = libhelper.a AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ EXTRA_DIST = ppoll.h uinput.h hal-dummy.c hal-libhal.c \ - notify-dummy.c notify-inotify.c \ - sdp-dummy.c sdp-expat.c sdp-glib.c + notify-dummy.c notify-inotify.c sdp-dummy.c sdp-glib.c MAINTAINERCLEANFILES = Makefile.in -- cgit From 3602dd77d79d7e172523d6ae32171b8e22b0e139 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 5 Mar 2008 21:52:10 +0000 Subject: Use the GMarkup stubs from eglib --- common/Makefile.am | 11 ++--------- common/sdp-dummy.c | 40 ---------------------------------------- common/sdp-xml.c | 1 - 3 files changed, 2 insertions(+), 50 deletions(-) delete mode 100644 common/sdp-dummy.c (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index d40d9d1d..f1d846a6 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -1,10 +1,4 @@ -if GLIB -sdp_sources = sdp-glib.c -else -sdp_sources = sdp-dummy.c -endif - if HAL hal_sources = hal-libhal.c else @@ -22,8 +16,7 @@ noinst_LIBRARIES = libhelper.a libhelper_a_SOURCES = oui.h oui.c dbus.h dbus.c \ textfile.h textfile.c logging.h logging.c \ dbus-helper.h dbus-helper.c \ - error.h error.c \ - sdp-xml.h sdp-xml.c $(sdp_sources) \ + error.h error.c sdp-xml.h sdp-xml.c sdp-glib.c \ hal.h $(hal_sources) notify.h $(notify_sources) noinst_PROGRAMS = test_textfile @@ -33,6 +26,6 @@ test_textfile_LDADD = libhelper.a AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ EXTRA_DIST = ppoll.h uinput.h hal-dummy.c hal-libhal.c \ - notify-dummy.c notify-inotify.c sdp-dummy.c sdp-glib.c + notify-dummy.c notify-inotify.c MAINTAINERCLEANFILES = Makefile.in diff --git a/common/sdp-dummy.c b/common/sdp-dummy.c deleted file mode 100644 index 16d1d3bd..00000000 --- a/common/sdp-dummy.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2005-2008 Marcel Holtmann - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include "logging.h" -#include "sdp-xml.h" - -sdp_record_t *sdp_xml_parse_record(const char *data, int size) -{ - error("No XML parser available"); - - return NULL; -} diff --git a/common/sdp-xml.c b/common/sdp-xml.c index 664a1ff5..2cc55c2d 100644 --- a/common/sdp-xml.c +++ b/common/sdp-xml.c @@ -37,7 +37,6 @@ #include #include "logging.h" - #include "sdp-xml.h" #define STRBUFSIZE 1024 -- cgit From 022b6a3c695ecccc54e20432caff3668bd28d4c5 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 6 Mar 2008 14:03:45 +0000 Subject: Add skeleton for GLib helpers --- common/Makefile.am | 4 ++-- common/glib-helper.c | 42 ++++++++++++++++++++++++++++++++++++++++++ common/glib-helper.h | 22 ++++++++++++++++++++++ 3 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 common/glib-helper.c create mode 100644 common/glib-helper.h (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index f1d846a6..c231319b 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -15,8 +15,8 @@ noinst_LIBRARIES = libhelper.a libhelper_a_SOURCES = oui.h oui.c dbus.h dbus.c \ textfile.h textfile.c logging.h logging.c \ - dbus-helper.h dbus-helper.c \ - error.h error.c sdp-xml.h sdp-xml.c sdp-glib.c \ + dbus-helper.h dbus-helper.c error.h error.c \ + glib-helper.h glib-helper.c sdp-xml.h sdp-xml.c sdp-glib.c \ hal.h $(hal_sources) notify.h $(notify_sources) noinst_PROGRAMS = test_textfile diff --git a/common/glib-helper.c b/common/glib-helper.c new file mode 100644 index 00000000..35261188 --- /dev/null +++ b/common/glib-helper.c @@ -0,0 +1,42 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2008 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include + +#include + +#include "glib-helper.h" + +int bt_discover_services(const bdaddr_t src, const bdaddr_t dst, + void (*callback) (void), void *user_data, + void (*destroy) (void *user_data)) +{ + return -EIO; +} diff --git a/common/glib-helper.h b/common/glib-helper.h new file mode 100644 index 00000000..71377516 --- /dev/null +++ b/common/glib-helper.h @@ -0,0 +1,22 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2008 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ -- cgit From 6eab5e203d793fbeea8a488a315a62ab2e69417e Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 6 Mar 2008 21:58:13 +0000 Subject: added bt_discover_services function --- common/glib-helper.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++-- common/glib-helper.h | 6 +++ 2 files changed, 143 insertions(+), 4 deletions(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index 35261188..b97aa82c 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -29,14 +29,147 @@ #include #include +#include +#include #include #include "glib-helper.h" -int bt_discover_services(const bdaddr_t src, const bdaddr_t dst, - void (*callback) (void), void *user_data, - void (*destroy) (void *user_data)) +struct search_context { + bdaddr_t src; + bdaddr_t dst; + sdp_session_t *session; + bt_callback_t cb; + bt_destroy_t destroy; + gpointer user_data; +}; + +static void search_context_cleanup(struct search_context *ctxt) +{ + if (ctxt->destroy) + ctxt->destroy(ctxt->user_data); + sdp_close(ctxt->session); + g_free(ctxt); +} + +static void search_completed_cb(uint8_t type, uint16_t status, + uint8_t *rsp, size_t size, void *user_data) +{ + struct search_context *ctxt = user_data; + sdp_list_t *recs = NULL; + + /* FIXME: Extract the records */ + + ctxt->cb(ctxt->user_data, recs, 0); + + search_context_cleanup(ctxt); +} + +static gboolean search_process_cb(GIOChannel *chan, + GIOCondition cond, void *user_data) +{ + struct search_context *ctxt = user_data; + int err = 0; + + if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) { + err = EIO; + goto failed; + } + + if (sdp_process(ctxt->session) < 0) + goto failed; + + return TRUE; + +failed: + if (err) { + ctxt->cb(ctxt->user_data, NULL, -err); + search_context_cleanup(ctxt); + } + + return FALSE; +} + +static gboolean connect_watch(GIOChannel *chan, GIOCondition cond, gpointer user_data) { - return -EIO; + struct search_context *ctxt = user_data; + sdp_list_t *search, *attrids; + uint32_t range = 0x0000ffff; + uuid_t uuid; + socklen_t len; + int sk, err = 0; + + sk = g_io_channel_unix_get_fd(chan); + + len = sizeof(err); + if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { + err = errno; + goto failed; + } + + if (err != 0) + goto failed; + + if (sdp_set_notify(ctxt->session, search_completed_cb, ctxt) < 0) { + err = EIO; + goto failed; + } + + sdp_uuid16_create(&uuid, PUBLIC_BROWSE_GROUP); + search = sdp_list_append(NULL, &uuid); + attrids = sdp_list_append(NULL, &range); + if (sdp_service_search_attr_async(ctxt->session, + search, SDP_ATTR_REQ_RANGE, attrids) < 0) { + sdp_list_free(attrids, NULL); + sdp_list_free(search, NULL); + err = EIO; + goto failed; + } + + sdp_list_free(attrids, NULL); + sdp_list_free(search, NULL); + + /* Set callback responsible for update the internal SDP transaction */ + g_io_add_watch(chan, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, + search_process_cb, ctxt); + return FALSE; + +failed: + ctxt->cb(ctxt->user_data, NULL, -err); + search_context_cleanup(ctxt); + + return FALSE; +} + +int bt_discover_services(const bdaddr_t *src, const bdaddr_t *dst, + bt_callback_t cb, void *user_data, bt_destroy_t destroy) +{ + struct search_context *ctxt; + sdp_session_t *s; + GIOChannel *chan; + + if (!cb) + return -EINVAL; + + s = sdp_connect(src, dst, SDP_NON_BLOCKING); + if (!s) + return -EIO; + + ctxt = g_malloc0(sizeof(struct search_context)); + if (!ctxt) + return -ENOMEM; + + bacpy(&ctxt->src, src); + bacpy(&ctxt->dst, dst); + ctxt->session = s; + ctxt->cb = cb; + ctxt->destroy = destroy; + ctxt->user_data = user_data; + + chan = g_io_channel_unix_new(sdp_get_socket(s)); + g_io_add_watch(chan, G_IO_OUT, connect_watch, ctxt); + g_io_channel_unref(chan); + + return 0; } diff --git a/common/glib-helper.h b/common/glib-helper.h index 71377516..7426a6ad 100644 --- a/common/glib-helper.h +++ b/common/glib-helper.h @@ -20,3 +20,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ + +typedef void (*bt_callback_t) (gpointer user_data, sdp_list_t *recs, int err); +typedef void (*bt_destroy_t) (gpointer user_data); + +int bt_discover_services(const bdaddr_t *src, const bdaddr_t *dst, + bt_callback_t cb, void *user_data, bt_destroy_t destroy); -- cgit From 7e31dd1071053dd326f19633a6f64188c787326d Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 6 Mar 2008 22:25:26 +0000 Subject: added missing conditions for sdp connect watch --- common/glib-helper.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index b97aa82c..f4d3f9d4 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -168,7 +168,8 @@ int bt_discover_services(const bdaddr_t *src, const bdaddr_t *dst, ctxt->user_data = user_data; chan = g_io_channel_unix_new(sdp_get_socket(s)); - g_io_add_watch(chan, G_IO_OUT, connect_watch, ctxt); + g_io_add_watch(chan, G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL, + connect_watch, ctxt); g_io_channel_unref(chan); return 0; -- cgit From 8b415b792063dc548c753c37166dfa104157daee Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 7 Mar 2008 13:00:13 +0000 Subject: glib-helper: use g_try_malloc instead of g_malloc --- common/glib-helper.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index f4d3f9d4..5938e654 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -154,11 +154,13 @@ int bt_discover_services(const bdaddr_t *src, const bdaddr_t *dst, s = sdp_connect(src, dst, SDP_NON_BLOCKING); if (!s) - return -EIO; + return -errno; - ctxt = g_malloc0(sizeof(struct search_context)); - if (!ctxt) + ctxt = g_try_malloc0(sizeof(struct search_context)); + if (!ctxt) { + sdp_close(s); return -ENOMEM; + } bacpy(&ctxt->src, src); bacpy(&ctxt->dst, dst); -- cgit From b866782105bd76c0f7f2c2bc9e2f4a25d3b0d0fe Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 7 Mar 2008 14:17:56 +0000 Subject: Fix handling of compat_ppoll when no timeout is specified --- common/ppoll.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'common') diff --git a/common/ppoll.h b/common/ppoll.h index d9096901..7d09d44d 100644 --- a/common/ppoll.h +++ b/common/ppoll.h @@ -7,5 +7,10 @@ static inline int compat_ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout, const sigset_t *sigmask) { - return poll(fds, nfds, timeout ? timeout->tv_sec * 1000 : 500); + if (timeout == NULL) + return poll(fds, nfds, -1); + else if (timeout->tv_sec == 0) + return poll(fds, nfds, 500); + else + return poll(fds, nfds, timeout->tv_sec * 1000); } -- cgit From ed8b41b18ffaee05ed24bc3d29063666852c0659 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 7 Mar 2008 14:35:25 +0000 Subject: glib-helper: Extracting the sdp record --- common/glib-helper.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index 5938e654..be3f7a25 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -58,10 +58,41 @@ static void search_completed_cb(uint8_t type, uint16_t status, { struct search_context *ctxt = user_data; sdp_list_t *recs = NULL; + int scanned, seqlen = 0; + uint8_t dataType; + int err = 0; + + if (status || type != SDP_SVC_SEARCH_ATTR_RSP) { + err = -EPROTO; + goto done; + } + + scanned = sdp_extract_seqtype(rsp, &dataType, &seqlen); + if (!scanned || !seqlen) + goto done; + + rsp += scanned; + do { + sdp_record_t *rec; + int recsize; + + recsize = 0; + rec = sdp_extract_pdu(rsp, &recsize); + if (!rec) + break; + + if (!recsize) { + sdp_record_free(rec); + break; + } - /* FIXME: Extract the records */ + scanned += recsize; + rsp += recsize; - ctxt->cb(ctxt->user_data, recs, 0); + recs = sdp_list_append(recs, rec); + } while (scanned < size); +done: + ctxt->cb(ctxt->user_data, recs, err); search_context_cleanup(ctxt); } -- cgit From ea00a446dbacead62040dd2bd7e663774c205c04 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 10 Mar 2008 14:20:50 +0000 Subject: added new function to convert uuid to string(uuid128) --- common/glib-helper.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ common/glib-helper.h | 2 ++ 2 files changed, 52 insertions(+) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index be3f7a25..eef6ad8d 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -26,6 +26,7 @@ #endif #include +#include #include #include @@ -91,6 +92,7 @@ static void search_completed_cb(uint8_t type, uint16_t status, recs = sdp_list_append(recs, rec); } while (scanned < size); + done: ctxt->cb(ctxt->user_data, recs, err); @@ -207,3 +209,51 @@ int bt_discover_services(const bdaddr_t *src, const bdaddr_t *dst, return 0; } + +char *bt_uuid2string(uuid_t *uuid) +{ + gchar *str; + uuid_t uuid128; + unsigned int data0; + unsigned short data1; + unsigned short data2; + unsigned short data3; + unsigned int data4; + unsigned short data5; + + if (!uuid) + return NULL; + + switch (uuid->type) { + case SDP_UUID16: + sdp_uuid16_to_uuid128(&uuid128, uuid); + break; + case SDP_UUID32: + sdp_uuid32_to_uuid128(&uuid128, uuid); + break; + case SDP_UUID128: + memcpy(&uuid128, uuid, sizeof(uuid_t)); + break; + default: + /* Type of UUID unknown */ + return NULL; + } + + memcpy(&data0, &uuid128.value.uuid128.data[0], 4); + memcpy(&data1, &uuid128.value.uuid128.data[4], 2); + memcpy(&data2, &uuid128.value.uuid128.data[6], 2); + memcpy(&data3, &uuid128.value.uuid128.data[8], 2); + memcpy(&data4, &uuid128.value.uuid128.data[10], 4); + memcpy(&data5, &uuid128.value.uuid128.data[14], 2); + + str = g_try_malloc0(MAX_LEN_UUID_STR); + if (!str) + return NULL; + + sprintf(str, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x", + ntohl(data0), ntohs(data1), + ntohs(data2), ntohs(data3), + ntohl(data4), ntohs(data5)); + + return str; +} diff --git a/common/glib-helper.h b/common/glib-helper.h index 7426a6ad..e64eccca 100644 --- a/common/glib-helper.h +++ b/common/glib-helper.h @@ -26,3 +26,5 @@ typedef void (*bt_destroy_t) (gpointer user_data); int bt_discover_services(const bdaddr_t *src, const bdaddr_t *dst, bt_callback_t cb, void *user_data, bt_destroy_t destroy); + +gchar *bt_uuid2string(uuid_t *uuid); -- cgit From b583273d911d67eb202f3f367f18d4460913ad41 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 10 Mar 2008 20:01:52 +0000 Subject: added list2string function --- common/glib-helper.c | 16 ++++++++++++++++ common/glib-helper.h | 1 + 2 files changed, 17 insertions(+) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index eef6ad8d..001bb4fc 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -257,3 +257,19 @@ char *bt_uuid2string(uuid_t *uuid) return str; } + +gchar *bt_list2string(GSList *list) +{ + GSList *l; + gchar *str = NULL; + + if (!list) + return NULL; + + str = g_strdup((const gchar *) list->data); + + for (l = list->next; l; l = l->next) + str = g_strconcat(str, ", " , (const gchar *) l->data, NULL); + + return str; +} diff --git a/common/glib-helper.h b/common/glib-helper.h index e64eccca..7cfdc5dc 100644 --- a/common/glib-helper.h +++ b/common/glib-helper.h @@ -28,3 +28,4 @@ int bt_discover_services(const bdaddr_t *src, const bdaddr_t *dst, bt_callback_t cb, void *user_data, bt_destroy_t destroy); gchar *bt_uuid2string(uuid_t *uuid); +gchar *bt_list2string(GSList *list); -- cgit From 7addabc5e7dab0b368d1c947b11fa56d30893575 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 10 Mar 2008 20:10:03 +0000 Subject: list2string: use space as uuid separator --- common/glib-helper.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index 001bb4fc..bed506c3 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -268,8 +268,9 @@ gchar *bt_list2string(GSList *list) str = g_strdup((const gchar *) list->data); + /* FIXME: eglib doesn't support g_strconcat */ for (l = list->next; l; l = l->next) - str = g_strconcat(str, ", " , (const gchar *) l->data, NULL); + str = g_strconcat(str, " " , (const gchar *) l->data, NULL); return str; } -- cgit From b0566c457e956e03ae5ff3fe4ae15a9176b0ae24 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 10 Mar 2008 20:48:10 +0000 Subject: bt_list2string: fixed memory leak --- common/glib-helper.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index bed506c3..cb8f35c4 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -261,7 +261,7 @@ char *bt_uuid2string(uuid_t *uuid) gchar *bt_list2string(GSList *list) { GSList *l; - gchar *str = NULL; + gchar *str, *tmp; if (!list) return NULL; @@ -269,8 +269,11 @@ gchar *bt_list2string(GSList *list) str = g_strdup((const gchar *) list->data); /* FIXME: eglib doesn't support g_strconcat */ - for (l = list->next; l; l = l->next) - str = g_strconcat(str, " " , (const gchar *) l->data, NULL); + for (l = list->next; l; l = l->next) { + tmp = g_strconcat(str, " " , (const gchar *) l->data, NULL); + g_free(str); + str = tmp; + } return str; } -- cgit From 2c52650872bdeede320c4192bc0ac06c029f2732 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 11 Mar 2008 19:29:12 +0000 Subject: added bt_string2list function --- common/glib-helper.c | 24 ++++++++++++++++++++++++ common/glib-helper.h | 1 + 2 files changed, 25 insertions(+) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index cb8f35c4..771b9d76 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -277,3 +277,27 @@ gchar *bt_list2string(GSList *list) return str; } + +GSList *bt_string2list(const gchar *str) +{ + GSList *l = NULL; + gchar **uuids; + int i = 0; + + if (!str) + return NULL; + + /* FIXME: eglib doesn't support g_strsplit */ + uuids = g_strsplit(str, " ", 0); + if (!uuids) + return NULL; + + while (uuids[i]) { + l = g_slist_append(l, uuids[i]); + i++; + } + + g_free(uuids); + + return l; +} diff --git a/common/glib-helper.h b/common/glib-helper.h index 7cfdc5dc..ed724af6 100644 --- a/common/glib-helper.h +++ b/common/glib-helper.h @@ -29,3 +29,4 @@ int bt_discover_services(const bdaddr_t *src, const bdaddr_t *dst, gchar *bt_uuid2string(uuid_t *uuid); gchar *bt_list2string(GSList *list); +GSList *bt_string2list(const gchar *str); -- cgit From ba93fb91ea81a35be0834ac395650e020a6b3fd3 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 11 Mar 2008 21:49:57 +0000 Subject: Added array support for dict --- common/dbus-helper.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index 67dd91ed..cf68d82f 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -415,11 +415,17 @@ dbus_bool_t dbus_connection_unregister_interface(DBusConnection *connection, return TRUE; } +static void append_array_item_string(const char *val, DBusMessageIter *iter) +{ + dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &val); +} + void dbus_message_iter_append_dict_entry(DBusMessageIter *dict, const char *key, int type, void *val) { DBusMessageIter entry; DBusMessageIter value; + DBusMessageIter array; char *sig; dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, NULL, &entry); @@ -442,6 +448,9 @@ void dbus_message_iter_append_dict_entry(DBusMessageIter *dict, case DBUS_TYPE_BOOLEAN: sig = DBUS_TYPE_BOOLEAN_AS_STRING; break; + case DBUS_TYPE_ARRAY: + sig = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING; + break; default: sig = DBUS_TYPE_VARIANT_AS_STRING; break; @@ -449,7 +458,15 @@ void dbus_message_iter_append_dict_entry(DBusMessageIter *dict, dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, sig, &value); - dbus_message_iter_append_basic(&value, type, val); + if (type == DBUS_TYPE_ARRAY) { + dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY, + DBUS_TYPE_STRING_AS_STRING, &array); + g_slist_foreach((GSList*) val, (GFunc) append_array_item_string, + &array); + + dbus_message_iter_close_container(&value, &array); + } else + dbus_message_iter_append_basic(&value, type, val); dbus_message_iter_close_container(&entry, &value); -- cgit From fb9cc5a68f4d046b88e3bc065c680b5e35202550 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 12 Mar 2008 13:35:30 +0000 Subject: Introduce dbus_message_iter_append_variant to libhelper. --- common/dbus-helper.c | 28 +++++++++++++++++----------- common/dbus-helper.h | 1 + 2 files changed, 18 insertions(+), 11 deletions(-) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index cf68d82f..6fa90ff1 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -420,18 +420,12 @@ static void append_array_item_string(const char *val, DBusMessageIter *iter) dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &val); } -void dbus_message_iter_append_dict_entry(DBusMessageIter *dict, - const char *key, int type, void *val) +void dbus_message_iter_append_variant(DBusMessageIter *iter, int type, void *val) { - DBusMessageIter entry; DBusMessageIter value; DBusMessageIter array; char *sig; - dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, NULL, &entry); - - dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key); - switch (type) { case DBUS_TYPE_STRING: sig = DBUS_TYPE_STRING_AS_STRING; @@ -452,11 +446,11 @@ void dbus_message_iter_append_dict_entry(DBusMessageIter *dict, sig = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING; break; default: - sig = DBUS_TYPE_VARIANT_AS_STRING; - break; + error("Could not append variant with type %d", type); + return; } - dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, sig, &value); + dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, sig, &value); if (type == DBUS_TYPE_ARRAY) { dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY, @@ -468,7 +462,19 @@ void dbus_message_iter_append_dict_entry(DBusMessageIter *dict, } else dbus_message_iter_append_basic(&value, type, val); - dbus_message_iter_close_container(&entry, &value); + dbus_message_iter_close_container(iter, &value); +} + +void dbus_message_iter_append_dict_entry(DBusMessageIter *dict, + const char *key, int type, void *val) +{ + DBusMessageIter entry; + + dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, NULL, &entry); + + dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key); + + dbus_message_iter_append_variant(&entry, type, val); dbus_message_iter_close_container(dict, &entry); } diff --git a/common/dbus-helper.h b/common/dbus-helper.h index 62810260..e5db24ba 100644 --- a/common/dbus-helper.h +++ b/common/dbus-helper.h @@ -70,6 +70,7 @@ dbus_bool_t dbus_connection_register_interface(DBusConnection *connection, dbus_bool_t dbus_connection_unregister_interface(DBusConnection *connection, const char *path, const char *name); +void dbus_message_iter_append_variant(DBusMessageIter *iter, int type, void *val); void dbus_message_iter_append_dict_entry(DBusMessageIter *dict, const char *key, int type, void *val); -- cgit From cf826d7c14f2587e96815dc714739be161e98d80 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 12 Mar 2008 19:49:15 +0000 Subject: Introduce dbus_connection_emit_property_changed. --- common/dbus-helper.c | 28 ++++++++++++++++++++++++++++ common/dbus-helper.h | 5 +++++ 2 files changed, 33 insertions(+) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index 6fa90ff1..aacae487 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -560,3 +560,31 @@ dbus_bool_t dbus_connection_emit_signal(DBusConnection *conn, const char *path, return ret; } +dbus_bool_t dbus_connection_emit_property_changed(DBusConnection *conn, + const char *path, + const char *interface, + const char *name, + int type, void *value) +{ + DBusMessage *signal; + DBusMessageIter iter; + gboolean ret; + + signal = dbus_message_new_signal(path, interface, "PropertyChanged"); + + if (!signal) { + error("Unable to allocate new %s.PropertyChanged signal", + interface); + return FALSE; + } + + dbus_message_iter_init_append(signal, &iter); + + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name); + dbus_message_iter_append_variant(&iter, type, value); + + ret = dbus_connection_send(conn, signal, NULL); + + dbus_message_unref(signal); + return ret; +} diff --git a/common/dbus-helper.h b/common/dbus-helper.h index e5db24ba..b95d79c4 100644 --- a/common/dbus-helper.h +++ b/common/dbus-helper.h @@ -84,3 +84,8 @@ dbus_bool_t dbus_connection_emit_signal_valist(DBusConnection *conn, const char *name, int first, va_list var_args); +dbus_bool_t dbus_connection_emit_property_changed(DBusConnection *conn, + const char *path, + const char *interface, + const char *name, + int type, void *value); -- cgit From dfad08e334136022c3918d6247823e7a79ca899f Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 13 Mar 2008 16:57:12 +0000 Subject: Move error_unknown_method to libhelper. --- common/error.c | 21 +++++++++++++++++++++ common/error.h | 1 + 2 files changed, 22 insertions(+) (limited to 'common') diff --git a/common/error.c b/common/error.c index daabe48d..58999393 100644 --- a/common/error.c +++ b/common/error.c @@ -27,6 +27,7 @@ #include #endif +#include #include #include @@ -240,3 +241,23 @@ DBusHandlerResult error_common_reply(DBusConnection *conn, DBusMessage *msg, return dbus_connection_send_and_unref(conn, derr); } + +/** + org.bluez.Error.UnknownMethod: + + Used in experimental code. +*/ +DBusHandlerResult error_unknown_method(DBusConnection *conn, DBusMessage *msg) +{ + char error[128]; + const char *signature = dbus_message_get_signature(msg); + const char *method = dbus_message_get_member(msg); + const char *interface = dbus_message_get_interface(msg); + + snprintf(error, 128, "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist", + method, signature, interface); + + return send_message_and_unref(conn, + dbus_message_new_error(msg, ERROR_INTERFACE ".UnknownMethod", + error)); +} diff --git a/common/error.h b/common/error.h index 03d0c182..44b6f417 100644 --- a/common/error.h +++ b/common/error.h @@ -74,3 +74,4 @@ DBusHandlerResult error_failed_errno(DBusConnection *conn, DBusMessage *msg, DBusHandlerResult error_common_reply(DBusConnection *conn, DBusMessage *msg, const char *name, const char *descr); +DBusHandlerResult error_unknown_method(DBusConnection *conn, DBusMessage *msg); -- cgit From 095a8af653e9d5f7c2cf9c82c19f1281e8ad8b92 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 13 Mar 2008 22:20:54 +0000 Subject: Introduce dbus_message_iter_append_dict and dbus_message_iter_append_dict_valist. --- common/dbus-helper.c | 35 +++++++++++++++++++++++++++++++++++ common/dbus-helper.h | 6 +++++- 2 files changed, 40 insertions(+), 1 deletion(-) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index aacae487..003d9837 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -479,6 +479,41 @@ void dbus_message_iter_append_dict_entry(DBusMessageIter *dict, dbus_message_iter_close_container(dict, &entry); } +void dbus_message_iter_append_dict_valist(DBusMessageIter *iter, + const char *first_key, + va_list var_args) +{ + DBusMessageIter dict; + const char *key; + int type; + void *val; + + dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); + + key = first_key; + while (key) { + type = va_arg(var_args, int); + val = va_arg(var_args, void *); + dbus_message_iter_append_dict_entry(&dict, key, type, val); + key = va_arg(var_args, char *); + } + + dbus_message_iter_close_container(iter, &dict); +} + +void dbus_message_iter_append_dict(DBusMessageIter *iter, + const char *first_key, ...) +{ + va_list var_args; + + va_start(var_args, first_key); + dbus_message_iter_append_dict_valist(iter, first_key, var_args); + va_end(var_args); +} + dbus_bool_t dbus_connection_emit_signal_valist(DBusConnection *conn, const char *path, const char *interface, diff --git a/common/dbus-helper.h b/common/dbus-helper.h index b95d79c4..57c3d09b 100644 --- a/common/dbus-helper.h +++ b/common/dbus-helper.h @@ -73,7 +73,11 @@ dbus_bool_t dbus_connection_unregister_interface(DBusConnection *connection, void dbus_message_iter_append_variant(DBusMessageIter *iter, int type, void *val); void dbus_message_iter_append_dict_entry(DBusMessageIter *dict, const char *key, int type, void *val); - +void dbus_message_iter_append_dict_valist(DBusMessageIter *iter, + const char *first_key, + va_list var_args); +void dbus_message_iter_append_dict(DBusMessageIter *iter, + const char *first_key, ...); dbus_bool_t dbus_connection_emit_signal(DBusConnection *conn, const char *path, const char *interface, const char *name, int first, ...); -- cgit From a89312e54979c0ee6cc82f50e423bcdafbe9df43 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 13 Mar 2008 22:27:22 +0000 Subject: Added new function to remove the listener based on integer identification --- common/dbus.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++------------ common/dbus.h | 4 +++- 2 files changed, 52 insertions(+), 13 deletions(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index 529caad3..e4008810 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -50,8 +50,7 @@ #define DISPATCH_TIMEOUT 0 -static int name_listener_initialized = 0; - +static guint listener_id = 0; static GSList *name_listeners = NULL; #ifndef HAVE_DBUS_GLIB @@ -81,6 +80,7 @@ struct disconnect_data { struct name_callback { name_cb_t func; void *user_data; + guint id; }; struct name_data { @@ -152,8 +152,8 @@ static void name_data_free(struct name_data *data) g_free(data); } -static int name_data_add(DBusConnection *connection, - const char *name, name_cb_t func, void *user_data) +static int name_data_add(DBusConnection *connection, const char *name, + name_cb_t func, void *user_data, guint id) { int first = 1; struct name_data *data = NULL; @@ -163,6 +163,7 @@ static int name_data_add(DBusConnection *connection, cb->func = func; cb->user_data = user_data; + cb->id = id; data = name_data_find(connection, name); if (data) { @@ -293,36 +294,36 @@ static DBusHandlerResult name_exit_filter(DBusConnection *connection, return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } -int name_listener_add(DBusConnection *connection, const char *name, +guint name_listener_add(DBusConnection *connection, const char *name, name_cb_t func, void *user_data) { int first; - if (!name_listener_initialized) { + if (!listener_id) { if (!dbus_connection_add_filter(connection, name_exit_filter, NULL, NULL)) { error("dbus_connection_add_filter() failed"); - return -1; + return 0; } - name_listener_initialized = 1; } - first = name_data_add(connection, name, func, user_data); + listener_id++; + first = name_data_add(connection, name, func, user_data, listener_id); /* The filter is already added if this is not the first callback * registration for the name */ if (!first) - return 0; + return listener_id; if (name) { debug("name_listener_add(%s)", name); if (!add_match(connection, name)) { name_data_remove(connection, name, func, user_data); - return -1; + return 0; } } - return 0; + return listener_id; } int name_listener_remove(DBusConnection *connection, const char *name, @@ -362,6 +363,42 @@ int name_listener_remove(DBusConnection *connection, const char *name, return 0; } +gboolean name_listener_id_remove(guint id) +{ + struct name_data *data; + struct name_callback *cb; + GSList *ldata, *lcb; + + for (ldata = name_listeners; ldata; ldata = ldata->next) { + data = ldata->data; + for (lcb = data->callbacks; lcb; lcb = lcb->next) { + cb = lcb->data; + if (cb->id == id) + goto remove; + } + } + + return FALSE; + +remove: + data->callbacks = g_slist_remove(data->callbacks, cb); + g_free(cb); + + /* Don't remove the filter if other callbacks exist */ + if (data->callbacks) + return TRUE; + + if (data->name) { + if (!remove_match(data->connection, data->name)) + return FALSE; + } + + name_listeners = g_slist_remove(name_listeners, data); + name_data_free(data); + + return TRUE; +} + int name_listener_indicate_disconnect(DBusConnection *connection) { struct name_data *data; diff --git a/common/dbus.h b/common/dbus.h index b65a83c9..b8223059 100644 --- a/common/dbus.h +++ b/common/dbus.h @@ -25,6 +25,7 @@ #define __H_BLUEZ_DBUS_H__ #include +#include void setup_dbus_server_with_main_loop(DBusServer *server); void setup_dbus_with_main_loop(DBusConnection *conn); @@ -42,10 +43,11 @@ DBusHandlerResult simple_introspect(DBusConnection *conn, typedef void (*name_cb_t)(const char *name, void *user_data); -int name_listener_add(DBusConnection *connection, const char *name, +guint name_listener_add(DBusConnection *connection, const char *name, name_cb_t func, void *user_data); int name_listener_remove(DBusConnection *connection, const char *name, name_cb_t func, void *user_data); +gboolean name_listener_id_remove(guint id); int name_listener_indicate_disconnect(DBusConnection *connection); dbus_bool_t dbus_bus_get_unix_process_id(DBusConnection *conn, const char *name, -- cgit From e9a2d42cf67f70430a563bd23d24774cdb15b97b Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 14 Mar 2008 19:34:01 +0000 Subject: Add some missing basic types to dbus_message_iter_append_variant. --- common/dbus-helper.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index 003d9837..70528d52 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -436,6 +436,12 @@ void dbus_message_iter_append_variant(DBusMessageIter *iter, int type, void *val case DBUS_TYPE_INT16: sig = DBUS_TYPE_INT16_AS_STRING; break; + case DBUS_TYPE_UINT16: + sig = DBUS_TYPE_UINT16_AS_STRING; + break; + case DBUS_TYPE_INT32: + sig = DBUS_TYPE_INT32_AS_STRING; + break; case DBUS_TYPE_UINT32: sig = DBUS_TYPE_UINT32_AS_STRING; break; -- cgit From 3ca0c59a0f86f9d4aaf6b6db167a3fd390dc0e4f Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 20 Mar 2008 02:22:20 +0000 Subject: Make dbus_connection_emit_property_changed to perform checks as dbus_connection_emit_signal_valist does. --- common/dbus-helper.c | 47 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 11 deletions(-) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index 70528d52..6c7946a8 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -520,20 +520,15 @@ void dbus_message_iter_append_dict(DBusMessageIter *iter, va_end(var_args); } -dbus_bool_t dbus_connection_emit_signal_valist(DBusConnection *conn, - const char *path, - const char *interface, - const char *name, - int first, - va_list var_args) +static gboolean check_signal(DBusConnection *conn, const char *path, + const char *interface, const char *name, + const char **args) { struct generic_data *data = NULL; struct interface_data *iface; DBusSignalVTable *sig_data; - DBusMessage *signal; - dbus_bool_t ret; - const char *signature, *args = NULL; + *args = NULL; if (!dbus_connection_get_object_path_data(conn, path, (void *) &data) || !data) { error("dbus_connection_emit_signal: path %s isn't registered", @@ -551,16 +546,33 @@ dbus_bool_t dbus_connection_emit_signal_valist(DBusConnection *conn, for (sig_data = iface->signals; sig_data && sig_data->name; sig_data++) { if (!strcmp(sig_data->name, name)) { - args = sig_data->signature; + *args = sig_data->signature; break; } } - if (!args) { + if (!*args) { error("No signal named %s on interface %s", name, interface); return FALSE; } + return TRUE; +} + +dbus_bool_t dbus_connection_emit_signal_valist(DBusConnection *conn, + const char *path, + const char *interface, + const char *name, + int first, + va_list var_args) +{ + DBusMessage *signal; + dbus_bool_t ret; + const char *signature, *args; + + if (!check_signal(conn, path, interface, name, &args)) + return FALSE; + signal = dbus_message_new_signal(path, interface, name); if (!signal) { error("Unable to allocate new %s.%s signal", interface, name); @@ -610,6 +622,10 @@ dbus_bool_t dbus_connection_emit_property_changed(DBusConnection *conn, DBusMessage *signal; DBusMessageIter iter; gboolean ret; + const char *signature, *args; + + if (!check_signal(conn, path, interface, "PropertyChanged", &args)) + return FALSE; signal = dbus_message_new_signal(path, interface, "PropertyChanged"); @@ -624,8 +640,17 @@ dbus_bool_t dbus_connection_emit_property_changed(DBusConnection *conn, dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name); dbus_message_iter_append_variant(&iter, type, value); + signature = dbus_message_get_signature(signal); + if (strcmp(args, signature) != 0) { + error("%s.%s: expected signature'%s' but got '%s'", + interface, name, args, signature); + ret = FALSE; + goto fail; + } + ret = dbus_connection_send(conn, signal, NULL); +fail: dbus_message_unref(signal); return ret; } -- cgit From 41e3ea17c0017dd1b238adaf69d75433ebdc9810 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 22 Mar 2008 14:20:47 +0000 Subject: Make the external service register function asynchron --- common/dbus.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index e4008810..aef88c7c 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -878,10 +878,22 @@ int set_nonblocking(int fd) return 0; } +static void external_reply(DBusPendingCall *call, void *user_data) +{ + DBusMessage *reply; + + debug("Service register reply"); + + reply = dbus_pending_call_steal_reply(call); + + dbus_message_unref(reply); +} + void register_external_service(DBusConnection *conn, const char *identifier, const char *name, const char *description) { - DBusMessage *msg, *reply; + DBusMessage *msg; + DBusPendingCall *call; info("Registering service"); @@ -896,14 +908,13 @@ void register_external_service(DBusConnection *conn, const char *identifier, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &description, DBUS_TYPE_INVALID); - reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, NULL); - if (!reply) { + if (dbus_connection_send_with_reply(conn, msg, &call, -1) == FALSE) { error("Can't register service"); + dbus_message_unref(msg); return; } - dbus_message_unref(msg); - dbus_message_unref(reply); + dbus_pending_call_set_notify(call, external_reply, NULL, NULL); - dbus_connection_flush(conn); + dbus_message_unref(msg); } -- cgit From 769c4b021665a26c9a6c20457ef9b7ded54c8ad6 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Mon, 24 Mar 2008 18:04:12 +0000 Subject: Fix dbus_message_iter_append_variant to use dbus string array format (char **) instead GSList. --- common/dbus-helper.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index 6c7946a8..e6211824 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -415,11 +415,6 @@ dbus_bool_t dbus_connection_unregister_interface(DBusConnection *connection, return TRUE; } -static void append_array_item_string(const char *val, DBusMessageIter *iter) -{ - dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &val); -} - void dbus_message_iter_append_variant(DBusMessageIter *iter, int type, void *val) { DBusMessageIter value; @@ -459,10 +454,15 @@ void dbus_message_iter_append_variant(DBusMessageIter *iter, int type, void *val dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, sig, &value); if (type == DBUS_TYPE_ARRAY) { + int i; + const char ***str_array = val; + dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING, &array); - g_slist_foreach((GSList*) val, (GFunc) append_array_item_string, - &array); + + for (i = 0; (*str_array)[i]; i++) + dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, + &((*str_array)[i])); dbus_message_iter_close_container(&value, &array); } else -- cgit From 6713eab44b740778179e5740afb43d457c3afbc2 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 1 Apr 2008 12:46:15 +0000 Subject: Removed pending call memory leak for external service registration --- common/dbus.c | 1 + 1 file changed, 1 insertion(+) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index aef88c7c..53e1046b 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -915,6 +915,7 @@ void register_external_service(DBusConnection *conn, const char *identifier, } dbus_pending_call_set_notify(call, external_reply, NULL, NULL); + dbus_pending_call_unref(call); dbus_message_unref(msg); } -- cgit From ec96a4be11db022bd8d2b403beb7ca245c5d1ebc Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 18 Apr 2008 17:41:06 +0000 Subject: Introduce bt_search_service and bt_rfcomm_connect. --- common/glib-helper.c | 206 ++++++++++++++++++++++++++++++++++++++++++++++----- common/glib-helper.h | 9 +++ 2 files changed, 196 insertions(+), 19 deletions(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index 771b9d76..b92a1ff4 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -26,10 +26,13 @@ #endif #include +#include #include +#include #include #include +#include #include #include @@ -37,6 +40,12 @@ #include "glib-helper.h" +struct io_context { + GIOChannel *io; + bt_io_callback_t cb; + gpointer user_data; +}; + struct search_context { bdaddr_t src; bdaddr_t dst; @@ -44,6 +53,7 @@ struct search_context { bt_callback_t cb; bt_destroy_t destroy; gpointer user_data; + uuid_t uuid; }; static void search_context_cleanup(struct search_context *ctxt) @@ -94,7 +104,8 @@ static void search_completed_cb(uint8_t type, uint16_t status, } while (scanned < size); done: - ctxt->cb(ctxt->user_data, recs, err); + if (ctxt->cb) + ctxt->cb(ctxt->user_data, recs, err); search_context_cleanup(ctxt); } @@ -117,7 +128,8 @@ static gboolean search_process_cb(GIOChannel *chan, failed: if (err) { - ctxt->cb(ctxt->user_data, NULL, -err); + if (ctxt->cb) + ctxt->cb(ctxt->user_data, NULL, -err); search_context_cleanup(ctxt); } @@ -129,7 +141,6 @@ static gboolean connect_watch(GIOChannel *chan, GIOCondition cond, gpointer user struct search_context *ctxt = user_data; sdp_list_t *search, *attrids; uint32_t range = 0x0000ffff; - uuid_t uuid; socklen_t len; int sk, err = 0; @@ -149,8 +160,7 @@ static gboolean connect_watch(GIOChannel *chan, GIOCondition cond, gpointer user goto failed; } - sdp_uuid16_create(&uuid, PUBLIC_BROWSE_GROUP); - search = sdp_list_append(NULL, &uuid); + search = sdp_list_append(NULL, &ctxt->uuid); attrids = sdp_list_append(NULL, &range); if (sdp_service_search_attr_async(ctxt->session, search, SDP_ATTR_REQ_RANGE, attrids) < 0) { @@ -169,47 +179,77 @@ static gboolean connect_watch(GIOChannel *chan, GIOCondition cond, gpointer user return FALSE; failed: - ctxt->cb(ctxt->user_data, NULL, -err); + if (ctxt->cb) + ctxt->cb(ctxt->user_data, NULL, -err); search_context_cleanup(ctxt); return FALSE; } -int bt_discover_services(const bdaddr_t *src, const bdaddr_t *dst, - bt_callback_t cb, void *user_data, bt_destroy_t destroy) +static int create_search_context(struct search_context **ctxt, + const bdaddr_t *src, const bdaddr_t *dst, + uuid_t uuid) { - struct search_context *ctxt; sdp_session_t *s; GIOChannel *chan; - if (!cb) + if (!ctxt) return -EINVAL; s = sdp_connect(src, dst, SDP_NON_BLOCKING); if (!s) return -errno; - ctxt = g_try_malloc0(sizeof(struct search_context)); - if (!ctxt) { + *ctxt = g_try_malloc0(sizeof(struct search_context)); + if (!*ctxt) { sdp_close(s); return -ENOMEM; } - bacpy(&ctxt->src, src); - bacpy(&ctxt->dst, dst); - ctxt->session = s; - ctxt->cb = cb; - ctxt->destroy = destroy; - ctxt->user_data = user_data; + bacpy(&(*ctxt)->src, src); + bacpy(&(*ctxt)->dst, dst); + (*ctxt)->session = s; + (*ctxt)->uuid = uuid; chan = g_io_channel_unix_new(sdp_get_socket(s)); g_io_add_watch(chan, G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL, - connect_watch, ctxt); + connect_watch, *ctxt); g_io_channel_unref(chan); return 0; } +int bt_search_service(const bdaddr_t *src, const bdaddr_t *dst, + uuid_t uuid, bt_callback_t cb, void *user_data, + bt_destroy_t destroy) +{ + struct search_context *ctxt; + int err; + + if (!cb) + return -EINVAL; + + err = create_search_context(&ctxt, src, dst, uuid); + if (err < 0) + return err; + + ctxt->cb = cb; + ctxt->destroy = destroy; + ctxt->user_data = user_data; + + return 0; +} + +int bt_discover_services(const bdaddr_t *src, const bdaddr_t *dst, + bt_callback_t cb, void *user_data, bt_destroy_t destroy) +{ + uuid_t uuid; + + sdp_uuid16_create(&uuid, PUBLIC_BROWSE_GROUP); + + return bt_search_service(src, dst, uuid, cb, user_data, destroy); +} + char *bt_uuid2string(uuid_t *uuid) { gchar *str; @@ -301,3 +341,131 @@ GSList *bt_string2list(const gchar *str) return l; } + +static gboolean rfcomm_connect_cb(GIOChannel *io, GIOCondition cond, + struct io_context *io_ctxt) +{ + int sk, err, ret; + socklen_t len; + + if (cond & G_IO_NVAL) + return FALSE; + + sk = g_io_channel_unix_get_fd(io); + + len = sizeof(ret); + if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) { + err = -errno; + goto done; + } + + if (ret != 0) + err = -ret; + + io_ctxt->io = NULL; + +done: + if (io_ctxt->cb) + io_ctxt->cb(io, err, io_ctxt->user_data); + if (io_ctxt->io) { + g_io_channel_close(io_ctxt->io); + g_io_channel_unref(io_ctxt->io); + } + g_free(io_ctxt); + + return FALSE; +} + +static int rfcomm_connect(struct io_context *io_ctxt, const bdaddr_t *src, + const bdaddr_t *dst, int channel) +{ + struct sockaddr_rc addr; + int sk, err; + + sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); + if (sk < 0) + return -errno; + + io_ctxt->io = g_io_channel_unix_new(sk); + if (!io_ctxt->io) + return -ENOMEM; + + memset(&addr, 0, sizeof(addr)); + addr.rc_family = AF_BLUETOOTH; + bacpy(&addr.rc_bdaddr, src); + addr.rc_channel = 0; + + err = bind(sk, (struct sockaddr *) &addr, sizeof(addr)); + if (err < 0) + return err; + + if (g_io_channel_set_flags(io_ctxt->io, G_IO_FLAG_NONBLOCK, NULL) != + G_IO_STATUS_NORMAL) + return -EPERM; + + memset(&addr, 0, sizeof(addr)); + addr.rc_family = AF_BLUETOOTH; + bacpy(&addr.rc_bdaddr, dst); + addr.rc_channel = channel; + + err = connect(sk, (struct sockaddr *) &addr, sizeof(addr)); + + if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) + return err; + + g_io_add_watch(io_ctxt->io, G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL, + (GIOFunc) rfcomm_connect_cb, io_ctxt); + + return 0; +} + +static int create_io_context(struct io_context **io_ctxt, bt_io_callback_t cb, + void *user_data) +{ + *io_ctxt = g_try_malloc0(sizeof(struct search_context)); + if (!*io_ctxt) + return -ENOMEM; + + (*io_ctxt)->cb = cb; + (*io_ctxt)->user_data = user_data; + + return 0; +} + +int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, + sdp_record_t *record, bt_io_callback_t cb, + void *user_data) +{ + struct io_context *io_ctxt; + sdp_list_t *protos; + int err, channel = -1; + + if (!record) + return -EINVAL; + + if (!sdp_get_access_protos(record, &protos)) { + channel = sdp_get_proto_port(protos, RFCOMM_UUID); + sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, + NULL); + sdp_list_free(protos, NULL); + } + + if (channel < 0) + return -EINVAL; + + err = create_io_context(&io_ctxt, cb, user_data); + if (err < 0) + return err; + + err = rfcomm_connect(io_ctxt, src, dst, channel); + if (err < 0) { + if (io_ctxt->io) { + g_io_channel_close(io_ctxt->io); + g_io_channel_unref(io_ctxt->io); + } + g_free(io_ctxt); + return err; + } + + return 0; +} diff --git a/common/glib-helper.h b/common/glib-helper.h index ed724af6..a6939fd1 100644 --- a/common/glib-helper.h +++ b/common/glib-helper.h @@ -21,12 +21,21 @@ * */ +typedef void (*bt_io_callback_t) (GIOChannel *io, int err, gpointer user_data); typedef void (*bt_callback_t) (gpointer user_data, sdp_list_t *recs, int err); typedef void (*bt_destroy_t) (gpointer user_data); int bt_discover_services(const bdaddr_t *src, const bdaddr_t *dst, bt_callback_t cb, void *user_data, bt_destroy_t destroy); +int bt_search_service(const bdaddr_t *src, const bdaddr_t *dst, + uuid_t uuid, bt_callback_t cb, void *user_data, + bt_destroy_t destroy); + gchar *bt_uuid2string(uuid_t *uuid); gchar *bt_list2string(GSList *list); GSList *bt_string2list(const gchar *str); + +int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, + sdp_record_t *record, bt_io_callback_t cb, + void *user_data); -- cgit From 56eba24d02bc70648c9f7da5a13ded03bccf8a2f Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 22 Apr 2008 14:50:37 +0000 Subject: Introduce bt_l2cap_connect. --- common/glib-helper.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++--- common/glib-helper.h | 2 ++ 2 files changed, 73 insertions(+), 4 deletions(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index b92a1ff4..e314d9e9 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -342,7 +343,7 @@ GSList *bt_string2list(const gchar *str) return l; } -static gboolean rfcomm_connect_cb(GIOChannel *io, GIOCondition cond, +static gboolean connect_cb(GIOChannel *io, GIOCondition cond, struct io_context *io_ctxt) { int sk, err, ret; @@ -359,8 +360,10 @@ static gboolean rfcomm_connect_cb(GIOChannel *io, GIOCondition cond, goto done; } - if (ret != 0) + if (ret != 0) { err = -ret; + goto done; + } io_ctxt->io = NULL; @@ -376,6 +379,48 @@ done: return FALSE; } +static int l2cap_connect(struct io_context *io_ctxt, const bdaddr_t *src, + const bdaddr_t *dst, uint16_t psm) +{ + struct sockaddr_l2 l2a; + int sk, err; + + sk = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); + if (sk < 0) + return -errno; + + io_ctxt->io = g_io_channel_unix_new(sk); + if (!io_ctxt->io) + return -ENOMEM; + + memset(&l2a, 0, sizeof(l2a)); + l2a.l2_family = AF_BLUETOOTH; + bacpy(&l2a.l2_bdaddr, src); + + err = bind(sk, (struct sockaddr *) &l2a, sizeof(l2a)); + if (err < 0) + return err; + + if (g_io_channel_set_flags(io_ctxt->io, G_IO_FLAG_NONBLOCK, NULL) != + G_IO_STATUS_NORMAL) + return -EPERM; + + memset(&l2a, 0, sizeof(l2a)); + l2a.l2_family = AF_BLUETOOTH; + bacpy(&l2a.l2_bdaddr, dst); + l2a.l2_psm = htobs(psm); + + err = connect(sk, (struct sockaddr *) &l2a, sizeof(l2a)); + + if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) + return err; + + g_io_add_watch(io_ctxt->io, G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL, + (GIOFunc) connect_cb, io_ctxt); + + return 0; +} + static int rfcomm_connect(struct io_context *io_ctxt, const bdaddr_t *src, const bdaddr_t *dst, int channel) { @@ -393,7 +438,6 @@ static int rfcomm_connect(struct io_context *io_ctxt, const bdaddr_t *src, memset(&addr, 0, sizeof(addr)); addr.rc_family = AF_BLUETOOTH; bacpy(&addr.rc_bdaddr, src); - addr.rc_channel = 0; err = bind(sk, (struct sockaddr *) &addr, sizeof(addr)); if (err < 0) @@ -414,7 +458,7 @@ static int rfcomm_connect(struct io_context *io_ctxt, const bdaddr_t *src, return err; g_io_add_watch(io_ctxt->io, G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL, - (GIOFunc) rfcomm_connect_cb, io_ctxt); + (GIOFunc) connect_cb, io_ctxt); return 0; } @@ -469,3 +513,26 @@ int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, return 0; } + +int bt_l2cap_connect(const bdaddr_t *src, const bdaddr_t *dst, + uint16_t psm, bt_io_callback_t cb, void *user_data) +{ + struct io_context *io_ctxt; + int err; + + err = create_io_context(&io_ctxt, cb, user_data); + if (err < 0) + return err; + + err = l2cap_connect(io_ctxt, src, dst, psm); + if (err < 0) { + if (io_ctxt->io) { + g_io_channel_close(io_ctxt->io); + g_io_channel_unref(io_ctxt->io); + } + g_free(io_ctxt); + return err; + } + + return 0; +} diff --git a/common/glib-helper.h b/common/glib-helper.h index a6939fd1..d356290f 100644 --- a/common/glib-helper.h +++ b/common/glib-helper.h @@ -39,3 +39,5 @@ GSList *bt_string2list(const gchar *str); int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, sdp_record_t *record, bt_io_callback_t cb, void *user_data); +int bt_l2cap_connect(const bdaddr_t *src, const bdaddr_t *dst, + uint16_t psm, bt_io_callback_t cb, void *user_data); -- cgit From 0a46bec1995f0b707080214bde9132cb6b69e162 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 23 Apr 2008 18:12:25 +0000 Subject: Introduce bt_sco_connect and some other fixes. --- common/glib-helper.c | 139 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 99 insertions(+), 40 deletions(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index e314d9e9..23271fa2 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -26,6 +26,7 @@ #endif #include +#include #include #include #include @@ -34,6 +35,7 @@ #include #include #include +#include #include #include @@ -379,6 +381,61 @@ done: return FALSE; } +static int transport_connect(struct io_context *io_ctxt, int fd, + struct sockaddr *addr, socklen_t addrlen) +{ + int err; + + io_ctxt->io = g_io_channel_unix_new(fd); + if (!io_ctxt->io) + return -ENOMEM; + + err = g_io_channel_set_flags(io_ctxt->io, G_IO_FLAG_NONBLOCK, NULL); + if (err != G_IO_STATUS_NORMAL) + return -EPERM; + + err = connect(fd, addr, addrlen); + if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) + return -errno; + + g_io_add_watch(io_ctxt->io, G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL, + (GIOFunc) connect_cb, io_ctxt); + + return 0; +} + +static int sco_connect(struct io_context *io_ctxt, const bdaddr_t *src, + const bdaddr_t *dst) +{ + struct sockaddr_sco addr; + int sk, err; + + sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO); + if (sk < 0) + return -errno; + + memset(&addr, 0, sizeof(addr)); + addr.sco_family = AF_BLUETOOTH; + bacpy(&addr.sco_bdaddr, src); + + err = bind(sk, (struct sockaddr *) &addr, sizeof(addr)); + if (err < 0) + return -errno; + + memset(&addr, 0, sizeof(addr)); + addr.sco_family = AF_BLUETOOTH; + bacpy(&addr.sco_bdaddr, dst); + + err = transport_connect(io_ctxt, sk, (struct sockaddr *) &addr, + sizeof(addr)); + if (err < 0) { + close(sk); + return err; + } + + return 0; +} + static int l2cap_connect(struct io_context *io_ctxt, const bdaddr_t *src, const bdaddr_t *dst, uint16_t psm) { @@ -389,34 +446,25 @@ static int l2cap_connect(struct io_context *io_ctxt, const bdaddr_t *src, if (sk < 0) return -errno; - io_ctxt->io = g_io_channel_unix_new(sk); - if (!io_ctxt->io) - return -ENOMEM; - memset(&l2a, 0, sizeof(l2a)); l2a.l2_family = AF_BLUETOOTH; bacpy(&l2a.l2_bdaddr, src); err = bind(sk, (struct sockaddr *) &l2a, sizeof(l2a)); if (err < 0) - return err; - - if (g_io_channel_set_flags(io_ctxt->io, G_IO_FLAG_NONBLOCK, NULL) != - G_IO_STATUS_NORMAL) - return -EPERM; + return -errno; memset(&l2a, 0, sizeof(l2a)); l2a.l2_family = AF_BLUETOOTH; bacpy(&l2a.l2_bdaddr, dst); l2a.l2_psm = htobs(psm); - err = connect(sk, (struct sockaddr *) &l2a, sizeof(l2a)); - - if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) + err = transport_connect(io_ctxt, sk, (struct sockaddr *) &l2a, + sizeof(l2a)); + if (err < 0) { + close(sk); return err; - - g_io_add_watch(io_ctxt->io, G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL, - (GIOFunc) connect_cb, io_ctxt); + } return 0; } @@ -431,34 +479,25 @@ static int rfcomm_connect(struct io_context *io_ctxt, const bdaddr_t *src, if (sk < 0) return -errno; - io_ctxt->io = g_io_channel_unix_new(sk); - if (!io_ctxt->io) - return -ENOMEM; - memset(&addr, 0, sizeof(addr)); addr.rc_family = AF_BLUETOOTH; bacpy(&addr.rc_bdaddr, src); err = bind(sk, (struct sockaddr *) &addr, sizeof(addr)); if (err < 0) - return err; - - if (g_io_channel_set_flags(io_ctxt->io, G_IO_FLAG_NONBLOCK, NULL) != - G_IO_STATUS_NORMAL) - return -EPERM; + return -errno; memset(&addr, 0, sizeof(addr)); addr.rc_family = AF_BLUETOOTH; bacpy(&addr.rc_bdaddr, dst); addr.rc_channel = channel; - err = connect(sk, (struct sockaddr *) &addr, sizeof(addr)); - - if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) + err = transport_connect(io_ctxt, sk, (struct sockaddr *) &addr, + sizeof(addr)); + if (err < 0) { + close(sk); return err; - - g_io_add_watch(io_ctxt->io, G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL, - (GIOFunc) connect_cb, io_ctxt); + } return 0; } @@ -476,6 +515,15 @@ static int create_io_context(struct io_context **io_ctxt, bt_io_callback_t cb, return 0; } +static void io_context_cleanup(struct io_context *io_ctxt) +{ + if (io_ctxt->io) { + g_io_channel_close(io_ctxt->io); + g_io_channel_unref(io_ctxt->io); + } + g_free(io_ctxt); +} + int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, sdp_record_t *record, bt_io_callback_t cb, void *user_data) @@ -503,11 +551,7 @@ int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, err = rfcomm_connect(io_ctxt, src, dst, channel); if (err < 0) { - if (io_ctxt->io) { - g_io_channel_close(io_ctxt->io); - g_io_channel_unref(io_ctxt->io); - } - g_free(io_ctxt); + io_context_cleanup(io_ctxt); return err; } @@ -526,11 +570,26 @@ int bt_l2cap_connect(const bdaddr_t *src, const bdaddr_t *dst, err = l2cap_connect(io_ctxt, src, dst, psm); if (err < 0) { - if (io_ctxt->io) { - g_io_channel_close(io_ctxt->io); - g_io_channel_unref(io_ctxt->io); - } - g_free(io_ctxt); + io_context_cleanup(io_ctxt); + return err; + } + + return 0; +} + +int bt_sco_connect(const bdaddr_t *src, const bdaddr_t *dst, + bt_io_callback_t cb, void *user_data) +{ + struct io_context *io_ctxt; + int err; + + err = create_io_context(&io_ctxt, cb, user_data); + if (err < 0) + return err; + + err = sco_connect(io_ctxt, src, dst); + if (err < 0) { + io_context_cleanup(io_ctxt); return err; } -- cgit From 5b9b4989612f0bee7d7b5574e78e760090bd2b7d Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 23 Apr 2008 20:19:04 +0000 Subject: Make bt_rfcomm_connect to take a channel instead of record and export bt_sco_connect. --- common/glib-helper.c | 21 +++------------------ common/glib-helper.h | 5 +++-- 2 files changed, 6 insertions(+), 20 deletions(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index 23271fa2..6eafa4f7 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -470,7 +470,7 @@ static int l2cap_connect(struct io_context *io_ctxt, const bdaddr_t *src, } static int rfcomm_connect(struct io_context *io_ctxt, const bdaddr_t *src, - const bdaddr_t *dst, int channel) + const bdaddr_t *dst, uint8_t channel) { struct sockaddr_rc addr; int sk, err; @@ -525,25 +525,10 @@ static void io_context_cleanup(struct io_context *io_ctxt) } int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, - sdp_record_t *record, bt_io_callback_t cb, - void *user_data) + uint8_t channel, bt_io_callback_t cb, void *user_data) { struct io_context *io_ctxt; - sdp_list_t *protos; - int err, channel = -1; - - if (!record) - return -EINVAL; - - if (!sdp_get_access_protos(record, &protos)) { - channel = sdp_get_proto_port(protos, RFCOMM_UUID); - sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, - NULL); - sdp_list_free(protos, NULL); - } - - if (channel < 0) - return -EINVAL; + int err; err = create_io_context(&io_ctxt, cb, user_data); if (err < 0) diff --git a/common/glib-helper.h b/common/glib-helper.h index d356290f..b51122ad 100644 --- a/common/glib-helper.h +++ b/common/glib-helper.h @@ -37,7 +37,8 @@ gchar *bt_list2string(GSList *list); GSList *bt_string2list(const gchar *str); int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, - sdp_record_t *record, bt_io_callback_t cb, - void *user_data); + uint8_t channel, bt_io_callback_t cb, void *user_data); int bt_l2cap_connect(const bdaddr_t *src, const bdaddr_t *dst, uint16_t psm, bt_io_callback_t cb, void *user_data); +int bt_sco_connect(const bdaddr_t *src, const bdaddr_t *dst, + bt_io_callback_t cb, void *user_data); -- cgit From 3a2024530dd736ece6f8b59db53bd8f67a755361 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 24 Apr 2008 14:56:40 +0000 Subject: Close socket on bind failure, fix callback user_data to be the last parameter and pass uuid refence. --- common/glib-helper.c | 26 ++++++++++++++++---------- common/glib-helper.h | 4 ++-- 2 files changed, 18 insertions(+), 12 deletions(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index 6eafa4f7..5e0d4cb3 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -108,7 +108,7 @@ static void search_completed_cb(uint8_t type, uint16_t status, done: if (ctxt->cb) - ctxt->cb(ctxt->user_data, recs, err); + ctxt->cb(recs, err, ctxt->user_data); search_context_cleanup(ctxt); } @@ -132,7 +132,7 @@ static gboolean search_process_cb(GIOChannel *chan, failed: if (err) { if (ctxt->cb) - ctxt->cb(ctxt->user_data, NULL, -err); + ctxt->cb(NULL, err, ctxt->user_data); search_context_cleanup(ctxt); } @@ -183,7 +183,7 @@ static gboolean connect_watch(GIOChannel *chan, GIOCondition cond, gpointer user failed: if (ctxt->cb) - ctxt->cb(ctxt->user_data, NULL, -err); + ctxt->cb(NULL, -err, ctxt->user_data); search_context_cleanup(ctxt); return FALSE; @@ -191,7 +191,7 @@ failed: static int create_search_context(struct search_context **ctxt, const bdaddr_t *src, const bdaddr_t *dst, - uuid_t uuid) + uuid_t *uuid) { sdp_session_t *s; GIOChannel *chan; @@ -212,7 +212,7 @@ static int create_search_context(struct search_context **ctxt, bacpy(&(*ctxt)->src, src); bacpy(&(*ctxt)->dst, dst); (*ctxt)->session = s; - (*ctxt)->uuid = uuid; + (*ctxt)->uuid = *uuid; chan = g_io_channel_unix_new(sdp_get_socket(s)); g_io_add_watch(chan, G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL, @@ -223,7 +223,7 @@ static int create_search_context(struct search_context **ctxt, } int bt_search_service(const bdaddr_t *src, const bdaddr_t *dst, - uuid_t uuid, bt_callback_t cb, void *user_data, + uuid_t *uuid, bt_callback_t cb, void *user_data, bt_destroy_t destroy) { struct search_context *ctxt; @@ -250,7 +250,7 @@ int bt_discover_services(const bdaddr_t *src, const bdaddr_t *dst, sdp_uuid16_create(&uuid, PUBLIC_BROWSE_GROUP); - return bt_search_service(src, dst, uuid, cb, user_data, destroy); + return bt_search_service(src, dst, &uuid, cb, user_data, destroy); } char *bt_uuid2string(uuid_t *uuid) @@ -419,8 +419,10 @@ static int sco_connect(struct io_context *io_ctxt, const bdaddr_t *src, bacpy(&addr.sco_bdaddr, src); err = bind(sk, (struct sockaddr *) &addr, sizeof(addr)); - if (err < 0) + if (err < 0) { + close(sk); return -errno; + } memset(&addr, 0, sizeof(addr)); addr.sco_family = AF_BLUETOOTH; @@ -451,8 +453,10 @@ static int l2cap_connect(struct io_context *io_ctxt, const bdaddr_t *src, bacpy(&l2a.l2_bdaddr, src); err = bind(sk, (struct sockaddr *) &l2a, sizeof(l2a)); - if (err < 0) + if (err < 0) { + close(sk); return -errno; + } memset(&l2a, 0, sizeof(l2a)); l2a.l2_family = AF_BLUETOOTH; @@ -484,8 +488,10 @@ static int rfcomm_connect(struct io_context *io_ctxt, const bdaddr_t *src, bacpy(&addr.rc_bdaddr, src); err = bind(sk, (struct sockaddr *) &addr, sizeof(addr)); - if (err < 0) + if (err < 0) { + close(sk); return -errno; + } memset(&addr, 0, sizeof(addr)); addr.rc_family = AF_BLUETOOTH; diff --git a/common/glib-helper.h b/common/glib-helper.h index b51122ad..6d191640 100644 --- a/common/glib-helper.h +++ b/common/glib-helper.h @@ -22,14 +22,14 @@ */ typedef void (*bt_io_callback_t) (GIOChannel *io, int err, gpointer user_data); -typedef void (*bt_callback_t) (gpointer user_data, sdp_list_t *recs, int err); +typedef void (*bt_callback_t) (sdp_list_t *recs, int err, gpointer user_data); typedef void (*bt_destroy_t) (gpointer user_data); int bt_discover_services(const bdaddr_t *src, const bdaddr_t *dst, bt_callback_t cb, void *user_data, bt_destroy_t destroy); int bt_search_service(const bdaddr_t *src, const bdaddr_t *dst, - uuid_t uuid, bt_callback_t cb, void *user_data, + uuid_t *uuid, bt_callback_t cb, void *user_data, bt_destroy_t destroy); gchar *bt_uuid2string(uuid_t *uuid); -- cgit From 03df0ffb9a8cb50289d8ec6e4dfdffb375481601 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 25 Apr 2008 13:00:18 +0000 Subject: Add support of DBUS_TYPE_OBJECT_PATH to dbus_message_iter_append_variant. --- common/dbus-helper.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'common') diff --git a/common/dbus-helper.c b/common/dbus-helper.c index e6211824..a7604f65 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -446,6 +446,9 @@ void dbus_message_iter_append_variant(DBusMessageIter *iter, int type, void *val case DBUS_TYPE_ARRAY: sig = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING; break; + case DBUS_TYPE_OBJECT_PATH: + sig = DBUS_TYPE_OBJECT_PATH_AS_STRING; + break; default: error("Could not append variant with type %d", type); return; -- cgit From fadd0daf0caaa8a6bab10d457e21176e25ecf060 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 25 Apr 2008 18:06:25 +0000 Subject: Fix possible use of unitialized memory. --- common/glib-helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index 5e0d4cb3..f76cdecb 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -348,7 +348,7 @@ GSList *bt_string2list(const gchar *str) static gboolean connect_cb(GIOChannel *io, GIOCondition cond, struct io_context *io_ctxt) { - int sk, err, ret; + int sk, err = 0, ret; socklen_t len; if (cond & G_IO_NVAL) -- cgit From f0056a32226d99db3d95f0e995c815640519749c Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 29 Apr 2008 14:23:04 +0000 Subject: Close sdp session before calling the application callback. --- common/glib-helper.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index f76cdecb..7810ba7e 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -63,7 +63,6 @@ static void search_context_cleanup(struct search_context *ctxt) { if (ctxt->destroy) ctxt->destroy(ctxt->user_data); - sdp_close(ctxt->session); g_free(ctxt); } @@ -107,9 +106,9 @@ static void search_completed_cb(uint8_t type, uint16_t status, } while (scanned < size); done: + sdp_close(ctxt->session); if (ctxt->cb) ctxt->cb(recs, err, ctxt->user_data); - search_context_cleanup(ctxt); } @@ -131,6 +130,7 @@ static gboolean search_process_cb(GIOChannel *chan, failed: if (err) { + sdp_close(ctxt->session); if (ctxt->cb) ctxt->cb(NULL, err, ctxt->user_data); search_context_cleanup(ctxt); @@ -182,6 +182,7 @@ static gboolean connect_watch(GIOChannel *chan, GIOCondition cond, gpointer user return FALSE; failed: + sdp_close(ctxt->session); if (ctxt->cb) ctxt->cb(NULL, -err, ctxt->user_data); search_context_cleanup(ctxt); -- cgit From f85b9560ece47c94ec82466cba9c44da715591d9 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 7 May 2008 18:39:36 +0000 Subject: Make bt_l2cap_connect to take mtu as paramter. --- common/glib-helper.c | 17 ++++++++++++++--- common/glib-helper.h | 3 ++- 2 files changed, 16 insertions(+), 4 deletions(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index 7810ba7e..8fa8efcf 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -440,8 +440,11 @@ static int sco_connect(struct io_context *io_ctxt, const bdaddr_t *src, } static int l2cap_connect(struct io_context *io_ctxt, const bdaddr_t *src, - const bdaddr_t *dst, uint16_t psm) + const bdaddr_t *dst, uint16_t psm, + uint16_t mtu) { + struct l2cap_options l2o; + socklen_t olen; struct sockaddr_l2 l2a; int sk, err; @@ -449,6 +452,14 @@ static int l2cap_connect(struct io_context *io_ctxt, const bdaddr_t *src, if (sk < 0) return -errno; + if (mtu) { + memset(&l2o, 0, sizeof(l2o)); + olen = sizeof(l2o); + getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &olen); + l2o.imtu = l2o.omtu = mtu; + setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, sizeof(l2o)); + } + memset(&l2a, 0, sizeof(l2a)); l2a.l2_family = AF_BLUETOOTH; bacpy(&l2a.l2_bdaddr, src); @@ -551,7 +562,7 @@ int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, } int bt_l2cap_connect(const bdaddr_t *src, const bdaddr_t *dst, - uint16_t psm, bt_io_callback_t cb, void *user_data) + uint16_t psm, uint16_t mtu, bt_io_callback_t cb, void *user_data) { struct io_context *io_ctxt; int err; @@ -560,7 +571,7 @@ int bt_l2cap_connect(const bdaddr_t *src, const bdaddr_t *dst, if (err < 0) return err; - err = l2cap_connect(io_ctxt, src, dst, psm); + err = l2cap_connect(io_ctxt, src, dst, psm, mtu); if (err < 0) { io_context_cleanup(io_ctxt); return err; diff --git a/common/glib-helper.h b/common/glib-helper.h index 6d191640..97f51b11 100644 --- a/common/glib-helper.h +++ b/common/glib-helper.h @@ -39,6 +39,7 @@ GSList *bt_string2list(const gchar *str); int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel, bt_io_callback_t cb, void *user_data); int bt_l2cap_connect(const bdaddr_t *src, const bdaddr_t *dst, - uint16_t psm, bt_io_callback_t cb, void *user_data); + uint16_t psm, uint16_t mtu, bt_io_callback_t cb, + void *user_data); int bt_sco_connect(const bdaddr_t *src, const bdaddr_t *dst, bt_io_callback_t cb, void *user_data); -- cgit From 1e3561c600a08b5a5dc45b405fe1ecc30df4f270 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 8 May 2008 13:27:42 +0000 Subject: Remove HAL support helpers --- common/Makefile.am | 13 ++--- common/hal-dummy.c | 47 ----------------- common/hal-libhal.c | 149 ---------------------------------------------------- common/hal.h | 35 ------------ 4 files changed, 3 insertions(+), 241 deletions(-) delete mode 100644 common/hal-dummy.c delete mode 100644 common/hal-libhal.c delete mode 100644 common/hal.h (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index c231319b..7dac6b6a 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -1,10 +1,4 @@ -if HAL -hal_sources = hal-libhal.c -else -hal_sources = hal-dummy.c -endif - if INOTIFY notify_sources = notify-inotify.c else @@ -16,8 +10,8 @@ noinst_LIBRARIES = libhelper.a libhelper_a_SOURCES = oui.h oui.c dbus.h dbus.c \ textfile.h textfile.c logging.h logging.c \ dbus-helper.h dbus-helper.c error.h error.c \ - glib-helper.h glib-helper.c sdp-xml.h sdp-xml.c sdp-glib.c \ - hal.h $(hal_sources) notify.h $(notify_sources) + glib-helper.h glib-helper.c notify.h $(notify_sources) \ + sdp-xml.h sdp-xml.c sdp-glib.c noinst_PROGRAMS = test_textfile @@ -25,7 +19,6 @@ test_textfile_LDADD = libhelper.a AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ -EXTRA_DIST = ppoll.h uinput.h hal-dummy.c hal-libhal.c \ - notify-dummy.c notify-inotify.c +EXTRA_DIST = ppoll.h uinput.h notify-dummy.c notify-inotify.c MAINTAINERCLEANFILES = Makefile.in diff --git a/common/hal-dummy.c b/common/hal-dummy.c deleted file mode 100644 index a049cda9..00000000 --- a/common/hal-dummy.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2006-2008 Marcel Holtmann - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "hal.h" - -int hal_init(DBusConnection *conn) -{ - return 0; -} - -void hal_cleanup(void) -{ -} - -int hal_create_device(struct hal_device *device) -{ - return 0; -} - -int hal_remove_device(struct hal_device *device) -{ - return 0; -} diff --git a/common/hal-libhal.c b/common/hal-libhal.c deleted file mode 100644 index 63b5677e..00000000 --- a/common/hal-libhal.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2006-2008 Marcel Holtmann - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include -#include - -#include "logging.h" -#include "dbus.h" - -#include "hal.h" - -static LibHalContext *hal_ctx = NULL; - -static DBusHandlerResult filter_function(DBusConnection *connection, - DBusMessage *message, void *userdata) -{ - info("filter_function: sender=%s destination=%s obj_path=%s interface=%s method=%s", - dbus_message_get_sender (message), - dbus_message_get_destination (message), - dbus_message_get_path (message), - dbus_message_get_interface (message), - dbus_message_get_member (message)); - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -int hal_init(DBusConnection *conn) -{ - hal_ctx = libhal_ctx_new(); - if (!hal_ctx) - return -ENOMEM; - - dbus_connection_add_filter(conn, filter_function, NULL, NULL); - - if (libhal_ctx_set_dbus_connection(hal_ctx, conn) == FALSE) { - error("Failed to connect HAL via system bus"); - libhal_ctx_free(hal_ctx); - hal_ctx = NULL; - return -EIO; - } - - if (libhal_ctx_init(hal_ctx, NULL) == FALSE) { - error("Unable to init HAL context"); - libhal_ctx_free(hal_ctx); - hal_ctx = NULL; - return -EIO; - } - - return 0; -} - -void hal_cleanup(void) -{ - if (!hal_ctx) - return; - - libhal_ctx_shutdown(hal_ctx, NULL); - - libhal_ctx_free(hal_ctx); - - hal_ctx = NULL; -} - -int hal_create_device(struct hal_device *device) -{ - DBusError err; - char udi[128], *dev; - char *str = "00000000-0000-1000-8000-00805f9b34fb"; - - dev = libhal_new_device(hal_ctx, NULL); - - if (libhal_device_set_property_string(hal_ctx, dev, - "bluetooth.uuid", str, NULL) == FALSE) { - error("Failed to add UUID property"); - } - - if (libhal_device_set_property_bool(hal_ctx, dev, - "bluetooth.is_connected", FALSE, NULL) == FALSE) { - error("Failed to add connected state property"); - } - - if (libhal_device_add_capability(hal_ctx, dev, - "bluetooth", NULL) == FALSE) { - error("Failed to add device capability"); - } - - sprintf(udi, "/org/freedesktop/Hal/devices/bluetooth_test"); - - dbus_error_init(&err); - if (libhal_device_claim_interface(hal_ctx, dev, - "org.freedesktop.Hal.Device.MyBluetooth", - " \n" - " \n" - " \n" - " \n", - &err) == FALSE) { - error("Failed to claim to interface: ", err.message); - dbus_error_free(&err); - } - - if (libhal_device_commit_to_gdl(hal_ctx, dev, udi, NULL) == FALSE) { - error("Failed to create HAL device"); - } - - free(dev); - - return 0; -} - -int hal_remove_device(struct hal_device *device) -{ - char udi[128]; - - sprintf(udi, "/org/freedesktop/Hal/devices/bluetooth_test"); - - if (libhal_remove_device(hal_ctx, udi, NULL) == FALSE) { - error("Failed to remove HAL device"); - } - - return 0; -} diff --git a/common/hal.h b/common/hal.h deleted file mode 100644 index 075ceb17..00000000 --- a/common/hal.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2006-2008 Marcel Holtmann - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include - -int hal_init(DBusConnection *conn); -void hal_cleanup(void); - -struct hal_device { - char *udi; - char uuid[37]; -}; - -int hal_create_device(struct hal_device *); -int hal_remove_device(struct hal_device *); -- cgit From 2810e2a6b3d36bf25e8b15fcdb078d2cc252daba Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 8 May 2008 13:41:21 +0000 Subject: Remove inotify support --- common/Makefile.am | 15 ++--- common/notify-dummy.c | 44 ------------- common/notify-inotify.c | 165 ------------------------------------------------ common/notify.h | 35 ---------- 4 files changed, 4 insertions(+), 255 deletions(-) delete mode 100644 common/notify-dummy.c delete mode 100644 common/notify-inotify.c delete mode 100644 common/notify.h (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index 7dac6b6a..a90df324 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -1,16 +1,9 @@ -if INOTIFY -notify_sources = notify-inotify.c -else -notify_sources = notify-dummy.c -endif - noinst_LIBRARIES = libhelper.a -libhelper_a_SOURCES = oui.h oui.c dbus.h dbus.c \ - textfile.h textfile.c logging.h logging.c \ - dbus-helper.h dbus-helper.c error.h error.c \ - glib-helper.h glib-helper.c notify.h $(notify_sources) \ +libhelper_a_SOURCES = oui.h oui.c textfile.h textfile.c \ + logging.h logging.c error.h error.c dbus.h dbus.c \ + dbus-helper.h dbus-helper.c glib-helper.h glib-helper.c \ sdp-xml.h sdp-xml.c sdp-glib.c noinst_PROGRAMS = test_textfile @@ -19,6 +12,6 @@ test_textfile_LDADD = libhelper.a AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ -EXTRA_DIST = ppoll.h uinput.h notify-dummy.c notify-inotify.c +EXTRA_DIST = ppoll.h uinput.h MAINTAINERCLEANFILES = Makefile.in diff --git a/common/notify-dummy.c b/common/notify-dummy.c deleted file mode 100644 index 98fdb621..00000000 --- a/common/notify-dummy.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2006-2008 Marcel Holtmann - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "notify.h" - -void notify_init(void) -{ -} - -void notify_close(void) -{ -} - -void notify_add(const char *pathname, notify_func func, void *user_data) -{ -} - -void notify_remove(const char *pathname) -{ -} diff --git a/common/notify-inotify.c b/common/notify-inotify.c deleted file mode 100644 index a8a6b193..00000000 --- a/common/notify-inotify.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2006-2008 Marcel Holtmann - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#ifndef IN_ONLYDIR -#define IN_ONLYDIR 0x01000000 -#endif - -#include - -#include "logging.h" -#include "notify.h" - -static GIOChannel *io = NULL; - -static int fd = -1; -static int wd = -1; - -static char *name = NULL; - -static notify_func callback = NULL; - -static gboolean io_event(GIOChannel *chan, GIOCondition cond, gpointer data) -{ - unsigned char buf[129], *ptr = buf; - gsize len; - GIOError err; - - if (cond & (G_IO_HUP | G_IO_ERR)) - return FALSE; - - memset(buf, 0, sizeof(buf)); - - err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf) - 1, &len); - if (err != G_IO_ERROR_NONE) { - if (err == G_IO_ERROR_AGAIN) - return TRUE; - error("Reading from inotify channel failed"); - return FALSE; - } - - - while (len >= sizeof(struct inotify_event)) { - struct inotify_event *evt = (struct inotify_event *) ptr; - - if (evt->wd == wd && callback) { - if (evt->mask & (IN_CREATE | IN_MOVED_TO)) - callback(NOTIFY_CREATE, evt->name, NULL); - - if (evt->mask & (IN_DELETE | IN_MOVED_FROM)) - callback(NOTIFY_DELETE, evt->name, NULL); - - if (evt->mask & IN_MODIFY) - callback(NOTIFY_MODIFY, evt->name, NULL); - } - - len -= sizeof(struct inotify_event) + evt->len; - ptr += sizeof(struct inotify_event) + evt->len; - } - - return TRUE; -} - -void notify_init(void) -{ - if (fd != -1) - return; - - fd = inotify_init(); - if (fd < 0) { - error("Creation of inotify context failed"); - return; - } - - io = g_io_channel_unix_new(fd); - if (!io) { - error("Creation of inotify channel failed"); - return; - } - - g_io_add_watch(io, G_IO_IN | G_IO_ERR | G_IO_HUP, io_event, NULL); -} - -void notify_close(void) -{ - if (fd == -1) - return; - - if (wd != -1) { - inotify_rm_watch(fd, wd); - wd = -1; - } - - if (io) { - g_io_channel_unref(io); - io = NULL; - } - - close(fd); - fd = -1; - - if (name) { - free(name); - name = NULL; - } -} - -void notify_add(const char *pathname, notify_func func, void *user_data) -{ - if (fd == -1 || wd != -1) - return; - - if (name) - free(name); - - name = strdup(pathname); - if (!name) - return; - - wd = inotify_add_watch(fd, pathname, - IN_ONLYDIR | IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVE); - if (wd < 0) - error("Creation of watch for %s failed", pathname); - - callback = func; -} - -void notify_remove(const char *pathname) -{ - if (fd == -1 || wd == -1) - return; - - inotify_rm_watch(fd, wd); - wd = -1; - - callback = NULL; -} diff --git a/common/notify.h b/common/notify.h deleted file mode 100644 index 50555dc1..00000000 --- a/common/notify.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2006-2008 Marcel Holtmann - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -typedef void (*notify_func)(int action, const char *name, void *user_data); - -enum { - NOTIFY_CREATE, - NOTIFY_DELETE, - NOTIFY_MODIFY, -}; - -void notify_init(void); -void notify_close(void); -void notify_add(const char *pathname, notify_func func, void *user_data); -void notify_remove(const char *pathname); -- cgit From 2af3c3a7ddc43577c067892cdfdc06dc4e63386c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 8 May 2008 17:24:48 +0000 Subject: Remove service daemon activation handling --- common/dbus.c | 42 ------------------------------------------ 1 file changed, 42 deletions(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index 53e1046b..5a59f8f2 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -877,45 +877,3 @@ int set_nonblocking(int fd) return 0; } - -static void external_reply(DBusPendingCall *call, void *user_data) -{ - DBusMessage *reply; - - debug("Service register reply"); - - reply = dbus_pending_call_steal_reply(call); - - dbus_message_unref(reply); -} - -void register_external_service(DBusConnection *conn, const char *identifier, - const char *name, const char *description) -{ - DBusMessage *msg; - DBusPendingCall *call; - - info("Registering service"); - - msg = dbus_message_new_method_call("org.bluez", "/org/bluez", - "org.bluez.Database", "RegisterService"); - if (!msg) { - error("Can't create service register method"); - return; - } - - dbus_message_append_args(msg, DBUS_TYPE_STRING, &identifier, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_STRING, &description, DBUS_TYPE_INVALID); - - if (dbus_connection_send_with_reply(conn, msg, &call, -1) == FALSE) { - error("Can't register service"); - dbus_message_unref(msg); - return; - } - - dbus_pending_call_set_notify(call, external_reply, NULL, NULL); - dbus_pending_call_unref(call); - - dbus_message_unref(msg); -} -- cgit From 2d1284ae8d28374c81af55b8240f1923e6694be2 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 8 May 2008 17:39:18 +0000 Subject: Remove simple introspection function --- common/dbus.c | 27 --------------------------- common/dbus.h | 3 --- 2 files changed, 30 deletions(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index 5a59f8f2..ccf7c46c 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -827,33 +827,6 @@ DBusConnection *dbus_bus_system_setup_with_main_loop(const char *name, return init_dbus(name, disconnect_cb, user_data); } -static char simple_xml[] = DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE ""; - -DBusHandlerResult simple_introspect(DBusConnection *conn, - DBusMessage *msg, void *user_data) -{ - DBusMessage *reply; - const char *path, *ptr = simple_xml; - - path = dbus_message_get_path(msg); - - info("Introspect path:%s", path); - - if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING)) { - error("Unexpected signature to introspect call"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - - reply = dbus_message_new_method_return(msg); - if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - - dbus_message_append_args(reply, DBUS_TYPE_STRING, &ptr, - DBUS_TYPE_INVALID); - - return send_message_and_unref(conn, reply); -} - int set_nonblocking(int fd) { long arg; diff --git a/common/dbus.h b/common/dbus.h index b8223059..2a182ac8 100644 --- a/common/dbus.h +++ b/common/dbus.h @@ -38,9 +38,6 @@ DBusConnection *init_dbus_direct(const char *address); DBusConnection *dbus_bus_system_setup_with_main_loop(const char *name, void (*disconnect_cb)(void *), void *user_data); -DBusHandlerResult simple_introspect(DBusConnection *conn, - DBusMessage *msg, void *user_data); - typedef void (*name_cb_t)(const char *name, void *user_data); guint name_listener_add(DBusConnection *connection, const char *name, -- cgit From 4d39e4d2ea552e2d4ad36c085700f513e10be7e0 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 8 May 2008 18:47:21 +0000 Subject: Move set_nonblocking() to the GLib helpers for now --- common/dbus.c | 24 ------------------------ common/dbus.h | 5 ----- common/glib-helper.c | 19 +++++++++++++++++++ common/glib-helper.h | 2 ++ 4 files changed, 21 insertions(+), 29 deletions(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index ccf7c46c..15716d7f 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -826,27 +826,3 @@ DBusConnection *dbus_bus_system_setup_with_main_loop(const char *name, { return init_dbus(name, disconnect_cb, user_data); } - -int set_nonblocking(int fd) -{ - long arg; - - arg = fcntl(fd, F_GETFL); - if (arg < 0) { - error("fcntl(F_GETFL): %s (%d)", strerror(errno), errno); - return -errno; - } - - /* Return if already nonblocking */ - if (arg & O_NONBLOCK) - return 0; - - arg |= O_NONBLOCK; - if (fcntl(fd, F_SETFL, arg) < 0) { - error("fcntl(F_SETFL, O_NONBLOCK): %s (%d)", - strerror(errno), errno); - return -errno; - } - - return 0; -} diff --git a/common/dbus.h b/common/dbus.h index 2a182ac8..5b133191 100644 --- a/common/dbus.h +++ b/common/dbus.h @@ -60,9 +60,4 @@ static inline DBusHandlerResult send_message_and_unref(DBusConnection *conn, DBu return DBUS_HANDLER_RESULT_HANDLED; } -int set_nonblocking(int fd); - -void register_external_service(DBusConnection *conn, const char *identifier, - const char *name, const char *description); - #endif /* __H_BLUEZ_DBUS_H__ */ diff --git a/common/glib-helper.c b/common/glib-helper.c index 8fa8efcf..36228d45 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -43,6 +43,25 @@ #include "glib-helper.h" +int set_nonblocking(int fd) +{ + long arg; + + arg = fcntl(fd, F_GETFL); + if (arg < 0) + return -errno; + + /* Return if already nonblocking */ + if (arg & O_NONBLOCK) + return 0; + + arg |= O_NONBLOCK; + if (fcntl(fd, F_SETFL, arg) < 0) + return -errno; + + return 0; +} + struct io_context { GIOChannel *io; bt_io_callback_t cb; diff --git a/common/glib-helper.h b/common/glib-helper.h index 97f51b11..7a312005 100644 --- a/common/glib-helper.h +++ b/common/glib-helper.h @@ -21,6 +21,8 @@ * */ +int set_nonblocking(int fd); + typedef void (*bt_io_callback_t) (GIOChannel *io, int err, gpointer user_data); typedef void (*bt_callback_t) (sdp_list_t *recs, int err, gpointer user_data); typedef void (*bt_destroy_t) (gpointer user_data); -- cgit From 6bf91edf6cdb840c0f40572f1a20d381fd2cdc5e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 8 May 2008 18:49:45 +0000 Subject: Remove uneeded D-Bus API extension --- common/dbus.c | 52 ---------------------------------------------------- common/dbus.h | 3 --- 2 files changed, 55 deletions(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index 15716d7f..beb97a07 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -416,58 +416,6 @@ int name_listener_indicate_disconnect(DBusConnection *connection) return 0; } -dbus_bool_t dbus_bus_get_unix_process_id(DBusConnection *conn, const char *name, - unsigned long *pid) -{ - DBusMessage *msg, *reply; - DBusError err; - dbus_uint32_t pid_arg; - - msg = dbus_message_new_method_call("org.freedesktop.DBus", - "/org/freedesktop/DBus", - "org.freedesktop.DBus", - "GetConnectionUnixProcessID"); - if (!msg) { - error("Unable to allocate new message"); - return FALSE; - } - - if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID)) { - error("Unable to append arguments to message"); - dbus_message_unref(msg); - return FALSE; - } - - dbus_error_init(&err); - reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err); - if (dbus_error_is_set(&err)) { - error("Sending GetConnectionUnixProcessID failed: %s", err.message); - dbus_error_free(&err); - dbus_message_unref(msg); - return FALSE; - } - - dbus_error_init(&err); - dbus_message_get_args(reply, &err, DBUS_TYPE_UINT32, &pid_arg, - DBUS_TYPE_INVALID); - if (dbus_error_is_set(&err)) { - error("Getting GetConnectionUnixProcessID args failed: %s", - err.message); - dbus_error_free(&err); - dbus_message_unref(msg); - dbus_message_unref(reply); - return FALSE; - } - - *pid = (unsigned long) pid_arg; - - dbus_message_unref(msg); - dbus_message_unref(reply); - - return TRUE; -} - static DBusHandlerResult disconnect_filter(DBusConnection *conn, DBusMessage *msg, void *data) { diff --git a/common/dbus.h b/common/dbus.h index 5b133191..94244eb6 100644 --- a/common/dbus.h +++ b/common/dbus.h @@ -47,9 +47,6 @@ int name_listener_remove(DBusConnection *connection, const char *name, gboolean name_listener_id_remove(guint id); int name_listener_indicate_disconnect(DBusConnection *connection); -dbus_bool_t dbus_bus_get_unix_process_id(DBusConnection *conn, const char *name, - unsigned long *pid); - static inline DBusHandlerResult send_message_and_unref(DBusConnection *conn, DBusMessage *msg) { if (msg) { -- cgit From 33191e6275ab82aa4161cdf75b45597e4d1568ec Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 8 May 2008 19:12:44 +0000 Subject: Move D-Bus mainloop integration into libgdbus --- common/dbus.c | 385 ---------------------------------------------------------- common/dbus.h | 11 -- 2 files changed, 396 deletions(-) (limited to 'common') diff --git a/common/dbus.c b/common/dbus.c index beb97a07..4ea56c9f 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -48,35 +48,9 @@ #include "dbus.h" #include "logging.h" -#define DISPATCH_TIMEOUT 0 - static guint listener_id = 0; static GSList *name_listeners = NULL; -#ifndef HAVE_DBUS_GLIB -typedef struct { - uint32_t id; - DBusTimeout *timeout; -} timeout_handler_t; - -struct watch_info { - guint watch_id; - GIOChannel *io; - DBusConnection *conn; -}; - -struct server_info { - guint watch_id; - GIOChannel *io; - DBusServer *server; -}; -#endif - -struct disconnect_data { - void (*disconnect_cb)(void *); - void *user_data; -}; - struct name_callback { name_cb_t func; void *user_data; @@ -415,362 +389,3 @@ int name_listener_indicate_disconnect(DBusConnection *connection) return 0; } - -static DBusHandlerResult disconnect_filter(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct disconnect_data *dc_data = data; - - if (dbus_message_is_signal(msg, - DBUS_INTERFACE_LOCAL, "Disconnected") == TRUE) { - error("Got disconnected from the system message bus"); - dbus_connection_unref(conn); - dc_data->disconnect_cb(dc_data->user_data); - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -#ifndef HAVE_DBUS_GLIB -static dbus_int32_t server_slot = -1; - -static gboolean server_func(GIOChannel *chan, GIOCondition cond, gpointer data) -{ - DBusWatch *watch = data; - int flags = 0; - - if (cond & G_IO_IN) flags |= DBUS_WATCH_READABLE; - if (cond & G_IO_OUT) flags |= DBUS_WATCH_WRITABLE; - if (cond & G_IO_HUP) flags |= DBUS_WATCH_HANGUP; - if (cond & G_IO_ERR) flags |= DBUS_WATCH_ERROR; - - dbus_watch_handle(watch, flags); - - return TRUE; -} - -static dbus_bool_t add_server(DBusWatch *watch, void *data) -{ - GIOCondition cond = G_IO_HUP | G_IO_ERR; - DBusServer *server = data; - struct server_info *info; - int fd, flags; - - if (!dbus_watch_get_enabled(watch)) - return TRUE; - - info = g_new(struct server_info, 1); - - fd = dbus_watch_get_unix_fd(watch); - info->io = g_io_channel_unix_new(fd); - info->server = dbus_server_ref(server); - - dbus_watch_set_data(watch, info, NULL); - - flags = dbus_watch_get_flags(watch); - - if (flags & DBUS_WATCH_READABLE) cond |= G_IO_IN; - if (flags & DBUS_WATCH_WRITABLE) cond |= G_IO_OUT; - - info->watch_id = g_io_add_watch(info->io, cond, server_func, watch); - - return TRUE; -} - -static void remove_server(DBusWatch *watch, void *data) -{ - struct server_info *info = dbus_watch_get_data(watch); - - dbus_watch_set_data(watch, NULL, NULL); - - if (info) { - g_source_remove(info->watch_id); - g_io_channel_unref(info->io); - dbus_server_unref(info->server); - g_free(info); - } -} - -static void server_toggled(DBusWatch *watch, void *data) -{ - /* Because we just exit on OOM, enable/disable is - * no different from add/remove */ - if (dbus_watch_get_enabled(watch)) - add_server(watch, data); - else - remove_server(watch, data); -} - -static gboolean message_dispatch_cb(void *data) -{ - DBusConnection *connection = data; - - dbus_connection_ref(connection); - - /* Dispatch messages */ - while (dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS); - - dbus_connection_unref(connection); - - return FALSE; -} - -static gboolean watch_func(GIOChannel *chan, GIOCondition cond, gpointer data) -{ - DBusWatch *watch = data; - struct watch_info *info = dbus_watch_get_data(watch); - int flags = 0; - - if (cond & G_IO_IN) flags |= DBUS_WATCH_READABLE; - if (cond & G_IO_OUT) flags |= DBUS_WATCH_WRITABLE; - if (cond & G_IO_HUP) flags |= DBUS_WATCH_HANGUP; - if (cond & G_IO_ERR) flags |= DBUS_WATCH_ERROR; - - dbus_watch_handle(watch, flags); - - if (dbus_connection_get_dispatch_status(info->conn) == DBUS_DISPATCH_DATA_REMAINS) - g_timeout_add(DISPATCH_TIMEOUT, message_dispatch_cb, info->conn); - - return TRUE; -} - -static dbus_bool_t add_watch(DBusWatch *watch, void *data) -{ - GIOCondition cond = G_IO_HUP | G_IO_ERR; - DBusConnection *conn = data; - struct watch_info *info; - int fd, flags; - - if (!dbus_watch_get_enabled(watch)) - return TRUE; - - info = g_new(struct watch_info, 1); - - fd = dbus_watch_get_unix_fd(watch); - info->io = g_io_channel_unix_new(fd); - info->conn = dbus_connection_ref(conn); - - dbus_watch_set_data(watch, info, NULL); - - flags = dbus_watch_get_flags(watch); - - if (flags & DBUS_WATCH_READABLE) cond |= G_IO_IN; - if (flags & DBUS_WATCH_WRITABLE) cond |= G_IO_OUT; - - info->watch_id = g_io_add_watch(info->io, cond, watch_func, watch); - - return TRUE; -} - -static void remove_watch(DBusWatch *watch, void *data) -{ - struct watch_info *info = dbus_watch_get_data(watch); - - dbus_watch_set_data(watch, NULL, NULL); - - if (info) { - g_source_remove(info->watch_id); - g_io_channel_unref(info->io); - dbus_connection_unref(info->conn); - g_free(info); - } -} - -static void watch_toggled(DBusWatch *watch, void *data) -{ - /* Because we just exit on OOM, enable/disable is - * no different from add/remove */ - if (dbus_watch_get_enabled(watch)) - add_watch(watch, data); - else - remove_watch(watch, data); -} - -static gboolean timeout_handler_dispatch(gpointer data) -{ - timeout_handler_t *handler = data; - - /* if not enabled should not be polled by the main loop */ - if (dbus_timeout_get_enabled(handler->timeout) != TRUE) - return FALSE; - - dbus_timeout_handle(handler->timeout); - - return FALSE; -} - -static void timeout_handler_free(void *data) -{ - timeout_handler_t *handler = data; - if (!handler) - return; - - g_source_remove(handler->id); - g_free(handler); -} - -static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) -{ - timeout_handler_t *handler; - - if (!dbus_timeout_get_enabled(timeout)) - return TRUE; - - handler = g_new0(timeout_handler_t, 1); - - handler->timeout = timeout; - handler->id = g_timeout_add(dbus_timeout_get_interval(timeout), - timeout_handler_dispatch, handler); - - dbus_timeout_set_data(timeout, handler, timeout_handler_free); - - return TRUE; -} - -static void remove_timeout(DBusTimeout *timeout, void *data) -{ -} - -static void timeout_toggled(DBusTimeout *timeout, void *data) -{ - if (dbus_timeout_get_enabled(timeout)) - add_timeout(timeout, data); - else - remove_timeout(timeout, data); -} - -static void dispatch_status_cb(DBusConnection *conn, - DBusDispatchStatus new_status, void *data) -{ - if (!dbus_connection_get_is_connected(conn)) - return; - - if (new_status == DBUS_DISPATCH_DATA_REMAINS) - g_timeout_add(DISPATCH_TIMEOUT, message_dispatch_cb, data); -} -#endif - -void setup_dbus_server_with_main_loop(DBusServer *server) -{ -#ifdef HAVE_DBUS_GLIB - debug("Using D-Bus GLib server setup"); - - dbus_server_setup_with_g_main(server, NULL); -#else - dbus_server_allocate_data_slot(&server_slot); - if (server_slot < 0) - return; - - dbus_server_set_data(server, server_slot, server, NULL); - - dbus_server_set_watch_functions(server, add_server, remove_server, - server_toggled, server, NULL); - - dbus_server_set_timeout_functions(server, add_timeout, remove_timeout, - timeout_toggled, server, NULL); -#endif -} - -void setup_dbus_with_main_loop(DBusConnection *conn) -{ -#ifdef HAVE_DBUS_GLIB - debug("Using D-Bus GLib connection setup"); - - dbus_connection_setup_with_g_main(conn, NULL); -#else - dbus_connection_set_watch_functions(conn, add_watch, remove_watch, - watch_toggled, conn, NULL); - - dbus_connection_set_timeout_functions(conn, add_timeout, remove_timeout, - timeout_toggled, conn, NULL); - - dbus_connection_set_dispatch_status_function(conn, dispatch_status_cb, - conn, NULL); -#endif -} - -DBusConnection *init_dbus(const char *name, - void (*disconnect_cb)(void *), void *user_data) -{ - struct disconnect_data *dc_data; - DBusConnection *conn; - DBusError err; - - dbus_error_init(&err); - - conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); - - if (dbus_error_is_set(&err)) { - error("Can't connect to system message bus: %s", err.message); - dbus_error_free(&err); - return NULL; - } - - setup_dbus_with_main_loop(conn); - - if (name) { - dbus_error_init(&err); - - if (dbus_bus_request_name(conn, name, 0, &err) != - DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER ) { - error("Could not become the primary owner of %s", name); - dbus_connection_unref(conn); - return NULL; - } - - if (dbus_error_is_set(&err)) { - error("Can't get bus name %s: %s", name, err.message); - dbus_error_free(&err); - dbus_connection_unref(conn); - return NULL; - } - } - - if (!disconnect_cb) - return conn; - - dc_data = g_new(struct disconnect_data, 1); - - dc_data->disconnect_cb = disconnect_cb; - dc_data->user_data = user_data; - - dbus_connection_set_exit_on_disconnect(conn, FALSE); - - if (!dbus_connection_add_filter(conn, disconnect_filter, - dc_data, g_free)) { - error("Can't add D-Bus disconnect filter"); - g_free(dc_data); - dbus_connection_unref(conn); - return NULL; - } - - return conn; -} - -DBusConnection *init_dbus_direct(const char *address) -{ - DBusConnection *conn; - DBusError err; - - dbus_error_init(&err); - - conn = dbus_connection_open(address, &err); - - if (dbus_error_is_set(&err)) { - error("Can't connect to message server: %s", err.message); - dbus_error_free(&err); - return NULL; - } - - setup_dbus_with_main_loop(conn); - - dbus_connection_set_exit_on_disconnect(conn, FALSE); - - return conn; -} - -DBusConnection *dbus_bus_system_setup_with_main_loop(const char *name, - void (*disconnect_cb)(void *), void *user_data) -{ - return init_dbus(name, disconnect_cb, user_data); -} diff --git a/common/dbus.h b/common/dbus.h index 94244eb6..5976a479 100644 --- a/common/dbus.h +++ b/common/dbus.h @@ -27,17 +27,6 @@ #include #include -void setup_dbus_server_with_main_loop(DBusServer *server); -void setup_dbus_with_main_loop(DBusConnection *conn); - -DBusConnection *init_dbus(const char *name, - void (*disconnect_cb)(void *), void *user_data); - -DBusConnection *init_dbus_direct(const char *address); - -DBusConnection *dbus_bus_system_setup_with_main_loop(const char *name, - void (*disconnect_cb)(void *), void *user_data); - typedef void (*name_cb_t)(const char *name, void *user_data); guint name_listener_add(DBusConnection *connection, const char *name, -- cgit From e7d668ac9e813bc9922ee7d771848bd8822d5d1f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 8 May 2008 20:23:45 +0000 Subject: Move D-Bus watch functions into libgdbus --- common/Makefile.am | 6 +- common/dbus-helper.h | 14 +- common/dbus.c | 391 --------------------------------------------------- common/dbus.h | 49 ------- 4 files changed, 16 insertions(+), 444 deletions(-) delete mode 100644 common/dbus.c delete mode 100644 common/dbus.h (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index a90df324..5352d34f 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -2,9 +2,9 @@ noinst_LIBRARIES = libhelper.a libhelper_a_SOURCES = oui.h oui.c textfile.h textfile.c \ - logging.h logging.c error.h error.c dbus.h dbus.c \ - dbus-helper.h dbus-helper.c glib-helper.h glib-helper.c \ - sdp-xml.h sdp-xml.c sdp-glib.c + logging.h logging.c error.h error.c \ + dbus-helper.h dbus-helper.c \ + glib-helper.h glib-helper.c sdp-xml.h sdp-xml.c sdp-glib.c noinst_PROGRAMS = test_textfile diff --git a/common/dbus-helper.h b/common/dbus-helper.h index 57c3d09b..6c3c3a89 100644 --- a/common/dbus-helper.h +++ b/common/dbus-helper.h @@ -20,8 +20,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ + #include -#include +#include #define DBUS_TYPE_STRING_ARRAY_AS_STRING (DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING) #define DBUS_TYPE_BYTE_ARRAY_AS_STRING (DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING) @@ -93,3 +94,14 @@ dbus_bool_t dbus_connection_emit_property_changed(DBusConnection *conn, const char *interface, const char *name, int type, void *value); + +static inline DBusHandlerResult send_message_and_unref(DBusConnection *conn, + DBusMessage *msg) +{ + if (msg) { + dbus_connection_send(conn, msg, NULL); + dbus_message_unref(msg); + } + + return DBUS_HANDLER_RESULT_HANDLED; +} diff --git a/common/dbus.c b/common/dbus.c deleted file mode 100644 index 4ea56c9f..00000000 --- a/common/dbus.c +++ /dev/null @@ -1,391 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2008 Marcel Holtmann - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#ifdef NEED_DBUS_WATCH_GET_UNIX_FD -#define dbus_watch_get_unix_fd dbus_watch_get_fd -#endif - -#ifdef HAVE_DBUS_GLIB -#include -#endif - -#include "dbus.h" -#include "logging.h" - -static guint listener_id = 0; -static GSList *name_listeners = NULL; - -struct name_callback { - name_cb_t func; - void *user_data; - guint id; -}; - -struct name_data { - DBusConnection *connection; - char *name; - GSList *callbacks; -}; - -static struct name_data *name_data_find(DBusConnection *connection, - const char *name) -{ - GSList *current; - - for (current = name_listeners; - current != NULL; current = current->next) { - struct name_data *data = current->data; - - if (name == NULL && data->name == NULL) { - if (connection == data->connection) - return data; - } else { - if (strcmp(name, data->name) == 0) - return data; - } - } - - return NULL; -} - -static struct name_callback *name_callback_find(GSList *callbacks, - name_cb_t func, void *user_data) -{ - GSList *current; - - for (current = callbacks; current != NULL; current = current->next) { - struct name_callback *cb = current->data; - if (cb->func == func && cb->user_data == user_data) - return cb; - } - - return NULL; -} - -static void name_data_call_and_free(struct name_data *data) -{ - GSList *l; - - for (l = data->callbacks; l != NULL; l = l->next) { - struct name_callback *cb = l->data; - if (cb->func) - cb->func(data->name, cb->user_data); - g_free(cb); - } - - g_slist_free(data->callbacks); - g_free(data->name); - g_free(data); -} - -static void name_data_free(struct name_data *data) -{ - GSList *l; - - for (l = data->callbacks; l != NULL; l = l->next) - g_free(l->data); - - g_slist_free(data->callbacks); - g_free(data->name); - g_free(data); -} - -static int name_data_add(DBusConnection *connection, const char *name, - name_cb_t func, void *user_data, guint id) -{ - int first = 1; - struct name_data *data = NULL; - struct name_callback *cb = NULL; - - cb = g_new(struct name_callback, 1); - - cb->func = func; - cb->user_data = user_data; - cb->id = id; - - data = name_data_find(connection, name); - if (data) { - first = 0; - goto done; - } - - data = g_new0(struct name_data, 1); - - data->connection = connection; - data->name = g_strdup(name); - - name_listeners = g_slist_append(name_listeners, data); - -done: - data->callbacks = g_slist_append(data->callbacks, cb); - return first; -} - -static void name_data_remove(DBusConnection *connection, - const char *name, name_cb_t func, void *user_data) -{ - struct name_data *data; - struct name_callback *cb = NULL; - - data = name_data_find(connection, name); - if (!data) - return; - - cb = name_callback_find(data->callbacks, func, user_data); - if (cb) { - data->callbacks = g_slist_remove(data->callbacks, cb); - g_free(cb); - } - - if (!data->callbacks) { - name_listeners = g_slist_remove(name_listeners, data); - name_data_free(data); - } -} - -static gboolean add_match(DBusConnection *connection, const char *name) -{ - DBusError err; - char match_string[128]; - - snprintf(match_string, sizeof(match_string), - "interface=%s,member=NameOwnerChanged,arg0=%s", - DBUS_INTERFACE_DBUS, name); - - dbus_error_init(&err); - - dbus_bus_add_match(connection, match_string, &err); - - if (dbus_error_is_set(&err)) { - error("Adding match rule \"%s\" failed: %s", match_string, - err.message); - dbus_error_free(&err); - return FALSE; - } - - return TRUE; -} - -static gboolean remove_match(DBusConnection *connection, const char *name) -{ - DBusError err; - char match_string[128]; - - snprintf(match_string, sizeof(match_string), - "interface=%s,member=NameOwnerChanged,arg0=%s", - DBUS_INTERFACE_DBUS, name); - - dbus_error_init(&err); - - dbus_bus_remove_match(connection, match_string, &err); - - if (dbus_error_is_set(&err)) { - error("Removing owner match rule for %s failed: %s", - name, err.message); - dbus_error_free(&err); - return FALSE; - } - - return TRUE; -} - -static DBusHandlerResult name_exit_filter(DBusConnection *connection, - DBusMessage *message, void *user_data) -{ - GSList *l; - struct name_data *data; - char *name, *old, *new; - - if (!dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, - "NameOwnerChanged")) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - if (!dbus_message_get_args(message, NULL, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_STRING, &old, - DBUS_TYPE_STRING, &new, - DBUS_TYPE_INVALID)) { - error("Invalid arguments for NameOwnerChanged signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - - /* We are not interested of service creations */ - if (*new != '\0') - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - data = name_data_find(connection, name); - if (!data) { - error("Got NameOwnerChanged signal for %s which has no listeners", name); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - - for (l = data->callbacks; l != NULL; l = l->next) { - struct name_callback *cb = l->data; - cb->func(name, cb->user_data); - } - - name_listeners = g_slist_remove(name_listeners, data); - name_data_free(data); - - remove_match(connection, name); - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -guint name_listener_add(DBusConnection *connection, const char *name, - name_cb_t func, void *user_data) -{ - int first; - - if (!listener_id) { - if (!dbus_connection_add_filter(connection, - name_exit_filter, NULL, NULL)) { - error("dbus_connection_add_filter() failed"); - return 0; - } - } - - listener_id++; - first = name_data_add(connection, name, func, user_data, listener_id); - /* The filter is already added if this is not the first callback - * registration for the name */ - if (!first) - return listener_id; - - if (name) { - debug("name_listener_add(%s)", name); - - if (!add_match(connection, name)) { - name_data_remove(connection, name, func, user_data); - return 0; - } - } - - return listener_id; -} - -int name_listener_remove(DBusConnection *connection, const char *name, - name_cb_t func, void *user_data) -{ - struct name_data *data; - struct name_callback *cb; - - data = name_data_find(connection, name); - if (!data) { - error("remove_name_listener: no listener for %s", name); - return -1; - } - - cb = name_callback_find(data->callbacks, func, user_data); - if (!cb) { - error("No matching callback found for %s", name); - return -1; - } - - data->callbacks = g_slist_remove(data->callbacks, cb); - g_free(cb); - - /* Don't remove the filter if other callbacks exist */ - if (data->callbacks) - return 0; - - if (name) { - debug("name_listener_remove(%s)", name); - - if (!remove_match(connection, name)) - return -1; - } - - name_data_remove(connection, name, func, user_data); - - return 0; -} - -gboolean name_listener_id_remove(guint id) -{ - struct name_data *data; - struct name_callback *cb; - GSList *ldata, *lcb; - - for (ldata = name_listeners; ldata; ldata = ldata->next) { - data = ldata->data; - for (lcb = data->callbacks; lcb; lcb = lcb->next) { - cb = lcb->data; - if (cb->id == id) - goto remove; - } - } - - return FALSE; - -remove: - data->callbacks = g_slist_remove(data->callbacks, cb); - g_free(cb); - - /* Don't remove the filter if other callbacks exist */ - if (data->callbacks) - return TRUE; - - if (data->name) { - if (!remove_match(data->connection, data->name)) - return FALSE; - } - - name_listeners = g_slist_remove(name_listeners, data); - name_data_free(data); - - return TRUE; -} - -int name_listener_indicate_disconnect(DBusConnection *connection) -{ - struct name_data *data; - - data = name_data_find(connection, NULL); - if (!data) { - error("name_listener_indicate_disconnect: no listener found"); - return -1; - } - - debug("name_listener_indicate_disconnect"); - - name_data_call_and_free(data); - - return 0; -} diff --git a/common/dbus.h b/common/dbus.h deleted file mode 100644 index 5976a479..00000000 --- a/common/dbus.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2008 Marcel Holtmann - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifndef __H_BLUEZ_DBUS_H__ -#define __H_BLUEZ_DBUS_H__ - -#include -#include - -typedef void (*name_cb_t)(const char *name, void *user_data); - -guint name_listener_add(DBusConnection *connection, const char *name, - name_cb_t func, void *user_data); -int name_listener_remove(DBusConnection *connection, const char *name, - name_cb_t func, void *user_data); -gboolean name_listener_id_remove(guint id); -int name_listener_indicate_disconnect(DBusConnection *connection); - -static inline DBusHandlerResult send_message_and_unref(DBusConnection *conn, DBusMessage *msg) -{ - if (msg) { - dbus_connection_send(conn, msg, NULL); - dbus_message_unref(msg); - } - - return DBUS_HANDLER_RESULT_HANDLED; -} - -#endif /* __H_BLUEZ_DBUS_H__ */ -- cgit From 15ea15b3a752f0487bc50d0ea04925f1b9d33dcb Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 8 May 2008 22:19:14 +0000 Subject: Move D-Bus object and interface helpers into libgdbus --- common/Makefile.am | 3 +- common/dbus-helper.c | 659 --------------------------------------------------- common/dbus-helper.h | 107 --------- common/error.c | 3 +- 4 files changed, 3 insertions(+), 769 deletions(-) delete mode 100644 common/dbus-helper.c delete mode 100644 common/dbus-helper.h (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index 5352d34f..6ae5ed7a 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -3,14 +3,13 @@ noinst_LIBRARIES = libhelper.a libhelper_a_SOURCES = oui.h oui.c textfile.h textfile.c \ logging.h logging.c error.h error.c \ - dbus-helper.h dbus-helper.c \ glib-helper.h glib-helper.c sdp-xml.h sdp-xml.c sdp-glib.c noinst_PROGRAMS = test_textfile test_textfile_LDADD = libhelper.a -AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ +AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @GDBUS_CFLAGS@ EXTRA_DIST = ppoll.h uinput.h diff --git a/common/dbus-helper.c b/common/dbus-helper.c deleted file mode 100644 index a7604f65..00000000 --- a/common/dbus-helper.c +++ /dev/null @@ -1,659 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2008 Marcel Holtmann - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include - -#include - -#include "logging.h" - -#include "dbus-helper.h" - -struct generic_data { - void *user_data; - DBusObjectPathUnregisterFunction unregister_function; - GSList *interfaces; - char *introspect; -}; - -struct interface_data { - char *name; - DBusMethodVTable *methods; - DBusSignalVTable *signals; - DBusPropertyVTable *properties; -}; - -DBusHandlerResult dbus_connection_send_and_unref(DBusConnection *connection, - DBusMessage *message) -{ - if (message) { - dbus_connection_send(connection, message, NULL); - dbus_message_unref(message); - } - - return DBUS_HANDLER_RESULT_HANDLED; -} - -static void print_arguments(GString *gstr, const char *sig, const char *direction) -{ - int i; - - for (i = 0; sig[i]; i++) { - char type[32]; - int len, struct_level, dict_level; - gboolean complete; - - complete = FALSE; - struct_level = dict_level = 0; - memset(type, 0, sizeof(type)); - - /* Gather enough data to have a single complete type */ - for (len = 0; len < (sizeof(type) - 1) && sig[i]; len++, i++) { - switch (sig[i]){ - case '(': - struct_level++; - break; - case ')': - struct_level--; - if (struct_level <= 0 && dict_level <= 0) - complete = TRUE; - break; - case '{': - dict_level++; - break; - case '}': - dict_level--; - if (struct_level <= 0 && dict_level <= 0) - complete = TRUE; - break; - case 'a': - break; - default: - if (struct_level <= 0 && dict_level <= 0) - complete = TRUE; - break; - } - - type[len] = sig[i]; - - if (complete) - break; - } - - - if (direction) - g_string_append_printf(gstr, - "\t\t\t\n", - type, direction); - else - g_string_append_printf(gstr, - "\t\t\t\n", - type); - } -} - -static void generate_introspection_xml(DBusConnection *conn, - struct generic_data *data, - const char *path) -{ - GSList *list; - GString *gstr; - char **children; - int i; - - g_free(data->introspect); - - gstr = g_string_new(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE); - - g_string_append_printf(gstr, "\n", path); - - for (list = data->interfaces; list; list = list->next) { - struct interface_data *iface = list->data; - DBusMethodVTable *method; - DBusSignalVTable *signal; - DBusPropertyVTable *property; - - g_string_append_printf(gstr, "\t\n", iface->name); - - for (method = iface->methods; method && method->name; method++) { - /* debug("%s: adding method %s.%s", - path, iface->name, method->name); */ - if (!strlen(method->signature) && !strlen(method->reply)) - g_string_append_printf(gstr, "\t\t\n", - method->name); - else { - g_string_append_printf(gstr, "\t\t\n", - method->name); - print_arguments(gstr, method->signature, "in"); - print_arguments(gstr, method->reply, "out"); - g_string_append_printf(gstr, "\t\t\n"); - } - } - - for (signal = iface->signals; signal && signal->name; signal++) { - /* debug("%s: adding signal %s.%s", - path, iface->name, signal->name); */ - if (!strlen(signal->signature)) - g_string_append_printf(gstr, "\t\t\n", - signal->name); - else { - g_string_append_printf(gstr, "\t\t\n", - signal->name); - print_arguments(gstr, signal->signature, NULL); - g_string_append_printf(gstr, "\t\t\n"); - } - } - - for (property = iface->properties; property && property->name; property++) { - debug("%s: adding property %s.%s", - path, iface->name, property->name); - } - - g_string_append_printf(gstr, "\t\n"); - } - - if (!dbus_connection_list_registered(conn, path, &children)) - goto done; - - for (i = 0; children[i]; i++) - g_string_append_printf(gstr, "\t\n", children[i]); - - dbus_free_string_array(children); - -done: - g_string_append_printf(gstr, "\n"); - - data->introspect = g_string_free(gstr, FALSE); -} - -static DBusHandlerResult introspect(DBusConnection *connection, - DBusMessage *message, struct generic_data *data) -{ - DBusMessage *reply; - - if (!dbus_message_has_signature(message, DBUS_TYPE_INVALID_AS_STRING)) { - error("Unexpected signature to introspect call"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - - if (!data->introspect) - generate_introspection_xml(connection, data, - dbus_message_get_path(message)); - - reply = dbus_message_new_method_return(message); - if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - - dbus_message_append_args(reply, DBUS_TYPE_STRING, &data->introspect, - DBUS_TYPE_INVALID); - - return dbus_connection_send_and_unref(connection, reply); -} - -static void generic_unregister(DBusConnection *connection, void *user_data) -{ - struct generic_data *data = user_data; - - if (data->unregister_function) - data->unregister_function(connection, data->user_data); - - g_free(data->introspect); - g_free(data); -} - -static struct interface_data *find_interface(GSList *interfaces, - const char *name) -{ - GSList *list; - - for (list = interfaces; list; list = list->next) { - struct interface_data *iface = list->data; - if (!strcmp(name, iface->name)) - return iface; - } - - return NULL; -} - -static DBusHandlerResult generic_message(DBusConnection *connection, - DBusMessage *message, void *user_data) -{ - struct generic_data *data = user_data; - struct interface_data *iface; - DBusMethodVTable *current; - const char *interface; - - if (dbus_message_is_method_call(message, - DBUS_INTERFACE_INTROSPECTABLE, - "Introspect")) - return introspect(connection, message, data); - - interface = dbus_message_get_interface(message); - - iface = find_interface(data->interfaces, interface); - if (!iface) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - for (current = iface->methods; - current->name && current->message_function; current++) { - if (!dbus_message_is_method_call(message, iface->name, - current->name)) - continue; - - if (dbus_message_has_signature(message, current->signature)) { - debug("%s: %s.%s()", dbus_message_get_path(message), - iface->name, current->name); - return current->message_function(connection, - message, data->user_data); - } - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static DBusObjectPathVTable generic_table = { - .unregister_function = generic_unregister, - .message_function = generic_message, -}; - -static void invalidate_parent_data(DBusConnection *conn, const char *child_path) -{ - struct generic_data *data = NULL; - char *parent_path, *slash; - - parent_path = g_strdup(child_path); - slash = strrchr(parent_path, '/'); - if (!slash) - goto done; - - *slash = '\0'; - if (!strlen(parent_path)) - goto done; - - if (!dbus_connection_get_object_path_data(conn, parent_path, - (void *) &data)) - goto done; - - if (!data) - goto done; - - g_free(data->introspect); - data->introspect = NULL; - -done: - g_free(parent_path); -} - -dbus_bool_t dbus_connection_create_object_path(DBusConnection *connection, - const char *path, void *user_data, - DBusObjectPathUnregisterFunction function) -{ - struct generic_data *data; - - data = g_new0(struct generic_data, 1); - - data->user_data = user_data; - data->unregister_function = function; - - data->introspect = g_strdup(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE ""); - - if (!dbus_connection_register_object_path(connection, path, - &generic_table, data)) { - g_free(data->introspect); - g_free(data); - return FALSE; - } - - invalidate_parent_data(connection, path); - - return TRUE; -} - -dbus_bool_t dbus_connection_destroy_object_path(DBusConnection *connection, - const char *path) -{ - invalidate_parent_data(connection, path); - - return dbus_connection_unregister_object_path(connection, path); -} - -dbus_bool_t dbus_connection_get_object_user_data(DBusConnection *connection, - const char *path, - void **data_p) -{ - struct generic_data *data = NULL; - - if (!dbus_connection_get_object_path_data(connection, path, - (void *) &data) || !data) - return FALSE; - - *data_p = data->user_data; - - return TRUE; -} - -dbus_bool_t dbus_connection_register_interface(DBusConnection *connection, - const char *path, const char *name, - DBusMethodVTable *methods, - DBusSignalVTable *signals, - DBusPropertyVTable *properties) -{ - struct generic_data *data = NULL; - struct interface_data *iface; - - if (!dbus_connection_get_object_path_data(connection, path, - (void *) &data) || !data) - return FALSE; - - if (find_interface(data->interfaces, name)) - return FALSE; - - iface = g_new0(struct interface_data, 1); - - iface->name = g_strdup(name); - iface->methods = methods; - iface->signals = signals; - iface->properties = properties; - - data->interfaces = g_slist_append(data->interfaces, iface); - - g_free(data->introspect); - data->introspect = NULL; - - return TRUE; -} - -dbus_bool_t dbus_connection_unregister_interface(DBusConnection *connection, - const char *path, const char *name) -{ - struct generic_data *data = NULL; - struct interface_data *iface; - - if (!dbus_connection_get_object_path_data(connection, path, - (void *) &data) || !data) - return FALSE; - - iface = find_interface(data->interfaces, name); - if (!iface) - return FALSE; - - data->interfaces = g_slist_remove(data->interfaces, iface); - - g_free(iface->name); - g_free(iface); - - g_free(data->introspect); - data->introspect = NULL; - - return TRUE; -} - -void dbus_message_iter_append_variant(DBusMessageIter *iter, int type, void *val) -{ - DBusMessageIter value; - DBusMessageIter array; - char *sig; - - switch (type) { - case DBUS_TYPE_STRING: - sig = DBUS_TYPE_STRING_AS_STRING; - break; - case DBUS_TYPE_BYTE: - sig = DBUS_TYPE_BYTE_AS_STRING; - break; - case DBUS_TYPE_INT16: - sig = DBUS_TYPE_INT16_AS_STRING; - break; - case DBUS_TYPE_UINT16: - sig = DBUS_TYPE_UINT16_AS_STRING; - break; - case DBUS_TYPE_INT32: - sig = DBUS_TYPE_INT32_AS_STRING; - break; - case DBUS_TYPE_UINT32: - sig = DBUS_TYPE_UINT32_AS_STRING; - break; - case DBUS_TYPE_BOOLEAN: - sig = DBUS_TYPE_BOOLEAN_AS_STRING; - break; - case DBUS_TYPE_ARRAY: - sig = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING; - break; - case DBUS_TYPE_OBJECT_PATH: - sig = DBUS_TYPE_OBJECT_PATH_AS_STRING; - break; - default: - error("Could not append variant with type %d", type); - return; - } - - dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, sig, &value); - - if (type == DBUS_TYPE_ARRAY) { - int i; - const char ***str_array = val; - - dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY, - DBUS_TYPE_STRING_AS_STRING, &array); - - for (i = 0; (*str_array)[i]; i++) - dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, - &((*str_array)[i])); - - dbus_message_iter_close_container(&value, &array); - } else - dbus_message_iter_append_basic(&value, type, val); - - dbus_message_iter_close_container(iter, &value); -} - -void dbus_message_iter_append_dict_entry(DBusMessageIter *dict, - const char *key, int type, void *val) -{ - DBusMessageIter entry; - - dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, NULL, &entry); - - dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key); - - dbus_message_iter_append_variant(&entry, type, val); - - dbus_message_iter_close_container(dict, &entry); -} - -void dbus_message_iter_append_dict_valist(DBusMessageIter *iter, - const char *first_key, - va_list var_args) -{ - DBusMessageIter dict; - const char *key; - int type; - void *val; - - dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, - DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING - DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING - DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); - - key = first_key; - while (key) { - type = va_arg(var_args, int); - val = va_arg(var_args, void *); - dbus_message_iter_append_dict_entry(&dict, key, type, val); - key = va_arg(var_args, char *); - } - - dbus_message_iter_close_container(iter, &dict); -} - -void dbus_message_iter_append_dict(DBusMessageIter *iter, - const char *first_key, ...) -{ - va_list var_args; - - va_start(var_args, first_key); - dbus_message_iter_append_dict_valist(iter, first_key, var_args); - va_end(var_args); -} - -static gboolean check_signal(DBusConnection *conn, const char *path, - const char *interface, const char *name, - const char **args) -{ - struct generic_data *data = NULL; - struct interface_data *iface; - DBusSignalVTable *sig_data; - - *args = NULL; - if (!dbus_connection_get_object_path_data(conn, path, - (void *) &data) || !data) { - error("dbus_connection_emit_signal: path %s isn't registered", - path); - return FALSE; - } - - iface = find_interface(data->interfaces, interface); - - if (!iface) { - error("dbus_connection_emit_signal: %s does not implement %s", - path, interface); - return FALSE; - } - - for (sig_data = iface->signals; sig_data && sig_data->name; sig_data++) { - if (!strcmp(sig_data->name, name)) { - *args = sig_data->signature; - break; - } - } - - if (!*args) { - error("No signal named %s on interface %s", name, interface); - return FALSE; - } - - return TRUE; -} - -dbus_bool_t dbus_connection_emit_signal_valist(DBusConnection *conn, - const char *path, - const char *interface, - const char *name, - int first, - va_list var_args) -{ - DBusMessage *signal; - dbus_bool_t ret; - const char *signature, *args; - - if (!check_signal(conn, path, interface, name, &args)) - return FALSE; - - signal = dbus_message_new_signal(path, interface, name); - if (!signal) { - error("Unable to allocate new %s.%s signal", interface, name); - return FALSE; - } - - ret = dbus_message_append_args_valist(signal, first, var_args); - if (!ret) - goto fail; - - signature = dbus_message_get_signature(signal); - if (strcmp(args, signature) != 0) { - error("%s.%s: expected signature'%s' but got '%s'", - interface, name, args, signature); - ret = FALSE; - goto fail; - } - - ret = dbus_connection_send(conn, signal, NULL); -fail: - dbus_message_unref(signal); - - return ret; -} - -dbus_bool_t dbus_connection_emit_signal(DBusConnection *conn, const char *path, - const char *interface, const char *name, - int first, ...) -{ - dbus_bool_t ret; - va_list var_args; - - va_start(var_args, first); - ret = dbus_connection_emit_signal_valist(conn, path, interface, name, - first, var_args); - va_end(var_args); - - return ret; -} - -dbus_bool_t dbus_connection_emit_property_changed(DBusConnection *conn, - const char *path, - const char *interface, - const char *name, - int type, void *value) -{ - DBusMessage *signal; - DBusMessageIter iter; - gboolean ret; - const char *signature, *args; - - if (!check_signal(conn, path, interface, "PropertyChanged", &args)) - return FALSE; - - signal = dbus_message_new_signal(path, interface, "PropertyChanged"); - - if (!signal) { - error("Unable to allocate new %s.PropertyChanged signal", - interface); - return FALSE; - } - - dbus_message_iter_init_append(signal, &iter); - - dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name); - dbus_message_iter_append_variant(&iter, type, value); - - signature = dbus_message_get_signature(signal); - if (strcmp(args, signature) != 0) { - error("%s.%s: expected signature'%s' but got '%s'", - interface, name, args, signature); - ret = FALSE; - goto fail; - } - - ret = dbus_connection_send(conn, signal, NULL); - -fail: - dbus_message_unref(signal); - return ret; -} diff --git a/common/dbus-helper.h b/common/dbus-helper.h deleted file mode 100644 index 6c3c3a89..00000000 --- a/common/dbus-helper.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2008 Marcel Holtmann - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include -#include - -#define DBUS_TYPE_STRING_ARRAY_AS_STRING (DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING) -#define DBUS_TYPE_BYTE_ARRAY_AS_STRING (DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING) - -DBusHandlerResult dbus_connection_send_and_unref(DBusConnection *connection, - DBusMessage *message); - -dbus_bool_t dbus_connection_create_object_path(DBusConnection *connection, - const char *path, void *user_data, - DBusObjectPathUnregisterFunction function); - -dbus_bool_t dbus_connection_destroy_object_path(DBusConnection *connection, - const char *path); - -dbus_bool_t dbus_connection_get_object_user_data(DBusConnection *connection, - const char *path, - void **data_p); - -typedef struct DBusMethodVTable DBusMethodVTable; - -struct DBusMethodVTable { - const char *name; - DBusObjectPathMessageFunction message_function; - const char *signature; - const char *reply; -}; - -typedef struct DBusSignalVTable DBusSignalVTable; - -struct DBusSignalVTable { - const char *name; - const char *signature; -}; - -typedef struct DBusPropertyVTable DBusPropertyVTable; - -struct DBusPropertyVTable { - const char *name; -}; - -dbus_bool_t dbus_connection_register_interface(DBusConnection *connection, - const char *path, const char *name, - DBusMethodVTable *methods, - DBusSignalVTable *signals, - DBusPropertyVTable *properties); - -dbus_bool_t dbus_connection_unregister_interface(DBusConnection *connection, - const char *path, const char *name); -void dbus_message_iter_append_variant(DBusMessageIter *iter, int type, void *val); -void dbus_message_iter_append_dict_entry(DBusMessageIter *dict, - const char *key, int type, void *val); -void dbus_message_iter_append_dict_valist(DBusMessageIter *iter, - const char *first_key, - va_list var_args); -void dbus_message_iter_append_dict(DBusMessageIter *iter, - const char *first_key, ...); -dbus_bool_t dbus_connection_emit_signal(DBusConnection *conn, const char *path, - const char *interface, const char *name, - int first, ...); - -dbus_bool_t dbus_connection_emit_signal_valist(DBusConnection *conn, - const char *path, - const char *interface, - const char *name, - int first, - va_list var_args); -dbus_bool_t dbus_connection_emit_property_changed(DBusConnection *conn, - const char *path, - const char *interface, - const char *name, - int type, void *value); - -static inline DBusHandlerResult send_message_and_unref(DBusConnection *conn, - DBusMessage *msg) -{ - if (msg) { - dbus_connection_send(conn, msg, NULL); - dbus_message_unref(msg); - } - - return DBUS_HANDLER_RESULT_HANDLED; -} diff --git a/common/error.c b/common/error.c index 58999393..656c7299 100644 --- a/common/error.c +++ b/common/error.c @@ -31,7 +31,8 @@ #include #include -#include "dbus-helper.h" +#include + #include "error.h" /** -- cgit From eac653286a4619a0b28614cdde1506997e5d6023 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Mon, 12 May 2008 21:21:47 +0000 Subject: introduce bt_rfcomm_listen. --- common/glib-helper.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++--- common/glib-helper.h | 2 + 2 files changed, 128 insertions(+), 8 deletions(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index 36228d45..1eafbb98 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -365,6 +365,63 @@ GSList *bt_string2list(const gchar *str) return l; } +static gboolean listen_cb(GIOChannel *chan, GIOCondition cond, + struct io_context *io_ctxt) +{ + int srv_sk, cli_sk, err = 0, ret; + GIOChannel *io; + socklen_t len; + struct sockaddr_rc addr; + + if (cond & G_IO_NVAL) + return FALSE; + + len = sizeof(ret); + if (cond & (G_IO_HUP | G_IO_ERR)) { + g_io_channel_close(chan); + g_io_channel_unref(chan); + g_free(io_ctxt); + return FALSE; + } + + srv_sk = g_io_channel_unix_get_fd(chan); + + len = sizeof(struct sockaddr_rc); + cli_sk = accept(srv_sk, (struct sockaddr *) &addr, &len); + if (cli_sk < 0) { + if (io_ctxt->cb) + io_ctxt->cb(NULL, -errno, io_ctxt->user_data); + return TRUE; + } + + io = g_io_channel_unix_new(cli_sk); + if (!io) + err = -ENOMEM; + + if (io_ctxt->cb) + io_ctxt->cb(io, err, io_ctxt->user_data); + + return TRUE; +} + +static int transport_listen(struct io_context *io_ctxt, int fd) +{ + int err; + + err = listen(fd, 1); + if (err < 0) + return -errno; + + io_ctxt->io = g_io_channel_unix_new(fd); + if (!io_ctxt->io) + return -ENOMEM; + + g_io_add_watch(io_ctxt->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, + (GIOFunc) listen_cb, io_ctxt); + + return 0; +} + static gboolean connect_cb(GIOChannel *io, GIOCondition cond, struct io_context *io_ctxt) { @@ -504,26 +561,68 @@ static int l2cap_connect(struct io_context *io_ctxt, const bdaddr_t *src, return 0; } -static int rfcomm_connect(struct io_context *io_ctxt, const bdaddr_t *src, - const bdaddr_t *dst, uint8_t channel) +static int rfcomm_bind(struct io_context *io_ctxt, const bdaddr_t *src, + uint8_t channel, uint32_t flags, + struct sockaddr_rc *addr) { - struct sockaddr_rc addr; - int sk, err; + int sk, err, opt; sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); if (sk < 0) return -errno; - memset(&addr, 0, sizeof(addr)); - addr.rc_family = AF_BLUETOOTH; - bacpy(&addr.rc_bdaddr, src); + if (flags) { + opt = flags; + err = setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &opt, sizeof(opt)); + if (err < 0) { + close(sk); + return -errno; + } + } - err = bind(sk, (struct sockaddr *) &addr, sizeof(addr)); + memset(addr, 0, sizeof(*addr)); + addr->rc_family = AF_BLUETOOTH; + bacpy(&addr->rc_bdaddr, src); + addr->rc_channel = channel; + + err = bind(sk, (struct sockaddr *) addr, sizeof(*addr)); if (err < 0) { close(sk); return -errno; } + return sk; +} + +static int rfcomm_listen(struct io_context *io_ctxt, const bdaddr_t *src, + uint8_t channel, uint32_t flags) +{ + struct sockaddr_rc addr; + int sk, err; + + sk = rfcomm_bind(io_ctxt, src, channel, flags, &addr); + if (sk < 0) + return sk; + + err = transport_listen(io_ctxt, sk); + if (err < 0) { + close(sk); + return err; + } + + return 0; +} + +static int rfcomm_connect(struct io_context *io_ctxt, const bdaddr_t *src, + const bdaddr_t *dst, uint8_t channel) +{ + struct sockaddr_rc addr; + int sk, err; + + sk = rfcomm_bind(io_ctxt, src, 0, 0, &addr); + if (sk < 0) + return sk; + memset(&addr, 0, sizeof(addr)); addr.rc_family = AF_BLUETOOTH; bacpy(&addr.rc_bdaddr, dst); @@ -561,6 +660,25 @@ static void io_context_cleanup(struct io_context *io_ctxt) g_free(io_ctxt); } +GIOChannel *bt_rfcomm_listen(const bdaddr_t *src, uint8_t channel, uint32_t flags, + bt_io_callback_t cb, void *user_data) +{ + struct io_context *io_ctxt; + int err; + + err = create_io_context(&io_ctxt, cb, user_data); + if (err < 0) + return NULL; + + err = rfcomm_listen(io_ctxt, src, channel, flags); + if (err < 0) { + io_context_cleanup(io_ctxt); + return NULL; + } + + return io_ctxt->io; +} + int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel, bt_io_callback_t cb, void *user_data) { diff --git a/common/glib-helper.h b/common/glib-helper.h index 7a312005..71ed67b8 100644 --- a/common/glib-helper.h +++ b/common/glib-helper.h @@ -38,6 +38,8 @@ gchar *bt_uuid2string(uuid_t *uuid); gchar *bt_list2string(GSList *list); GSList *bt_string2list(const gchar *str); +GIOChannel *bt_rfcomm_listen(const bdaddr_t *src, uint8_t channel, + uint32_t flags, bt_io_callback_t cb, void *user_data); int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel, bt_io_callback_t cb, void *user_data); int bt_l2cap_connect(const bdaddr_t *src, const bdaddr_t *dst, -- cgit From efeeab95ad87e827c2a801186754df868b598242 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 13 May 2008 18:18:02 +0000 Subject: Introduce bt_l2cap_listen. --- common/glib-helper.c | 90 +++++++++++++++++++++++++++++++++++++++++++--------- common/glib-helper.h | 3 ++ 2 files changed, 78 insertions(+), 15 deletions(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index 1eafbb98..798f8a64 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -515,37 +515,78 @@ static int sco_connect(struct io_context *io_ctxt, const bdaddr_t *src, return 0; } -static int l2cap_connect(struct io_context *io_ctxt, const bdaddr_t *src, - const bdaddr_t *dst, uint16_t psm, - uint16_t mtu) +static int l2cap_bind(struct io_context *io_ctxt, const bdaddr_t *src, + uint16_t psm, uint16_t mtu, uint32_t flags, + struct sockaddr_l2 *addr) { - struct l2cap_options l2o; - socklen_t olen; - struct sockaddr_l2 l2a; int sk, err; + struct l2cap_options l2o; - sk = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); + sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); if (sk < 0) return -errno; if (mtu) { - memset(&l2o, 0, sizeof(l2o)); - olen = sizeof(l2o); + socklen_t olen = sizeof(l2o); + memset(&l2o, 0, olen); getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &olen); l2o.imtu = l2o.omtu = mtu; setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, sizeof(l2o)); } - memset(&l2a, 0, sizeof(l2a)); - l2a.l2_family = AF_BLUETOOTH; - bacpy(&l2a.l2_bdaddr, src); + if (flags) { + int opt = flags; + err = setsockopt(sk, SOL_L2CAP, L2CAP_LM, &opt, sizeof(opt)); + if (err < 0) { + close(sk); + return -errno; + } + } + + memset(addr, 0, sizeof(*addr)); + addr->l2_family = AF_BLUETOOTH; + bacpy(&addr->l2_bdaddr, src); + addr->l2_psm = htobs(psm); - err = bind(sk, (struct sockaddr *) &l2a, sizeof(l2a)); + err = bind(sk, (struct sockaddr *) addr, sizeof(*addr)); if (err < 0) { close(sk); return -errno; } + return sk; +} + +static int l2cap_listen(struct io_context *io_ctxt, const bdaddr_t *src, + uint16_t psm, uint16_t mtu, uint32_t flags) +{ + struct sockaddr_l2 addr; + int sk, err; + + sk = l2cap_bind(io_ctxt, src, psm, mtu, flags, &addr); + if (sk < 0) + return sk; + + err = transport_listen(io_ctxt, sk); + if (err < 0) { + close(sk); + return err; + } + + return 0; +} + +static int l2cap_connect(struct io_context *io_ctxt, const bdaddr_t *src, + const bdaddr_t *dst, uint16_t psm, + uint16_t mtu) +{ + struct sockaddr_l2 l2a; + int sk, err; + + sk = l2cap_bind(io_ctxt, src, 0, mtu, 0, &l2a); + if (sk < 0) + return sk; + memset(&l2a, 0, sizeof(l2a)); l2a.l2_family = AF_BLUETOOTH; bacpy(&l2a.l2_bdaddr, dst); @@ -565,14 +606,14 @@ static int rfcomm_bind(struct io_context *io_ctxt, const bdaddr_t *src, uint8_t channel, uint32_t flags, struct sockaddr_rc *addr) { - int sk, err, opt; + int sk, err; sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); if (sk < 0) return -errno; if (flags) { - opt = flags; + int opt = flags; err = setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &opt, sizeof(opt)); if (err < 0) { close(sk); @@ -698,6 +739,25 @@ int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, return 0; } +GIOChannel *bt_l2cap_listen(const bdaddr_t *src, uint16_t psm, uint16_t mtu, + uint32_t flags, bt_io_callback_t cb, void *user_data) +{ + struct io_context *io_ctxt; + int err; + + err = create_io_context(&io_ctxt, cb, user_data); + if (err < 0) + return NULL; + + err = l2cap_listen(io_ctxt, src, psm, mtu, flags); + if (err < 0) { + io_context_cleanup(io_ctxt); + return NULL; + } + + return io_ctxt->io; +} + int bt_l2cap_connect(const bdaddr_t *src, const bdaddr_t *dst, uint16_t psm, uint16_t mtu, bt_io_callback_t cb, void *user_data) { diff --git a/common/glib-helper.h b/common/glib-helper.h index 71ed67b8..ddc57d4b 100644 --- a/common/glib-helper.h +++ b/common/glib-helper.h @@ -42,6 +42,9 @@ GIOChannel *bt_rfcomm_listen(const bdaddr_t *src, uint8_t channel, uint32_t flags, bt_io_callback_t cb, void *user_data); int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel, bt_io_callback_t cb, void *user_data); + +GIOChannel *bt_l2cap_listen(const bdaddr_t *src, uint16_t psm, uint16_t mtu, + uint32_t flags, bt_io_callback_t cb, void *user_data); int bt_l2cap_connect(const bdaddr_t *src, const bdaddr_t *dst, uint16_t psm, uint16_t mtu, bt_io_callback_t cb, void *user_data); -- cgit From 00869eb23b642c63a20998575aa4497baad5a3d1 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 13 May 2008 23:08:40 +0000 Subject: Fix bug on l2cap_bind and some code cleanup. --- common/glib-helper.c | 103 ++++++++++++++++++++++++++------------------------- 1 file changed, 53 insertions(+), 50 deletions(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index 798f8a64..93ef262c 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -63,6 +63,7 @@ int set_nonblocking(int fd) } struct io_context { + int fd; GIOChannel *io; bt_io_callback_t cb; gpointer user_data; @@ -404,15 +405,15 @@ static gboolean listen_cb(GIOChannel *chan, GIOCondition cond, return TRUE; } -static int transport_listen(struct io_context *io_ctxt, int fd) +static int transport_listen(struct io_context *io_ctxt) { int err; - err = listen(fd, 1); + err = listen(io_ctxt->fd, 1); if (err < 0) return -errno; - io_ctxt->io = g_io_channel_unix_new(fd); + io_ctxt->io = g_io_channel_unix_new(io_ctxt->fd); if (!io_ctxt->io) return -ENOMEM; @@ -458,12 +459,12 @@ done: return FALSE; } -static int transport_connect(struct io_context *io_ctxt, int fd, - struct sockaddr *addr, socklen_t addrlen) +static int transport_connect(struct io_context *io_ctxt, struct sockaddr *addr, + socklen_t addrlen) { int err; - io_ctxt->io = g_io_channel_unix_new(fd); + io_ctxt->io = g_io_channel_unix_new(io_ctxt->fd); if (!io_ctxt->io) return -ENOMEM; @@ -471,7 +472,7 @@ static int transport_connect(struct io_context *io_ctxt, int fd, if (err != G_IO_STATUS_NORMAL) return -EPERM; - err = connect(fd, addr, addrlen); + err = connect(io_ctxt->fd, addr, addrlen); if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) return -errno; @@ -505,7 +506,7 @@ static int sco_connect(struct io_context *io_ctxt, const bdaddr_t *src, addr.sco_family = AF_BLUETOOTH; bacpy(&addr.sco_bdaddr, dst); - err = transport_connect(io_ctxt, sk, (struct sockaddr *) &addr, + err = transport_connect(io_ctxt, (struct sockaddr *) &addr, sizeof(addr)); if (err < 0) { close(sk); @@ -519,26 +520,27 @@ static int l2cap_bind(struct io_context *io_ctxt, const bdaddr_t *src, uint16_t psm, uint16_t mtu, uint32_t flags, struct sockaddr_l2 *addr) { - int sk, err; + int err; struct l2cap_options l2o; - sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); - if (sk < 0) + io_ctxt->fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); + if (io_ctxt->fd < 0) return -errno; if (mtu) { socklen_t olen = sizeof(l2o); memset(&l2o, 0, olen); - getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &olen); + getsockopt(io_ctxt->fd, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &olen); l2o.imtu = l2o.omtu = mtu; - setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, sizeof(l2o)); + setsockopt(io_ctxt->fd, SOL_L2CAP, L2CAP_OPTIONS, &l2o, sizeof(l2o)); } if (flags) { int opt = flags; - err = setsockopt(sk, SOL_L2CAP, L2CAP_LM, &opt, sizeof(opt)); + err = setsockopt(io_ctxt->fd, SOL_L2CAP, L2CAP_LM, &opt, + sizeof(opt)); if (err < 0) { - close(sk); + close(io_ctxt->fd); return -errno; } } @@ -548,28 +550,28 @@ static int l2cap_bind(struct io_context *io_ctxt, const bdaddr_t *src, bacpy(&addr->l2_bdaddr, src); addr->l2_psm = htobs(psm); - err = bind(sk, (struct sockaddr *) addr, sizeof(*addr)); + err = bind(io_ctxt->fd, (struct sockaddr *) addr, sizeof(*addr)); if (err < 0) { - close(sk); + close(io_ctxt->fd); return -errno; } - return sk; + return 0; } static int l2cap_listen(struct io_context *io_ctxt, const bdaddr_t *src, uint16_t psm, uint16_t mtu, uint32_t flags) { struct sockaddr_l2 addr; - int sk, err; + int err; - sk = l2cap_bind(io_ctxt, src, psm, mtu, flags, &addr); - if (sk < 0) - return sk; + err = l2cap_bind(io_ctxt, src, psm, mtu, flags, &addr); + if (err < 0) + return err; - err = transport_listen(io_ctxt, sk); + err = transport_listen(io_ctxt); if (err < 0) { - close(sk); + close(io_ctxt->fd); return err; } @@ -581,21 +583,21 @@ static int l2cap_connect(struct io_context *io_ctxt, const bdaddr_t *src, uint16_t mtu) { struct sockaddr_l2 l2a; - int sk, err; + int err; - sk = l2cap_bind(io_ctxt, src, 0, mtu, 0, &l2a); - if (sk < 0) - return sk; + err = l2cap_bind(io_ctxt, src, 0, mtu, 0, &l2a); + if (err < 0) + return err; memset(&l2a, 0, sizeof(l2a)); l2a.l2_family = AF_BLUETOOTH; bacpy(&l2a.l2_bdaddr, dst); l2a.l2_psm = htobs(psm); - err = transport_connect(io_ctxt, sk, (struct sockaddr *) &l2a, + err = transport_connect(io_ctxt, (struct sockaddr *) &l2a, sizeof(l2a)); if (err < 0) { - close(sk); + close(io_ctxt->fd); return err; } @@ -606,17 +608,18 @@ static int rfcomm_bind(struct io_context *io_ctxt, const bdaddr_t *src, uint8_t channel, uint32_t flags, struct sockaddr_rc *addr) { - int sk, err; + int err; - sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); - if (sk < 0) + io_ctxt->fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); + if ( io_ctxt->fd < 0) return -errno; if (flags) { int opt = flags; - err = setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &opt, sizeof(opt)); + err = setsockopt(io_ctxt->fd, SOL_RFCOMM, RFCOMM_LM, &opt, + sizeof(opt)); if (err < 0) { - close(sk); + close(io_ctxt->fd); return -errno; } } @@ -626,28 +629,28 @@ static int rfcomm_bind(struct io_context *io_ctxt, const bdaddr_t *src, bacpy(&addr->rc_bdaddr, src); addr->rc_channel = channel; - err = bind(sk, (struct sockaddr *) addr, sizeof(*addr)); + err = bind(io_ctxt->fd, (struct sockaddr *) addr, sizeof(*addr)); if (err < 0) { - close(sk); + close(io_ctxt->fd); return -errno; } - return sk; + return 0; } static int rfcomm_listen(struct io_context *io_ctxt, const bdaddr_t *src, uint8_t channel, uint32_t flags) { struct sockaddr_rc addr; - int sk, err; + int err; - sk = rfcomm_bind(io_ctxt, src, channel, flags, &addr); - if (sk < 0) - return sk; + err = rfcomm_bind(io_ctxt, src, channel, flags, &addr); + if (err < 0) + return err; - err = transport_listen(io_ctxt, sk); + err = transport_listen(io_ctxt); if (err < 0) { - close(sk); + close(io_ctxt->fd); return err; } @@ -658,21 +661,21 @@ static int rfcomm_connect(struct io_context *io_ctxt, const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel) { struct sockaddr_rc addr; - int sk, err; + int err; - sk = rfcomm_bind(io_ctxt, src, 0, 0, &addr); - if (sk < 0) - return sk; + err = rfcomm_bind(io_ctxt, src, 0, 0, &addr); + if (err < 0) + return err; memset(&addr, 0, sizeof(addr)); addr.rc_family = AF_BLUETOOTH; bacpy(&addr.rc_bdaddr, dst); addr.rc_channel = channel; - err = transport_connect(io_ctxt, sk, (struct sockaddr *) &addr, + err = transport_connect(io_ctxt, (struct sockaddr *) &addr, sizeof(addr)); if (err < 0) { - close(sk); + close(io_ctxt->fd); return err; } -- cgit From 0094809955895c974fbe95f2d3ed13f420a6a6ed Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 14 May 2008 22:16:16 +0000 Subject: Make bt_io_callback_t to take both source and destination. --- common/glib-helper.c | 142 ++++++++++++++++++++++++++++++++++++++++++--------- common/glib-helper.h | 3 +- 2 files changed, 119 insertions(+), 26 deletions(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index 93ef262c..69b23d4c 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -43,6 +43,8 @@ #include "glib-helper.h" +typedef int (*resolver_t) (int fd, bdaddr_t *src, bdaddr_t *dst); + int set_nonblocking(int fd) { long arg; @@ -66,6 +68,7 @@ struct io_context { int fd; GIOChannel *io; bt_io_callback_t cb; + resolver_t resolver; gpointer user_data; }; @@ -366,18 +369,91 @@ GSList *bt_string2list(const gchar *str) return l; } +static inline int resolve_names(int fd, struct sockaddr *host, + struct sockaddr *peer, socklen_t len) +{ + int err; + socklen_t namelen; + + namelen = len; + err = getsockname(fd, host, &namelen); + if (err < 0) + return err; + + namelen = len; + err = getpeername(fd, peer, &namelen); + if (err < 0) + return err; + + return 0; +} + +static int rfcomm_resolver(int fd, bdaddr_t *src, bdaddr_t *dst) +{ + struct sockaddr_rc host, peer; + socklen_t len; + int err; + + len = sizeof(host); + err = resolve_names(fd, (struct sockaddr *) &host, + (struct sockaddr *) &peer, len); + if (err < 0) + return err; + + bacpy(src, &host.rc_bdaddr); + bacpy(dst, &peer.rc_bdaddr); + + return 0; +} + +static int l2cap_resolver(int fd, bdaddr_t *src, bdaddr_t *dst) +{ + struct sockaddr_l2 host, peer; + socklen_t len; + int err; + + len = sizeof(host); + err = resolve_names(fd, (struct sockaddr *) &host, + (struct sockaddr *) &peer, len); + if (err < 0) + return err; + + bacpy(src, &host.l2_bdaddr); + bacpy(dst, &peer.l2_bdaddr); + + return 0; +} + +static int sco_resolver(int fd, bdaddr_t *src, bdaddr_t *dst) +{ + struct sockaddr_sco host, peer; + socklen_t len; + int err; + + len = sizeof(host); + err = resolve_names(fd, (struct sockaddr *) &host, + (struct sockaddr *) &peer, len); + if (err < 0) + return err; + + bacpy(src, &host.sco_bdaddr); + bacpy(dst, &peer.sco_bdaddr); + + return 0; +} + static gboolean listen_cb(GIOChannel *chan, GIOCondition cond, struct io_context *io_ctxt) { - int srv_sk, cli_sk, err = 0, ret; + int fd, err = 0; GIOChannel *io; + struct sockaddr addr; socklen_t len; - struct sockaddr_rc addr; + bdaddr_t src, dst; if (cond & G_IO_NVAL) return FALSE; - len = sizeof(ret); if (cond & (G_IO_HUP | G_IO_ERR)) { g_io_channel_close(chan); g_io_channel_unref(chan); @@ -385,22 +461,31 @@ static gboolean listen_cb(GIOChannel *chan, GIOCondition cond, return FALSE; } - srv_sk = g_io_channel_unix_get_fd(chan); + len = sizeof(addr); + fd = accept(io_ctxt->fd, &addr, &len); + if (fd < 0) + goto drop; - len = sizeof(struct sockaddr_rc); - cli_sk = accept(srv_sk, (struct sockaddr *) &addr, &len); - if (cli_sk < 0) { - if (io_ctxt->cb) - io_ctxt->cb(NULL, -errno, io_ctxt->user_data); - return TRUE; + if (io_ctxt->resolver) { + err = io_ctxt->resolver(fd, &src, &dst); + if (err < 0) { + close(fd); + goto drop; + } } - io = g_io_channel_unix_new(cli_sk); + io = g_io_channel_unix_new(fd); if (!io) err = -ENOMEM; if (io_ctxt->cb) - io_ctxt->cb(io, err, io_ctxt->user_data); + io_ctxt->cb(io, err, &src, &dst, io_ctxt->user_data); + + return TRUE; + +drop: + if (io_ctxt->cb) + io_ctxt->cb(NULL, -errno, NULL, NULL, io_ctxt->user_data); return TRUE; } @@ -426,16 +511,15 @@ static int transport_listen(struct io_context *io_ctxt) static gboolean connect_cb(GIOChannel *io, GIOCondition cond, struct io_context *io_ctxt) { - int sk, err = 0, ret; + int err = 0, ret; socklen_t len; + bdaddr_t src, dst; if (cond & G_IO_NVAL) return FALSE; - sk = g_io_channel_unix_get_fd(io); - len = sizeof(ret); - if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) { + if (getsockopt(io_ctxt->fd, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) { err = -errno; goto done; } @@ -445,11 +529,17 @@ static gboolean connect_cb(GIOChannel *io, GIOCondition cond, goto done; } + if (io_ctxt->resolver) { + err = io_ctxt->resolver(io_ctxt->fd, &src, &dst); + if (err < 0) + goto done; + } + io_ctxt->io = NULL; done: if (io_ctxt->cb) - io_ctxt->cb(io, err, io_ctxt->user_data); + io_ctxt->cb(io, err, &src, &dst, io_ctxt->user_data); if (io_ctxt->io) { g_io_channel_close(io_ctxt->io); g_io_channel_unref(io_ctxt->io); @@ -682,14 +772,15 @@ static int rfcomm_connect(struct io_context *io_ctxt, const bdaddr_t *src, return 0; } -static int create_io_context(struct io_context **io_ctxt, bt_io_callback_t cb, - void *user_data) +static int create_io_context(struct io_context **io_ctxt, gpointer cb, + gpointer resolver, gpointer user_data) { *io_ctxt = g_try_malloc0(sizeof(struct search_context)); if (!*io_ctxt) return -ENOMEM; (*io_ctxt)->cb = cb; + (*io_ctxt)->resolver = resolver; (*io_ctxt)->user_data = user_data; return 0; @@ -710,7 +801,7 @@ GIOChannel *bt_rfcomm_listen(const bdaddr_t *src, uint8_t channel, uint32_t flag struct io_context *io_ctxt; int err; - err = create_io_context(&io_ctxt, cb, user_data); + err = create_io_context(&io_ctxt, cb, rfcomm_resolver, user_data); if (err < 0) return NULL; @@ -729,7 +820,7 @@ int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, struct io_context *io_ctxt; int err; - err = create_io_context(&io_ctxt, cb, user_data); + err = create_io_context(&io_ctxt, cb, rfcomm_resolver, user_data); if (err < 0) return err; @@ -748,7 +839,7 @@ GIOChannel *bt_l2cap_listen(const bdaddr_t *src, uint16_t psm, uint16_t mtu, struct io_context *io_ctxt; int err; - err = create_io_context(&io_ctxt, cb, user_data); + err = create_io_context(&io_ctxt, cb, l2cap_resolver, user_data); if (err < 0) return NULL; @@ -762,12 +853,13 @@ GIOChannel *bt_l2cap_listen(const bdaddr_t *src, uint16_t psm, uint16_t mtu, } int bt_l2cap_connect(const bdaddr_t *src, const bdaddr_t *dst, - uint16_t psm, uint16_t mtu, bt_io_callback_t cb, void *user_data) + uint16_t psm, uint16_t mtu, bt_io_callback_t cb, + void *user_data) { struct io_context *io_ctxt; int err; - err = create_io_context(&io_ctxt, cb, user_data); + err = create_io_context(&io_ctxt, cb, l2cap_resolver, user_data); if (err < 0) return err; @@ -786,7 +878,7 @@ int bt_sco_connect(const bdaddr_t *src, const bdaddr_t *dst, struct io_context *io_ctxt; int err; - err = create_io_context(&io_ctxt, cb, user_data); + err = create_io_context(&io_ctxt, cb, sco_resolver, user_data); if (err < 0) return err; diff --git a/common/glib-helper.h b/common/glib-helper.h index ddc57d4b..1db329ca 100644 --- a/common/glib-helper.h +++ b/common/glib-helper.h @@ -23,7 +23,8 @@ int set_nonblocking(int fd); -typedef void (*bt_io_callback_t) (GIOChannel *io, int err, gpointer user_data); +typedef void (*bt_io_callback_t) (GIOChannel *io, int err, const bdaddr_t *src, + const bdaddr_t *dst, gpointer user_data); typedef void (*bt_callback_t) (sdp_list_t *recs, int err, gpointer user_data); typedef void (*bt_destroy_t) (gpointer user_data); -- cgit From b0151710a8127f566d4d1dde35c9896e0938e025 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 14 May 2008 22:51:11 +0000 Subject: Initialize sockaddr variables before using them. --- common/glib-helper.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index 69b23d4c..d43a3cf7 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -376,11 +376,13 @@ static inline int resolve_names(int fd, struct sockaddr *host, socklen_t namelen; namelen = len; + memset(host, 0, len); err = getsockname(fd, host, &namelen); if (err < 0) return err; namelen = len; + memset(peer, 0, len); err = getpeername(fd, peer, &namelen); if (err < 0) return err; @@ -462,6 +464,7 @@ static gboolean listen_cb(GIOChannel *chan, GIOCondition cond, } len = sizeof(addr); + memset(&addr, 0, len); fd = accept(io_ctxt->fd, &addr, &len); if (fd < 0) goto drop; -- cgit From 497dd72d04902511120a03b0f66333642426be47 Mon Sep 17 00:00:00 2001 From: Cidorvan Leite Date: Thu, 15 May 2008 13:17:42 +0000 Subject: Added function for convert string to uuid128 --- common/glib-helper.c | 36 ++++++++++++++++++++++++++++++++++++ common/glib-helper.h | 1 + 2 files changed, 37 insertions(+) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index d43a3cf7..ef5a1d13 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -325,6 +325,42 @@ char *bt_uuid2string(uuid_t *uuid) return str; } +int bt_string2uuid(uuid_t *uuid, const char *string) +{ + uint16_t data1, data2, data3, data5; + uint32_t data0, data4; + + if (strlen(string) == 36 && + string[8] == '-' && + string[13] == '-' && + string[18] == '-' && + string[23] == '-' && + sscanf(string, "%08x-%04hx-%04hx-%04hx-%08x%04hx", + &data0, &data1, &data2, &data3, &data4, &data5) == 6) { + uint8_t val[16]; + + data0 = htonl(data0); + data1 = htons(data1); + data2 = htons(data2); + data3 = htons(data3); + data4 = htonl(data4); + data5 = htons(data5); + + memcpy(&val[0], &data0, 4); + memcpy(&val[4], &data1, 2); + memcpy(&val[6], &data2, 2); + memcpy(&val[8], &data3, 2); + memcpy(&val[10], &data4, 4); + memcpy(&val[14], &data5, 2); + + sdp_uuid128_create(uuid, val); + + return 0; + } + + return -1; +} + gchar *bt_list2string(GSList *list) { GSList *l; diff --git a/common/glib-helper.h b/common/glib-helper.h index 1db329ca..23a04046 100644 --- a/common/glib-helper.h +++ b/common/glib-helper.h @@ -36,6 +36,7 @@ int bt_search_service(const bdaddr_t *src, const bdaddr_t *dst, bt_destroy_t destroy); gchar *bt_uuid2string(uuid_t *uuid); +int bt_string2uuid(uuid_t *uuid, const char *string); gchar *bt_list2string(GSList *list); GSList *bt_string2list(const gchar *str); -- cgit From 3cb3d3d7e4aa089dd5840980c8846927631757f6 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 16 May 2008 22:25:51 +0000 Subject: Introduce bt_rfcomm_listen_allocate. --- common/glib-helper.c | 32 +++++++++++++++++++++++++++----- common/glib-helper.h | 2 ++ 2 files changed, 29 insertions(+), 5 deletions(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index ef5a1d13..59293334 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -734,7 +734,7 @@ static int l2cap_connect(struct io_context *io_ctxt, const bdaddr_t *src, } static int rfcomm_bind(struct io_context *io_ctxt, const bdaddr_t *src, - uint8_t channel, uint32_t flags, + uint8_t *channel, uint32_t flags, struct sockaddr_rc *addr) { int err; @@ -756,7 +756,7 @@ static int rfcomm_bind(struct io_context *io_ctxt, const bdaddr_t *src, memset(addr, 0, sizeof(*addr)); addr->rc_family = AF_BLUETOOTH; bacpy(&addr->rc_bdaddr, src); - addr->rc_channel = channel; + addr->rc_channel = *channel; err = bind(io_ctxt->fd, (struct sockaddr *) addr, sizeof(*addr)); if (err < 0) { @@ -764,11 +764,13 @@ static int rfcomm_bind(struct io_context *io_ctxt, const bdaddr_t *src, return -errno; } + *channel = addr->rc_channel; + return 0; } static int rfcomm_listen(struct io_context *io_ctxt, const bdaddr_t *src, - uint8_t channel, uint32_t flags) + uint8_t *channel, uint32_t flags) { struct sockaddr_rc addr; int err; @@ -834,8 +836,8 @@ static void io_context_cleanup(struct io_context *io_ctxt) g_free(io_ctxt); } -GIOChannel *bt_rfcomm_listen(const bdaddr_t *src, uint8_t channel, uint32_t flags, - bt_io_callback_t cb, void *user_data) +GIOChannel *rfcomm_listen_internal(const bdaddr_t *src, uint8_t *channel, + uint32_t flags, bt_io_callback_t cb, void *user_data) { struct io_context *io_ctxt; int err; @@ -853,6 +855,26 @@ GIOChannel *bt_rfcomm_listen(const bdaddr_t *src, uint8_t channel, uint32_t flag return io_ctxt->io; } +GIOChannel *bt_rfcomm_listen_allocate(const bdaddr_t *src, uint8_t *channel, + uint32_t flags, bt_io_callback_t cb, void *user_data) +{ + if (!channel) + return NULL; + + *channel = 0; + + return rfcomm_listen_internal(src, channel, flags, cb, user_data); +} + +GIOChannel *bt_rfcomm_listen(const bdaddr_t *src, uint8_t channel, + uint32_t flags, bt_io_callback_t cb, void *user_data) +{ + if (channel < 1 || channel > 30) + return NULL; + + return rfcomm_listen_internal(src, &channel, flags, cb, user_data); +} + int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel, bt_io_callback_t cb, void *user_data) { diff --git a/common/glib-helper.h b/common/glib-helper.h index 23a04046..8d346b49 100644 --- a/common/glib-helper.h +++ b/common/glib-helper.h @@ -42,6 +42,8 @@ GSList *bt_string2list(const gchar *str); GIOChannel *bt_rfcomm_listen(const bdaddr_t *src, uint8_t channel, uint32_t flags, bt_io_callback_t cb, void *user_data); +GIOChannel *bt_rfcomm_listen_allocate(const bdaddr_t *src, uint8_t *channel, + uint32_t flags, bt_io_callback_t cb, void *user_data); int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel, bt_io_callback_t cb, void *user_data); -- cgit From f475b6c9b0de7c06d64b5ba147ac770dbe88419d Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 16 May 2008 23:45:23 +0000 Subject: Fix bt_rfcomm_connect segfault --- common/glib-helper.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index 59293334..0333ca07 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -740,7 +740,7 @@ static int rfcomm_bind(struct io_context *io_ctxt, const bdaddr_t *src, int err; io_ctxt->fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); - if ( io_ctxt->fd < 0) + if (io_ctxt->fd < 0) return -errno; if (flags) { @@ -756,7 +756,7 @@ static int rfcomm_bind(struct io_context *io_ctxt, const bdaddr_t *src, memset(addr, 0, sizeof(*addr)); addr->rc_family = AF_BLUETOOTH; bacpy(&addr->rc_bdaddr, src); - addr->rc_channel = *channel; + addr->rc_channel = channel ? *channel : 0; err = bind(io_ctxt->fd, (struct sockaddr *) addr, sizeof(*addr)); if (err < 0) { @@ -764,7 +764,8 @@ static int rfcomm_bind(struct io_context *io_ctxt, const bdaddr_t *src, return -errno; } - *channel = addr->rc_channel; + if (channel) + *channel = addr->rc_channel; return 0; } @@ -794,7 +795,7 @@ static int rfcomm_connect(struct io_context *io_ctxt, const bdaddr_t *src, struct sockaddr_rc addr; int err; - err = rfcomm_bind(io_ctxt, src, 0, 0, &addr); + err = rfcomm_bind(io_ctxt, src, NULL, 0, &addr); if (err < 0) return err; -- cgit From d7d35ec921ce7fcc138c36a738e337603d122cf0 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sat, 17 May 2008 09:11:21 +0000 Subject: Fix bt_rfcomm_listen_allocate since channel allocation happens after listen() and not bind() --- common/glib-helper.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index 0333ca07..91b167b0 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -734,7 +734,7 @@ static int l2cap_connect(struct io_context *io_ctxt, const bdaddr_t *src, } static int rfcomm_bind(struct io_context *io_ctxt, const bdaddr_t *src, - uint8_t *channel, uint32_t flags, + uint8_t channel, uint32_t flags, struct sockaddr_rc *addr) { int err; @@ -756,7 +756,7 @@ static int rfcomm_bind(struct io_context *io_ctxt, const bdaddr_t *src, memset(addr, 0, sizeof(*addr)); addr->rc_family = AF_BLUETOOTH; bacpy(&addr->rc_bdaddr, src); - addr->rc_channel = channel ? *channel : 0; + addr->rc_channel = channel; err = bind(io_ctxt->fd, (struct sockaddr *) addr, sizeof(*addr)); if (err < 0) { @@ -764,9 +764,6 @@ static int rfcomm_bind(struct io_context *io_ctxt, const bdaddr_t *src, return -errno; } - if (channel) - *channel = addr->rc_channel; - return 0; } @@ -774,9 +771,10 @@ static int rfcomm_listen(struct io_context *io_ctxt, const bdaddr_t *src, uint8_t *channel, uint32_t flags) { struct sockaddr_rc addr; + socklen_t sa_len; int err; - err = rfcomm_bind(io_ctxt, src, channel, flags, &addr); + err = rfcomm_bind(io_ctxt, src, *channel, flags, &addr); if (err < 0) return err; @@ -786,6 +784,16 @@ static int rfcomm_listen(struct io_context *io_ctxt, const bdaddr_t *src, return err; } + sa_len = sizeof(struct sockaddr_rc); + memset(&addr, 0, sizeof(addr)); + if (getsockname(io_ctxt->fd, (struct sockaddr *) &addr, &sa_len) < 0) { + err = -errno; + close(io_ctxt->fd); + return err; + } + + *channel = addr.rc_channel; + return 0; } @@ -795,7 +803,7 @@ static int rfcomm_connect(struct io_context *io_ctxt, const bdaddr_t *src, struct sockaddr_rc addr; int err; - err = rfcomm_bind(io_ctxt, src, NULL, 0, &addr); + err = rfcomm_bind(io_ctxt, src, 0, 0, &addr); if (err < 0) return err; -- cgit From 2cd95cb7308dc5d164be21745c5ab187cd7862da Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Tue, 27 May 2008 10:41:25 +0000 Subject: Initialize pointer to avoid compiler warning --- common/glib-helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index 91b167b0..0d7c6d60 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -250,7 +250,7 @@ int bt_search_service(const bdaddr_t *src, const bdaddr_t *dst, uuid_t *uuid, bt_callback_t cb, void *user_data, bt_destroy_t destroy) { - struct search_context *ctxt; + struct search_context *ctxt = NULL; int err; if (!cb) -- cgit From 40b5cf346c985b629c927c5b2a6d188ccd0966dd Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 27 May 2008 11:43:25 +0000 Subject: Restore error handling for the new manager interface --- common/error.c | 6 ++++++ common/error.h | 2 ++ 2 files changed, 8 insertions(+) (limited to 'common') diff --git a/common/error.c b/common/error.c index 656c7299..51f4f4bc 100644 --- a/common/error.c +++ b/common/error.c @@ -35,6 +35,12 @@ #include "error.h" +DBusMessage *create_errno_message(DBusMessage *msg, int err) +{ + return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", + strerror(err)); +} + /** org.bluez.Error.DeviceUnreachable: diff --git a/common/error.h b/common/error.h index 44b6f417..a2492601 100644 --- a/common/error.h +++ b/common/error.h @@ -27,6 +27,8 @@ #define ERROR_INTERFACE "org.bluez.Error" +DBusMessage *create_errno_message(DBusMessage *msg, int err); + DBusHandlerResult error_device_unreachable(DBusConnection *conn, DBusMessage *msg); -- cgit From 95fda45987df20c6603b1c5a068fe46fccf55b6e Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 30 May 2008 07:51:44 +0000 Subject: Add initial implementation of BtIO API. --- common/glib-helper.c | 481 ++++++++++++++++++++++++++++++++++++++------------- common/glib-helper.h | 37 ++++ 2 files changed, 396 insertions(+), 122 deletions(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index 0d7c6d60..c0355dba 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -43,7 +43,9 @@ #include "glib-helper.h" -typedef int (*resolver_t) (int fd, bdaddr_t *src, bdaddr_t *dst); +typedef int (*resolver_t) (int fd, char *src, char *dst); +typedef BtIOError (*connect_t) (BtIO *io, BtIOFunc func); +typedef BtIOError (*listen_t) (BtIO *io, BtIOFunc func); int set_nonblocking(int fd) { @@ -67,11 +69,26 @@ int set_nonblocking(int fd) struct io_context { int fd; GIOChannel *io; + BtIOFunc func; bt_io_callback_t cb; resolver_t resolver; gpointer user_data; }; +struct bt_io { + char src[18]; + char dst[18]; + guint32 flags; + guint8 channel; + guint16 psm; + guint16 mtu; + BtIOTransport type; + connect_t connect; + listen_t listen; + struct io_context *io_ctxt; + int refcount; +}; + struct search_context { bdaddr_t src; bdaddr_t dst; @@ -426,7 +443,7 @@ static inline int resolve_names(int fd, struct sockaddr *host, return 0; } -static int rfcomm_resolver(int fd, bdaddr_t *src, bdaddr_t *dst) +static int rfcomm_resolver(int fd, char *src, char *dst) { struct sockaddr_rc host, peer; socklen_t len; @@ -438,13 +455,13 @@ static int rfcomm_resolver(int fd, bdaddr_t *src, bdaddr_t *dst) if (err < 0) return err; - bacpy(src, &host.rc_bdaddr); - bacpy(dst, &peer.rc_bdaddr); + ba2str(&host.rc_bdaddr, src); + ba2str(&peer.rc_bdaddr, dst); return 0; } -static int l2cap_resolver(int fd, bdaddr_t *src, bdaddr_t *dst) +static int l2cap_resolver(int fd, char *src, char *dst) { struct sockaddr_l2 host, peer; socklen_t len; @@ -456,13 +473,13 @@ static int l2cap_resolver(int fd, bdaddr_t *src, bdaddr_t *dst) if (err < 0) return err; - bacpy(src, &host.l2_bdaddr); - bacpy(dst, &peer.l2_bdaddr); + ba2str(&host.l2_bdaddr, src); + ba2str(&peer.l2_bdaddr, dst); return 0; } -static int sco_resolver(int fd, bdaddr_t *src, bdaddr_t *dst) +static int sco_resolver(int fd, char *src, char *dst) { struct sockaddr_sco host, peer; socklen_t len; @@ -474,17 +491,19 @@ static int sco_resolver(int fd, bdaddr_t *src, bdaddr_t *dst) if (err < 0) return err; - bacpy(src, &host.sco_bdaddr); - bacpy(dst, &peer.sco_bdaddr); + ba2str(&host.sco_bdaddr, src); + ba2str(&peer.sco_bdaddr, dst); return 0; } static gboolean listen_cb(GIOChannel *chan, GIOCondition cond, - struct io_context *io_ctxt) + gpointer user_data) { + BtIO *io = user_data; + struct io_context *io_ctxt = io->io_ctxt; int fd, err = 0; - GIOChannel *io; + GIOChannel *gio; struct sockaddr addr; socklen_t len; bdaddr_t src, dst; @@ -506,34 +525,42 @@ static gboolean listen_cb(GIOChannel *chan, GIOCondition cond, goto drop; if (io_ctxt->resolver) { - err = io_ctxt->resolver(fd, &src, &dst); + err = io_ctxt->resolver(fd, io->src, io->dst); if (err < 0) { close(fd); goto drop; } } - io = g_io_channel_unix_new(fd); - if (!io) + gio = g_io_channel_unix_new(fd); + if (!gio) err = -ENOMEM; - if (io_ctxt->cb) - io_ctxt->cb(io, err, &src, &dst, io_ctxt->user_data); + if (io_ctxt->func) + io_ctxt->func(io, err, gio, io_ctxt->user_data); + if (io_ctxt->cb) { + str2ba(io->src, &src); + str2ba(io->dst, &dst); + io_ctxt->cb(gio, err, &src, &dst, io_ctxt->user_data); + } return TRUE; drop: + if (io_ctxt->func) + io_ctxt->func(io, -errno, NULL, io_ctxt->user_data); if (io_ctxt->cb) - io_ctxt->cb(NULL, -errno, NULL, NULL, io_ctxt->user_data); + io_ctxt->cb(NULL, err, NULL, NULL, io_ctxt->user_data); return TRUE; } -static int transport_listen(struct io_context *io_ctxt) +static int transport_listen(BtIO *io) { + struct io_context *io_ctxt = io->io_ctxt; int err; - err = listen(io_ctxt->fd, 1); + err = listen(io_ctxt->fd, 5); if (err < 0) return -errno; @@ -542,14 +569,16 @@ static int transport_listen(struct io_context *io_ctxt) return -ENOMEM; g_io_add_watch(io_ctxt->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, - (GIOFunc) listen_cb, io_ctxt); + (GIOFunc) listen_cb, io); return 0; } -static gboolean connect_cb(GIOChannel *io, GIOCondition cond, - struct io_context *io_ctxt) +static gboolean connect_cb(GIOChannel *gio, GIOCondition cond, + gpointer user_data) { + BtIO *io = user_data; + struct io_context *io_ctxt = io->io_ctxt; int err = 0, ret; socklen_t len; bdaddr_t src, dst; @@ -569,7 +598,7 @@ static gboolean connect_cb(GIOChannel *io, GIOCondition cond, } if (io_ctxt->resolver) { - err = io_ctxt->resolver(io_ctxt->fd, &src, &dst); + err = io_ctxt->resolver(io_ctxt->fd, io->src, io->dst); if (err < 0) goto done; } @@ -577,8 +606,13 @@ static gboolean connect_cb(GIOChannel *io, GIOCondition cond, io_ctxt->io = NULL; done: - if (io_ctxt->cb) - io_ctxt->cb(io, err, &src, &dst, io_ctxt->user_data); + if (io_ctxt->func) + io_ctxt->func(io, err, gio, io_ctxt->user_data); + if (io_ctxt->cb) { + str2ba(io->src, &src); + str2ba(io->dst, &dst); + io_ctxt->cb(gio, err, &src, &dst, io_ctxt->user_data); + } if (io_ctxt->io) { g_io_channel_close(io_ctxt->io); g_io_channel_unref(io_ctxt->io); @@ -588,9 +622,10 @@ done: return FALSE; } -static int transport_connect(struct io_context *io_ctxt, struct sockaddr *addr, - socklen_t addrlen) +static int transport_connect(BtIO *io, struct sockaddr *addr, + socklen_t addrlen) { + struct io_context *io_ctxt = io->io_ctxt; int err; io_ctxt->io = g_io_channel_unix_new(io_ctxt->fd); @@ -606,51 +641,54 @@ static int transport_connect(struct io_context *io_ctxt, struct sockaddr *addr, return -errno; g_io_add_watch(io_ctxt->io, G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL, - (GIOFunc) connect_cb, io_ctxt); + (GIOFunc) connect_cb, io); return 0; } -static int sco_connect(struct io_context *io_ctxt, const bdaddr_t *src, - const bdaddr_t *dst) +static BtIOError sco_connect(BtIO *io, BtIOFunc func) { + struct io_context *io_ctxt = io->io_ctxt; struct sockaddr_sco addr; int sk, err; + io_ctxt->func = func; + sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO); if (sk < 0) return -errno; memset(&addr, 0, sizeof(addr)); addr.sco_family = AF_BLUETOOTH; - bacpy(&addr.sco_bdaddr, src); + str2ba(io->src, &addr.sco_bdaddr); err = bind(sk, (struct sockaddr *) &addr, sizeof(addr)); if (err < 0) { close(sk); - return -errno; + return BT_IO_FAILED; } memset(&addr, 0, sizeof(addr)); addr.sco_family = AF_BLUETOOTH; - bacpy(&addr.sco_bdaddr, dst); + str2ba(io->dst, &addr.sco_bdaddr); - err = transport_connect(io_ctxt, (struct sockaddr *) &addr, + err = transport_connect(io, (struct sockaddr *) &addr, sizeof(addr)); if (err < 0) { close(sk); - return err; + return BT_IO_FAILED; } - return 0; + return BT_IO_SUCCESS; } -static int l2cap_bind(struct io_context *io_ctxt, const bdaddr_t *src, +static int l2cap_bind(struct io_context *io_ctxt, const char *address, uint16_t psm, uint16_t mtu, uint32_t flags, struct sockaddr_l2 *addr) { int err; struct l2cap_options l2o; + struct sockaddr_l2 l2a; io_ctxt->fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); if (io_ctxt->fd < 0) @@ -676,7 +714,7 @@ static int l2cap_bind(struct io_context *io_ctxt, const bdaddr_t *src, memset(addr, 0, sizeof(*addr)); addr->l2_family = AF_BLUETOOTH; - bacpy(&addr->l2_bdaddr, src); + str2ba(address, &l2a.l2_bdaddr); addr->l2_psm = htobs(psm); err = bind(io_ctxt->fd, (struct sockaddr *) addr, sizeof(*addr)); @@ -688,60 +726,63 @@ static int l2cap_bind(struct io_context *io_ctxt, const bdaddr_t *src, return 0; } -static int l2cap_listen(struct io_context *io_ctxt, const bdaddr_t *src, - uint16_t psm, uint16_t mtu, uint32_t flags) +static BtIOError l2cap_listen(BtIO *io, BtIOFunc func) { + struct io_context *io_ctxt = io->io_ctxt; struct sockaddr_l2 addr; - int err; + BtIOError err; - err = l2cap_bind(io_ctxt, src, psm, mtu, flags, &addr); + io_ctxt->func = func; + + err = l2cap_bind(io_ctxt, io->src, io->psm, io->mtu, io->flags, &addr); if (err < 0) return err; - err = transport_listen(io_ctxt); + err = transport_listen(io); if (err < 0) { close(io_ctxt->fd); return err; } - return 0; + return BT_IO_SUCCESS; } -static int l2cap_connect(struct io_context *io_ctxt, const bdaddr_t *src, - const bdaddr_t *dst, uint16_t psm, - uint16_t mtu) +static BtIOError l2cap_connect(BtIO *io, BtIOFunc func) { + struct io_context *io_ctxt = io->io_ctxt; struct sockaddr_l2 l2a; - int err; + BtIOError err; + + io_ctxt->func = func; - err = l2cap_bind(io_ctxt, src, 0, mtu, 0, &l2a); + err = l2cap_bind(io_ctxt, io->src, 0, io->mtu, 0, &l2a); if (err < 0) return err; memset(&l2a, 0, sizeof(l2a)); l2a.l2_family = AF_BLUETOOTH; - bacpy(&l2a.l2_bdaddr, dst); - l2a.l2_psm = htobs(psm); + str2ba(io->dst, &l2a.l2_bdaddr); + l2a.l2_psm = htobs(io->psm); - err = transport_connect(io_ctxt, (struct sockaddr *) &l2a, + err = transport_connect(io, (struct sockaddr *) &l2a, sizeof(l2a)); if (err < 0) { close(io_ctxt->fd); return err; } - return 0; + return BT_IO_SUCCESS; } -static int rfcomm_bind(struct io_context *io_ctxt, const bdaddr_t *src, +static BtIOError rfcomm_bind(struct io_context *io_ctxt, const char *address, uint8_t channel, uint32_t flags, struct sockaddr_rc *addr) { - int err; + BtIOError err; io_ctxt->fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); if (io_ctxt->fd < 0) - return -errno; + return BT_IO_FAILED; if (flags) { int opt = flags; @@ -749,36 +790,38 @@ static int rfcomm_bind(struct io_context *io_ctxt, const bdaddr_t *src, sizeof(opt)); if (err < 0) { close(io_ctxt->fd); - return -errno; + return BT_IO_FAILED; } } memset(addr, 0, sizeof(*addr)); addr->rc_family = AF_BLUETOOTH; - bacpy(&addr->rc_bdaddr, src); + str2ba(address, &addr->rc_bdaddr); addr->rc_channel = channel; err = bind(io_ctxt->fd, (struct sockaddr *) addr, sizeof(*addr)); if (err < 0) { close(io_ctxt->fd); - return -errno; + return BT_IO_FAILED; } - return 0; + return BT_IO_SUCCESS; } -static int rfcomm_listen(struct io_context *io_ctxt, const bdaddr_t *src, - uint8_t *channel, uint32_t flags) +static BtIOError rfcomm_listen(BtIO *io, BtIOFunc func) { + struct io_context *io_ctxt = io->io_ctxt; struct sockaddr_rc addr; socklen_t sa_len; - int err; + BtIOError err; + + io_ctxt->func = func; - err = rfcomm_bind(io_ctxt, src, *channel, flags, &addr); + err = rfcomm_bind(io_ctxt, io->src, io->channel, io->flags, &addr); if (err < 0) return err; - err = transport_listen(io_ctxt); + err = transport_listen(io); if (err < 0) { close(io_ctxt->fd); return err; @@ -792,44 +835,47 @@ static int rfcomm_listen(struct io_context *io_ctxt, const bdaddr_t *src, return err; } - *channel = addr.rc_channel; + io->channel = addr.rc_channel; - return 0; + return BT_IO_SUCCESS; } -static int rfcomm_connect(struct io_context *io_ctxt, const bdaddr_t *src, - const bdaddr_t *dst, uint8_t channel) +static BtIOError rfcomm_connect(BtIO *io, BtIOFunc func) { + struct io_context *io_ctxt = io->io_ctxt; struct sockaddr_rc addr; - int err; + BtIOError err; + + io_ctxt->func = func; - err = rfcomm_bind(io_ctxt, src, 0, 0, &addr); + err = rfcomm_bind(io_ctxt, io->src, 0, 0, &addr); if (err < 0) return err; memset(&addr, 0, sizeof(addr)); addr.rc_family = AF_BLUETOOTH; - bacpy(&addr.rc_bdaddr, dst); - addr.rc_channel = channel; + str2ba(io->dst, &addr.rc_bdaddr); + addr.rc_channel = io->channel; - err = transport_connect(io_ctxt, (struct sockaddr *) &addr, + err = transport_connect(io, (struct sockaddr *) &addr, sizeof(addr)); if (err < 0) { close(io_ctxt->fd); return err; } - return 0; + return BT_IO_SUCCESS; } -static int create_io_context(struct io_context **io_ctxt, gpointer cb, - gpointer resolver, gpointer user_data) +static int create_io_context(struct io_context **io_ctxt, BtIOFunc func, + gpointer cb, gpointer resolver, gpointer user_data) { *io_ctxt = g_try_malloc0(sizeof(struct search_context)); if (!*io_ctxt) return -ENOMEM; (*io_ctxt)->cb = cb; + (*io_ctxt)->func = func; (*io_ctxt)->resolver = resolver; (*io_ctxt)->user_data = user_data; @@ -848,20 +894,26 @@ static void io_context_cleanup(struct io_context *io_ctxt) GIOChannel *rfcomm_listen_internal(const bdaddr_t *src, uint8_t *channel, uint32_t flags, bt_io_callback_t cb, void *user_data) { - struct io_context *io_ctxt; - int err; + BtIO *io; + BtIOError err; - err = create_io_context(&io_ctxt, cb, rfcomm_resolver, user_data); - if (err < 0) + io = bt_io_create(BT_RFCOMM, user_data, NULL); + if (!io) return NULL; - err = rfcomm_listen(io_ctxt, src, channel, flags); - if (err < 0) { - io_context_cleanup(io_ctxt); + ba2str(src, io->src); + io->channel = *channel; + io->flags = flags; + io->io_ctxt->cb = cb; + err = bt_io_listen(io, NULL, NULL); + if (err != BT_IO_SUCCESS) { + bt_io_unref(io); return NULL; } - return io_ctxt->io; + *channel = io->channel; + + return io->io_ctxt->io; } GIOChannel *bt_rfcomm_listen_allocate(const bdaddr_t *src, uint8_t *channel, @@ -882,22 +934,27 @@ GIOChannel *bt_rfcomm_listen(const bdaddr_t *src, uint8_t channel, return NULL; return rfcomm_listen_internal(src, &channel, flags, cb, user_data); + } int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel, bt_io_callback_t cb, void *user_data) { - struct io_context *io_ctxt; - int err; - - err = create_io_context(&io_ctxt, cb, rfcomm_resolver, user_data); - if (err < 0) - return err; + BtIO *io; + BtIOError err; - err = rfcomm_connect(io_ctxt, src, dst, channel); - if (err < 0) { - io_context_cleanup(io_ctxt); - return err; + io = bt_io_create(BT_RFCOMM, user_data, NULL); + if (!io) + return -1; + + ba2str(src, io->src); + ba2str(dst, io->dst); + io->channel = channel; + io->io_ctxt->cb = cb; + err = bt_io_connect(io, NULL, NULL); + if (err != BT_IO_SUCCESS) { + bt_io_unref(io); + return -1; } return 0; @@ -906,37 +963,47 @@ int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, GIOChannel *bt_l2cap_listen(const bdaddr_t *src, uint16_t psm, uint16_t mtu, uint32_t flags, bt_io_callback_t cb, void *user_data) { - struct io_context *io_ctxt; - int err; + BtIO *io; + BtIOError err; - err = create_io_context(&io_ctxt, cb, l2cap_resolver, user_data); - if (err < 0) + io = bt_io_create(BT_L2CAP, user_data, NULL); + if (!io) return NULL; - err = l2cap_listen(io_ctxt, src, psm, mtu, flags); - if (err < 0) { - io_context_cleanup(io_ctxt); + ba2str(src, io->src); + io->psm = psm; + io->mtu = mtu; + io->flags = flags; + io->io_ctxt->cb = cb; + err = bt_io_listen(io, NULL, NULL); + if (err != BT_IO_SUCCESS) { + bt_io_unref(io); return NULL; } - return io_ctxt->io; + return io->io_ctxt->io; } int bt_l2cap_connect(const bdaddr_t *src, const bdaddr_t *dst, uint16_t psm, uint16_t mtu, bt_io_callback_t cb, void *user_data) { - struct io_context *io_ctxt; - int err; + BtIO *io; + BtIOError err; - err = create_io_context(&io_ctxt, cb, l2cap_resolver, user_data); - if (err < 0) - return err; - - err = l2cap_connect(io_ctxt, src, dst, psm, mtu); - if (err < 0) { - io_context_cleanup(io_ctxt); - return err; + io = bt_io_create(BT_L2CAP, user_data, NULL); + if (!io) + return -1; + + ba2str(src, io->src); + ba2str(dst, io->dst); + io->psm = psm; + io->mtu = mtu; + io->io_ctxt->cb = cb; + err = bt_io_connect(io, NULL, NULL); + if (err != BT_IO_SUCCESS) { + bt_io_unref(io); + return -1; } return 0; @@ -945,18 +1012,188 @@ int bt_l2cap_connect(const bdaddr_t *src, const bdaddr_t *dst, int bt_sco_connect(const bdaddr_t *src, const bdaddr_t *dst, bt_io_callback_t cb, void *user_data) { - struct io_context *io_ctxt; + BtIO *io; + BtIOError err; + + io = bt_io_create(BT_SCO, user_data, NULL); + if (!io) + return -1; + + ba2str(src, io->src); + ba2str(dst, io->dst); + io->io_ctxt->cb = cb; + err = bt_io_connect(io, NULL, NULL); + if (err != BT_IO_SUCCESS) { + bt_io_unref(io); + return -1; + } + + return 0; +} + +/* Experiemental bt_io API */ + +BtIO *bt_io_create(BtIOTransport type, gpointer user_data, GDestroyNotify notify) +{ + BtIO *io; int err; - err = create_io_context(&io_ctxt, cb, sco_resolver, user_data); - if (err < 0) - return err; + io = g_new0(BtIO, 1); + if (!io) + return NULL; + + io->refcount = 1; + + switch (type) { + case BT_L2CAP: + err = create_io_context(&io->io_ctxt, NULL, NULL, + l2cap_resolver, user_data); + io->connect = l2cap_connect; + io->listen = l2cap_listen; + break; + case BT_RFCOMM: + err = create_io_context(&io->io_ctxt, NULL, NULL, + rfcomm_resolver, user_data); + io->connect = rfcomm_connect; + io->listen = rfcomm_listen; + break; + case BT_SCO: + err = create_io_context(&io->io_ctxt, NULL, NULL, + sco_resolver, user_data); + io->connect = sco_connect; + break; + default: + return NULL; + } - err = sco_connect(io_ctxt, src, dst); if (err < 0) { - io_context_cleanup(io_ctxt); - return err; + bt_io_unref(io); + return NULL; } - return 0; + return io; +} + +BtIO *bt_io_ref(BtIO *io) +{ + io->refcount++; + + return io; +} + +void bt_io_unref(BtIO *io) +{ + io->refcount--; + + if (io->refcount) + return; + + io_context_cleanup(io->io_ctxt); + g_free(io); +} + +gboolean bt_io_set_source(BtIO *io, const char *address) +{ + if (strlen(address) != sizeof(io->src)) + return FALSE; + + memcpy(io->src, address, sizeof(io->src)); + + return TRUE; +} + +const char *bt_io_get_source(BtIO *io) +{ + return io->src; +} + +gboolean bt_io_set_destination(BtIO *io, const char *address) +{ + if (strlen(address) != sizeof(io->dst)) + return FALSE; + + memcpy(io->dst, address, sizeof(io->dst)); + + return TRUE; +} + +const char *bt_io_get_destination(BtIO *io) +{ + return io->dst; +} + +gboolean bt_io_set_flags(BtIO *io, guint32 flags) +{ + io->flags = flags; + + return TRUE; +} + +guint32 bt_io_get_flags(BtIO *io) +{ + return io->flags; +} + +gboolean bt_io_set_channel(BtIO *io, guint8 channel) +{ + if (io->type != BT_RFCOMM) + return FALSE; + + io->channel = channel; + + return TRUE; +} + +guint8 bt_io_get_channel(BtIO *io) +{ + return io->channel; +} + +gboolean bt_io_set_psm(BtIO *io, guint16 psm) +{ + if (io->type != BT_L2CAP) + return FALSE; + + io->psm = psm; + + return TRUE; +} +guint16 bt_io_get_psm(BtIO *io) +{ + return io->psm; +} + +gboolean bt_io_set_mtu(BtIO *io, guint16 mtu) +{ + io->mtu = mtu; + + return TRUE; +} + +guint16 bt_io_get_mtu(BtIO *io) +{ + return io->mtu; +} + +BtIOError bt_io_connect(BtIO *io, const char *uuid, BtIOFunc func) +{ + if (!io->connect) + return BT_IO_FAILED; + + return io->connect(io, func); +} + +BtIOError bt_io_listen(BtIO *io, const char *uuid, BtIOFunc func) +{ + if (!io->listen) + return BT_IO_FAILED; + + return io->listen(io, func); +} + +BtIOError bt_io_shutdown(BtIO *io) +{ + io_context_cleanup(io->io_ctxt); + + return BT_IO_SUCCESS; } diff --git a/common/glib-helper.h b/common/glib-helper.h index 8d346b49..458d5c88 100644 --- a/common/glib-helper.h +++ b/common/glib-helper.h @@ -54,3 +54,40 @@ int bt_l2cap_connect(const bdaddr_t *src, const bdaddr_t *dst, void *user_data); int bt_sco_connect(const bdaddr_t *src, const bdaddr_t *dst, bt_io_callback_t cb, void *user_data); + +/* Experiemental bt_io API */ + +typedef struct bt_io BtIO; + +typedef enum { + BT_L2CAP, + BT_RFCOMM, + BT_SCO +} BtIOTransport; + +typedef enum { + BT_IO_SUCCESS, + BT_IO_FAILED +} BtIOError; + +typedef void (*BtIOFunc) (BtIO *io, BtIOError err, GIOChannel *chan, + gpointer user_data); + +BtIO *bt_io_create(BtIOTransport type, gpointer user_data, GDestroyNotify notify); +BtIO *bt_io_ref(BtIO *io); +void bt_io_unref(BtIO *io); +gboolean bt_io_set_source(BtIO *io, const char *address); +const char *bt_io_get_source(BtIO *io); +gboolean bt_io_set_destination(BtIO *io, const char *address); +const char *bt_io_get_destination(BtIO *io); +gboolean bt_io_set_flags(BtIO *io, guint32 flags); +guint32 bt_io_get_flags(BtIO *io); +gboolean bt_io_set_channel(BtIO *io, guint8 channel); +guint8 bt_io_get_channel(BtIO *io); +gboolean bt_io_set_psm(BtIO *io, guint16 psm); +guint16 bt_io_get_psm(BtIO *io); +gboolean bt_io_set_mtu(BtIO *io, guint16 mtu); +guint16 bt_io_get_mtu(BtIO *io); +BtIOError bt_io_connect(BtIO *io, const char *uuid, BtIOFunc func); +BtIOError bt_io_listen(BtIO *io, const char *uuid, BtIOFunc func); +BtIOError bt_io_shutdown(BtIO *io); -- cgit From 3232edc9af22131032cef987479d081b90fa4f81 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 30 May 2008 08:57:22 +0000 Subject: Rename the transport types with proper BT_IO prefix --- common/glib-helper.c | 20 ++++++++++---------- common/glib-helper.h | 9 +++++---- 2 files changed, 15 insertions(+), 14 deletions(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index c0355dba..c472dd22 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -897,7 +897,7 @@ GIOChannel *rfcomm_listen_internal(const bdaddr_t *src, uint8_t *channel, BtIO *io; BtIOError err; - io = bt_io_create(BT_RFCOMM, user_data, NULL); + io = bt_io_create(BT_IO_RFCOMM, user_data, NULL); if (!io) return NULL; @@ -943,7 +943,7 @@ int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, BtIO *io; BtIOError err; - io = bt_io_create(BT_RFCOMM, user_data, NULL); + io = bt_io_create(BT_IO_RFCOMM, user_data, NULL); if (!io) return -1; @@ -966,7 +966,7 @@ GIOChannel *bt_l2cap_listen(const bdaddr_t *src, uint16_t psm, uint16_t mtu, BtIO *io; BtIOError err; - io = bt_io_create(BT_L2CAP, user_data, NULL); + io = bt_io_create(BT_IO_L2CAP, user_data, NULL); if (!io) return NULL; @@ -991,7 +991,7 @@ int bt_l2cap_connect(const bdaddr_t *src, const bdaddr_t *dst, BtIO *io; BtIOError err; - io = bt_io_create(BT_L2CAP, user_data, NULL); + io = bt_io_create(BT_IO_L2CAP, user_data, NULL); if (!io) return -1; @@ -1015,7 +1015,7 @@ int bt_sco_connect(const bdaddr_t *src, const bdaddr_t *dst, BtIO *io; BtIOError err; - io = bt_io_create(BT_SCO, user_data, NULL); + io = bt_io_create(BT_IO_SCO, user_data, NULL); if (!io) return -1; @@ -1045,19 +1045,19 @@ BtIO *bt_io_create(BtIOTransport type, gpointer user_data, GDestroyNotify notify io->refcount = 1; switch (type) { - case BT_L2CAP: + case BT_IO_L2CAP: err = create_io_context(&io->io_ctxt, NULL, NULL, l2cap_resolver, user_data); io->connect = l2cap_connect; io->listen = l2cap_listen; break; - case BT_RFCOMM: + case BT_IO_RFCOMM: err = create_io_context(&io->io_ctxt, NULL, NULL, rfcomm_resolver, user_data); io->connect = rfcomm_connect; io->listen = rfcomm_listen; break; - case BT_SCO: + case BT_IO_SCO: err = create_io_context(&io->io_ctxt, NULL, NULL, sco_resolver, user_data); io->connect = sco_connect; @@ -1136,7 +1136,7 @@ guint32 bt_io_get_flags(BtIO *io) gboolean bt_io_set_channel(BtIO *io, guint8 channel) { - if (io->type != BT_RFCOMM) + if (io->type != BT_IO_RFCOMM) return FALSE; io->channel = channel; @@ -1151,7 +1151,7 @@ guint8 bt_io_get_channel(BtIO *io) gboolean bt_io_set_psm(BtIO *io, guint16 psm) { - if (io->type != BT_L2CAP) + if (io->type != BT_IO_L2CAP) return FALSE; io->psm = psm; diff --git a/common/glib-helper.h b/common/glib-helper.h index 458d5c88..0919fe97 100644 --- a/common/glib-helper.h +++ b/common/glib-helper.h @@ -60,14 +60,15 @@ int bt_sco_connect(const bdaddr_t *src, const bdaddr_t *dst, typedef struct bt_io BtIO; typedef enum { - BT_L2CAP, - BT_RFCOMM, - BT_SCO + BT_IO_AUTO, + BT_IO_L2CAP, + BT_IO_RFCOMM, + BT_IO_SCO, } BtIOTransport; typedef enum { BT_IO_SUCCESS, - BT_IO_FAILED + BT_IO_FAILED, } BtIOError; typedef void (*BtIOFunc) (BtIO *io, BtIOError err, GIOChannel *chan, -- cgit From 52f1452d5dedfade299fa81b68fa759b13aa86d9 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 6 Jun 2008 10:01:33 +0000 Subject: Fix the D-Bus sending for error messages --- common/error.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'common') diff --git a/common/error.c b/common/error.c index 51f4f4bc..096b8651 100644 --- a/common/error.c +++ b/common/error.c @@ -246,7 +246,11 @@ DBusHandlerResult error_common_reply(DBusConnection *conn, DBusMessage *msg, if (!derr) return DBUS_HANDLER_RESULT_NEED_MEMORY; - return dbus_connection_send_and_unref(conn, derr); + dbus_connection_send(conn, derr, NULL); + + dbus_message_unref(derr); + + return DBUS_HANDLER_RESULT_HANDLED; } /** @@ -256,6 +260,7 @@ DBusHandlerResult error_common_reply(DBusConnection *conn, DBusMessage *msg, */ DBusHandlerResult error_unknown_method(DBusConnection *conn, DBusMessage *msg) { + DBusMessage *derr; char error[128]; const char *signature = dbus_message_get_signature(msg); const char *method = dbus_message_get_member(msg); @@ -264,7 +269,14 @@ DBusHandlerResult error_unknown_method(DBusConnection *conn, DBusMessage *msg) snprintf(error, 128, "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist", method, signature, interface); - return send_message_and_unref(conn, - dbus_message_new_error(msg, ERROR_INTERFACE ".UnknownMethod", - error)); + derr = dbus_message_new_error(msg, ERROR_INTERFACE ".UnknownMethod", + error); + if (!derr) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + dbus_connection_send(conn, derr, NULL); + + dbus_message_unref(derr); + + return DBUS_HANDLER_RESULT_HANDLED; } -- cgit From 92faff9a094d5cbdfaa3c83f3fe17074a483ce55 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 7 Jun 2008 08:49:19 +0000 Subject: Cleanup errors and remove unused functions --- common/error.c | 157 --------------------------------------------------------- common/error.h | 30 ----------- 2 files changed, 187 deletions(-) (limited to 'common') diff --git a/common/error.c b/common/error.c index 096b8651..adf2aa4f 100644 --- a/common/error.c +++ b/common/error.c @@ -41,17 +41,6 @@ DBusMessage *create_errno_message(DBusMessage *msg, int err) strerror(err)); } -/** - org.bluez.Error.DeviceUnreachable: - - The remote device is either powered down or out of range. -*/ -DBusHandlerResult error_device_unreachable(DBusConnection *conn, DBusMessage *msg) -{ - return error_common_reply(conn, msg, ERROR_INTERFACE ".DeviceUnreachable", - "Device Unreachable"); -} - /** org.bluez.Error.ConnectionAttemptFailed: @@ -65,74 +54,6 @@ DBusHandlerResult error_connection_attempt_failed(DBusConnection *conn, DBusMess err ? strerror(err) : "Connection attempt failed"); } -/** - org.bluez.Error.AlreadyConnected: - - A connection request has been received on an already connected device. -*/ -DBusHandlerResult error_already_connected(DBusConnection *conn, DBusMessage *msg) -{ - return error_common_reply(conn, msg, - ERROR_INTERFACE ".AlreadyConnected", - "Already connected to a device"); -} - -/** - org.bluez.Error.InProgress: - - Error returned if an operation is in progress. Since - this is a generic error that can be used in various - situations, the error message should be more clear - about what is in progress. For example "Bonding in - progress". - */ -DBusHandlerResult error_in_progress(DBusConnection *conn, DBusMessage *msg, - const char *str) -{ - return error_common_reply(conn, msg, ERROR_INTERFACE ".InProgress", str); -} - -/** - org.bluez.Error.InvalidArguments: - - The DBUS request does not contain the right number of - arguments with the right type, or the arguments are there but - their value is wrong, or does not makes sense in the current context. -*/ -DBusHandlerResult error_invalid_arguments(DBusConnection *conn, DBusMessage *msg, - const char *descr) -{ - return error_common_reply(conn, msg, - ERROR_INTERFACE ".InvalidArguments", - descr ? descr : "Invalid arguments in method call"); -} - -/** - org.bluez.Error.OutOfMemory: - - Not enough memory to execute the request. - Error returned when a memory allocation via malloc() - fails. This error is similar to ENOMEM. -*/ -DBusHandlerResult error_out_of_memory(DBusConnection *conn, DBusMessage *msg) -{ - return error_common_reply(conn, msg, ERROR_INTERFACE ".OutOfMemory", - "Out of memory"); -} - -/** - org.bluez.Error.NotAvailable: - - The requested information is not there. - Examples of use: Adapter object when remote info is not available, or Database - object record is not found -*/ -DBusHandlerResult error_not_available(DBusConnection *conn, DBusMessage *msg) -{ - return error_common_reply(conn, msg, ERROR_INTERFACE ".NotAvailable", - "Not available"); -} - /** org.bluez.Error.NotSupported: @@ -146,56 +67,6 @@ DBusHandlerResult error_not_supported(DBusConnection *conn, DBusMessage *msg) "Not supported"); } -/** - org.bluez.Error.NotConnected: - - The remote device is not connected, while the method call - would expect it to be, or is not in the expected state to - perform the action -*/ -DBusHandlerResult error_not_connected(DBusConnection *conn, DBusMessage *msg) -{ - return error_common_reply(conn, msg, ERROR_INTERFACE ".NotConnected", - "Not connected"); -} - -/** - org.bluez.Error.AlreadyExists: - - One of the requested elements already exists - Examples of use: Bonding, record, passkey agent, auth agent, - hid device ... already exists -*/ -DBusHandlerResult error_already_exists(DBusConnection *conn, DBusMessage *msg, - const char *str) -{ - return error_common_reply(conn, msg, ERROR_INTERFACE ".AlreadyExists", str); -} - -/** - org.bluez.Error.DoesNotExist: - - One of the requested elements does not exist - Examples of use: Bonding, record, passkey agent, auth agent, bluetooth device - ... does not exist. -*/ -DBusHandlerResult error_does_not_exist(DBusConnection *conn, DBusMessage *msg, - const char *str) -{ - return error_common_reply(conn, msg, ERROR_INTERFACE ".DoesNotExist", str); -} - -/** - org.bluez.Error.DoesNotExist: - - Same as error_does_not_exist, but with device error message -*/ -DBusHandlerResult error_device_does_not_exist(DBusConnection *conn, - DBusMessage *msg) -{ - return error_does_not_exist(conn, msg, "Device does not exist"); -} - /** org.bluez.Error.Canceled: @@ -252,31 +123,3 @@ DBusHandlerResult error_common_reply(DBusConnection *conn, DBusMessage *msg, return DBUS_HANDLER_RESULT_HANDLED; } - -/** - org.bluez.Error.UnknownMethod: - - Used in experimental code. -*/ -DBusHandlerResult error_unknown_method(DBusConnection *conn, DBusMessage *msg) -{ - DBusMessage *derr; - char error[128]; - const char *signature = dbus_message_get_signature(msg); - const char *method = dbus_message_get_member(msg); - const char *interface = dbus_message_get_interface(msg); - - snprintf(error, 128, "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist", - method, signature, interface); - - derr = dbus_message_new_error(msg, ERROR_INTERFACE ".UnknownMethod", - error); - if (!derr) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - - dbus_connection_send(conn, derr, NULL); - - dbus_message_unref(derr); - - return DBUS_HANDLER_RESULT_HANDLED; -} diff --git a/common/error.h b/common/error.h index a2492601..68ce105a 100644 --- a/common/error.h +++ b/common/error.h @@ -29,41 +29,13 @@ DBusMessage *create_errno_message(DBusMessage *msg, int err); -DBusHandlerResult error_device_unreachable(DBusConnection *conn, - DBusMessage *msg); - DBusHandlerResult error_connection_attempt_failed(DBusConnection *conn, DBusMessage *msg, int err); -DBusHandlerResult error_already_connected(DBusConnection *conn, - DBusMessage *msg); - -DBusHandlerResult error_not_connected(DBusConnection *conn, DBusMessage *msg); - -DBusHandlerResult error_in_progress(DBusConnection *conn, DBusMessage *msg, - const char *str); - -DBusHandlerResult error_invalid_arguments(DBusConnection *conn, - DBusMessage *msg, - const char *str); - -DBusHandlerResult error_out_of_memory(DBusConnection *conn, DBusMessage *msg); - -DBusHandlerResult error_not_available(DBusConnection *conn, DBusMessage *msg); - DBusHandlerResult error_not_supported(DBusConnection *conn, DBusMessage *msg); -DBusHandlerResult error_already_exists(DBusConnection *conn, DBusMessage *msg, - const char *str); - -DBusHandlerResult error_does_not_exist(DBusConnection *conn, DBusMessage *msg, - const char *str); - -DBusHandlerResult error_device_does_not_exist(DBusConnection *conn, - DBusMessage *msg); - DBusHandlerResult error_canceled(DBusConnection *conn, DBusMessage *msg, const char *str); @@ -75,5 +47,3 @@ DBusHandlerResult error_failed_errno(DBusConnection *conn, DBusMessage *msg, DBusHandlerResult error_common_reply(DBusConnection *conn, DBusMessage *msg, const char *name, const char *descr); - -DBusHandlerResult error_unknown_method(DBusConnection *conn, DBusMessage *msg); -- cgit From eef93c82a0e106dd12c29c1ed3a06502d92bcef2 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 8 Jun 2008 20:53:31 +0000 Subject: Add special DBG helper --- common/logging.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'common') diff --git a/common/logging.h b/common/logging.h index e99131e5..822eb15a 100644 --- a/common/logging.h +++ b/common/logging.h @@ -33,4 +33,6 @@ void disable_debug(void); void start_logging(const char *ident, const char *message, ...); void stop_logging(void); +#define DBG(fmt, arg...) debug("%s: " fmt "\n" , __FUNCTION__ , ## arg) + #endif /* __LOGGING_H */ -- cgit From 2b742d9f7a637b713bf77c52523dfee30922a080 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 10 Jun 2008 00:10:02 +0000 Subject: Fix some minor details --- common/error.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'common') diff --git a/common/error.c b/common/error.c index adf2aa4f..bc813d74 100644 --- a/common/error.c +++ b/common/error.c @@ -50,8 +50,8 @@ DBusMessage *create_errno_message(DBusMessage *msg, int err) DBusHandlerResult error_connection_attempt_failed(DBusConnection *conn, DBusMessage *msg, int err) { return error_common_reply(conn, msg, - ERROR_INTERFACE ".ConnectionAttemptFailed", - err ? strerror(err) : "Connection attempt failed"); + ERROR_INTERFACE ".ConnectionAttemptFailed", + err > 0 ? strerror(err) : "Connection attempt failed"); } /** @@ -109,6 +109,7 @@ DBusHandlerResult error_common_reply(DBusConnection *conn, DBusMessage *msg, const char *name, const char *descr) { DBusMessage *derr; + dbus_bool_t ret; if (!conn || !msg) return DBUS_HANDLER_RESULT_HANDLED; @@ -117,7 +118,7 @@ DBusHandlerResult error_common_reply(DBusConnection *conn, DBusMessage *msg, if (!derr) return DBUS_HANDLER_RESULT_NEED_MEMORY; - dbus_connection_send(conn, derr, NULL); + ret = dbus_connection_send(conn, derr, NULL); dbus_message_unref(derr); -- cgit From 9fdd6a8c1358daa9360ea2269ee357402ac9ed83 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 10 Jun 2008 00:24:09 +0000 Subject: Use GLib helpers for host/network order --- common/glib-helper.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index c472dd22..9152c1b4 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -335,9 +334,9 @@ char *bt_uuid2string(uuid_t *uuid) return NULL; sprintf(str, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x", - ntohl(data0), ntohs(data1), - ntohs(data2), ntohs(data3), - ntohl(data4), ntohs(data5)); + g_ntohl(data0), g_ntohs(data1), + g_ntohs(data2), g_ntohs(data3), + g_ntohl(data4), g_ntohs(data5)); return str; } @@ -356,12 +355,12 @@ int bt_string2uuid(uuid_t *uuid, const char *string) &data0, &data1, &data2, &data3, &data4, &data5) == 6) { uint8_t val[16]; - data0 = htonl(data0); - data1 = htons(data1); - data2 = htons(data2); - data3 = htons(data3); - data4 = htonl(data4); - data5 = htons(data5); + data0 = g_htonl(data0); + data1 = g_htons(data1); + data2 = g_htons(data2); + data3 = g_htons(data3); + data4 = g_htonl(data4); + data5 = g_htons(data5); memcpy(&val[0], &data0, 4); memcpy(&val[4], &data1, 2); -- cgit From 89f8b57a8cdf51d10cbfc4e80cd3071b10db221d Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Tue, 10 Jun 2008 02:47:59 +0000 Subject: Fix storing socket fd in bt_sco_connect --- common/glib-helper.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index 9152c1b4..665a1880 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -667,6 +667,8 @@ static BtIOError sco_connect(BtIO *io, BtIOFunc func) return BT_IO_FAILED; } + io_ctxt->fd = sk; + memset(&addr, 0, sizeof(addr)); addr.sco_family = AF_BLUETOOTH; str2ba(io->dst, &addr.sco_bdaddr); -- cgit From 45c36dbd276501aa76d9798a8fafe6c202db7276 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 11 Jun 2008 13:20:50 +0000 Subject: Avoid direct inclusion of malloc.h --- common/oui.c | 2 +- common/sdp-xml.c | 1 - common/textfile.c | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) (limited to 'common') diff --git a/common/oui.c b/common/oui.c index a9c4af5a..0915afdf 100644 --- a/common/oui.c +++ b/common/oui.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/common/sdp-xml.c b/common/sdp-xml.c index 2cc55c2d..1e1e07c3 100644 --- a/common/sdp-xml.c +++ b/common/sdp-xml.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/common/textfile.c b/common/textfile.c index 021fc8fb..eef0f96a 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include -- cgit From 19b4c8b0e51a20a1b95ede34b092ebc56e1183ae Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 16 Jun 2008 14:26:54 +0000 Subject: Allow to cancel a service discovery --- common/glib-helper.c | 41 +++++++++++++++++++++++++++++++++++++++++ common/glib-helper.h | 1 + 2 files changed, 42 insertions(+) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index 665a1880..9d942cf9 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -98,10 +98,15 @@ struct search_context { uuid_t uuid; }; +static GSList *context_list = NULL; + static void search_context_cleanup(struct search_context *ctxt) { + context_list = g_slist_remove(context_list, ctxt); + if (ctxt->destroy) ctxt->destroy(ctxt->user_data); + g_free(ctxt); } @@ -146,8 +151,10 @@ static void search_completed_cb(uint8_t type, uint16_t status, done: sdp_close(ctxt->session); + if (ctxt->cb) ctxt->cb(recs, err, ctxt->user_data); + search_context_cleanup(ctxt); } @@ -170,8 +177,10 @@ static gboolean search_process_cb(GIOChannel *chan, failed: if (err) { sdp_close(ctxt->session); + if (ctxt->cb) ctxt->cb(NULL, err, ctxt->user_data); + search_context_cleanup(ctxt); } @@ -222,8 +231,10 @@ static gboolean connect_watch(GIOChannel *chan, GIOCondition cond, gpointer user failed: sdp_close(ctxt->session); + if (ctxt->cb) ctxt->cb(NULL, -err, ctxt->user_data); + search_context_cleanup(ctxt); return FALSE; @@ -280,6 +291,8 @@ int bt_search_service(const bdaddr_t *src, const bdaddr_t *dst, ctxt->destroy = destroy; ctxt->user_data = user_data; + context_list = g_slist_append(context_list, ctxt); + return 0; } @@ -293,6 +306,33 @@ int bt_discover_services(const bdaddr_t *src, const bdaddr_t *dst, return bt_search_service(src, dst, &uuid, cb, user_data, destroy); } +static int find_by_bdaddr(const void *data, const void *user_data) +{ + const struct search_context *ctxt = data, *search = user_data; + + return (bacmp(&ctxt->dst, &search->dst) && + bacmp(&ctxt->src, &search->src)); +} + +void bt_cancel_discovery(const bdaddr_t *src, const bdaddr_t *dst) +{ + struct search_context search, *ctxt; + GSList *match; + + memset(&search, 0, sizeof(search)); + bacpy(&search.src, src); + bacpy(&search.dst, dst); + + match = g_slist_find_custom(context_list, &search, find_by_bdaddr); + + /* Ongoing SDP Discovery */ + if (match) { + ctxt = match->data; + if (ctxt->session) + close(ctxt->session->sock); + } +} + char *bt_uuid2string(uuid_t *uuid) { gchar *str; @@ -1159,6 +1199,7 @@ gboolean bt_io_set_psm(BtIO *io, guint16 psm) return TRUE; } + guint16 bt_io_get_psm(BtIO *io) { return io->psm; diff --git a/common/glib-helper.h b/common/glib-helper.h index 0919fe97..6c9b89b0 100644 --- a/common/glib-helper.h +++ b/common/glib-helper.h @@ -34,6 +34,7 @@ int bt_discover_services(const bdaddr_t *src, const bdaddr_t *dst, int bt_search_service(const bdaddr_t *src, const bdaddr_t *dst, uuid_t *uuid, bt_callback_t cb, void *user_data, bt_destroy_t destroy); +void bt_cancel_discovery(const bdaddr_t *src, const bdaddr_t *dst); gchar *bt_uuid2string(uuid_t *uuid); int bt_string2uuid(uuid_t *uuid, const char *string); -- cgit From de32e4ca4c787266f194f3ffdab74e428fe3649a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 16 Jun 2008 14:28:15 +0000 Subject: Remove obsolete FIXME comment --- common/glib-helper.c | 1 - 1 file changed, 1 deletion(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index 9d942cf9..515254ec 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -427,7 +427,6 @@ gchar *bt_list2string(GSList *list) str = g_strdup((const gchar *) list->data); - /* FIXME: eglib doesn't support g_strconcat */ for (l = list->next; l; l = l->next) { tmp = g_strconcat(str, " " , (const gchar *) l->data, NULL); g_free(str); -- cgit From 1e4c95e09bf53e50ad033febae0d6383517508b4 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 16 Jun 2008 15:35:41 +0000 Subject: Fix minor whitespace issues --- common/glib-helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index 515254ec..ed203eb4 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -328,7 +328,7 @@ void bt_cancel_discovery(const bdaddr_t *src, const bdaddr_t *dst) /* Ongoing SDP Discovery */ if (match) { ctxt = match->data; - if (ctxt->session) + if (ctxt->session) close(ctxt->session->sock); } } -- cgit From 289e29c6c4a073569c7e7aa3c8fc51ed5c46993f Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Mon, 16 Jun 2008 16:56:38 +0000 Subject: Fix bt_cancel_discovery to only succeed when there is a discover to cancel. --- common/glib-helper.c | 17 ++++++++++------- common/glib-helper.h | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index ed203eb4..eab30b5e 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -314,7 +314,7 @@ static int find_by_bdaddr(const void *data, const void *user_data) bacmp(&ctxt->src, &search->src)); } -void bt_cancel_discovery(const bdaddr_t *src, const bdaddr_t *dst) +int bt_cancel_discovery(const bdaddr_t *src, const bdaddr_t *dst) { struct search_context search, *ctxt; GSList *match; @@ -323,14 +323,17 @@ void bt_cancel_discovery(const bdaddr_t *src, const bdaddr_t *dst) bacpy(&search.src, src); bacpy(&search.dst, dst); + /* Ongoing SDP Discovery */ match = g_slist_find_custom(context_list, &search, find_by_bdaddr); + if (!match) + return -ENODATA; - /* Ongoing SDP Discovery */ - if (match) { - ctxt = match->data; - if (ctxt->session) - close(ctxt->session->sock); - } + ctxt = match->data; + if (!ctxt->session) + return -ENOTCONN; + + close(ctxt->session->sock); + return 0; } char *bt_uuid2string(uuid_t *uuid) diff --git a/common/glib-helper.h b/common/glib-helper.h index 6c9b89b0..8bb6b284 100644 --- a/common/glib-helper.h +++ b/common/glib-helper.h @@ -34,7 +34,7 @@ int bt_discover_services(const bdaddr_t *src, const bdaddr_t *dst, int bt_search_service(const bdaddr_t *src, const bdaddr_t *dst, uuid_t *uuid, bt_callback_t cb, void *user_data, bt_destroy_t destroy); -void bt_cancel_discovery(const bdaddr_t *src, const bdaddr_t *dst); +int bt_cancel_discovery(const bdaddr_t *src, const bdaddr_t *dst); gchar *bt_uuid2string(uuid_t *uuid); int bt_string2uuid(uuid_t *uuid, const char *string); -- cgit From 86a2b9551e7352b6f9115c0b057b0d9133079e25 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 24 Jun 2008 00:22:20 +0000 Subject: Use the safe versions for SDP record extraction --- common/glib-helper.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index eab30b5e..931b99a5 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -115,7 +115,7 @@ static void search_completed_cb(uint8_t type, uint16_t status, { struct search_context *ctxt = user_data; sdp_list_t *recs = NULL; - int scanned, seqlen = 0; + int scanned, seqlen = 0, bytesleft = size; uint8_t dataType; int err = 0; @@ -124,17 +124,18 @@ static void search_completed_cb(uint8_t type, uint16_t status, goto done; } - scanned = sdp_extract_seqtype(rsp, &dataType, &seqlen); + scanned = sdp_extract_seqtype_safe(rsp, bytesleft, &dataType, &seqlen); if (!scanned || !seqlen) goto done; rsp += scanned; + bytesleft -= scanned; do { sdp_record_t *rec; int recsize; recsize = 0; - rec = sdp_extract_pdu(rsp, &recsize); + rec = sdp_extract_pdu_safe(rsp, bytesleft, &recsize); if (!rec) break; @@ -145,9 +146,10 @@ static void search_completed_cb(uint8_t type, uint16_t status, scanned += recsize; rsp += recsize; + bytesleft -= recsize; recs = sdp_list_append(recs, rec); - } while (scanned < size); + } while (scanned < size && bytesleft > 0); done: sdp_close(ctxt->session); -- cgit From 3005856580174bb25cd0510115bed9499b1f1bdc Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 30 Jun 2008 14:05:38 +0000 Subject: Accept friendly names for discover services --- common/glib-helper.c | 40 +++++++++++++++++++++++++++++++++++++++- common/glib-helper.h | 1 + 2 files changed, 40 insertions(+), 1 deletion(-) (limited to 'common') diff --git a/common/glib-helper.c b/common/glib-helper.c index 931b99a5..f0435aca 100644 --- a/common/glib-helper.c +++ b/common/glib-helper.c @@ -386,10 +386,42 @@ char *bt_uuid2string(uuid_t *uuid) return str; } +static struct { + const char *name; + uint16_t class; +} bt_services[] = { + { "vcp", VIDEO_CONF_SVCLASS_ID }, + { "pbap", PBAP_SVCLASS_ID }, + { "sap", SAP_SVCLASS_ID }, + { "ftp", OBEX_FILETRANS_SVCLASS_ID }, + { "bpp", BASIC_PRINTING_SVCLASS_ID }, + { "bip", IMAGING_SVCLASS_ID }, + { "synch", IRMC_SYNC_SVCLASS_ID }, + { "dun", DIALUP_NET_SVCLASS_ID }, + { "opp", OBEX_OBJPUSH_SVCLASS_ID }, + { "fax", FAX_SVCLASS_ID }, + { "spp", SERIAL_PORT_SVCLASS_ID }, + { "hsp", HEADSET_SVCLASS_ID }, + { "hfp", HANDSFREE_SVCLASS_ID }, + { } +}; + +uint16_t bt_string2class(const char *pattern) +{ + int i; + + for (i = 0; bt_services[i].name; i++) { + if (strcasecmp(bt_services[i].name, pattern) == 0) + return bt_services[i].class; + } + + return 0; +} + int bt_string2uuid(uuid_t *uuid, const char *string) { - uint16_t data1, data2, data3, data5; uint32_t data0, data4; + uint16_t data1, data2, data3, data5; if (strlen(string) == 36 && string[8] == '-' && @@ -417,6 +449,12 @@ int bt_string2uuid(uuid_t *uuid, const char *string) sdp_uuid128_create(uuid, val); return 0; + } else { + uint16_t class = bt_string2class(string); + if (class) { + sdp_uuid16_create(uuid, class); + return 0; + } } return -1; diff --git a/common/glib-helper.h b/common/glib-helper.h index 8bb6b284..6b188f7f 100644 --- a/common/glib-helper.h +++ b/common/glib-helper.h @@ -37,6 +37,7 @@ int bt_search_service(const bdaddr_t *src, const bdaddr_t *dst, int bt_cancel_discovery(const bdaddr_t *src, const bdaddr_t *dst); gchar *bt_uuid2string(uuid_t *uuid); +uint16_t bt_string2class(const char *string); int bt_string2uuid(uuid_t *uuid, const char *string); gchar *bt_list2string(GSList *list); GSList *bt_string2list(const gchar *str); -- cgit