summaryrefslogtreecommitdiffstats
path: root/avahi-common
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2005-08-13 21:25:09 +0000
committerLennart Poettering <lennart@poettering.net>2005-08-13 21:25:09 +0000
commit4f0a5e7572a4257894b4bfede42c26d65152609e (patch)
tree21e3d5ee20716739590e5931859a4c2052161395 /avahi-common
parentd6d7d3769441b73ffb5b7af34fef823b41e66312 (diff)
* strip glib from avahi-core
* implement glib memory allocator * add new documentation file MALLOC * initialize pseudo-RNG from /dev/urandom in avahi-daemon * remove some gcc 4.0 warnings * beef up watch system with real timeouts * move GCC __attribute__ macros into its own header avahi-common/gccmacro.h * make use of GCC's sentinel attribute where it make sense * add malloc() implementations that abort on OOM and enable them by default git-svn-id: file:///home/lennart/svn/public/avahi/trunk@308 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe
Diffstat (limited to 'avahi-common')
-rw-r--r--avahi-common/Makefile.am3
-rw-r--r--avahi-common/domain-test.c2
-rw-r--r--avahi-common/domain.c17
-rw-r--r--avahi-common/domain.h5
-rw-r--r--avahi-common/error.c3
-rw-r--r--avahi-common/error.h3
-rw-r--r--avahi-common/gccmacro.h47
-rw-r--r--avahi-common/malloc.c71
-rw-r--r--avahi-common/malloc.h7
-rw-r--r--avahi-common/simple-watch.c120
-rw-r--r--avahi-common/simple-watch.h2
-rw-r--r--avahi-common/strlst.h5
-rw-r--r--avahi-common/watch-test.c41
-rw-r--r--avahi-common/watch.h3
14 files changed, 256 insertions, 73 deletions
diff --git a/avahi-common/Makefile.am b/avahi-common/Makefile.am
index c78e054..8ac6365 100644
--- a/avahi-common/Makefile.am
+++ b/avahi-common/Makefile.am
@@ -34,7 +34,8 @@ avahi_commoninclude_HEADERS = \
malloc.h
watch.h \
timeval.h \
- simple-watch.h
+ simple-watch.h \
+ gccmacro.h
noinst_HEADERS = llist.h
diff --git a/avahi-common/domain-test.c b/avahi-common/domain-test.c
index fc310c7..76f806a 100644
--- a/avahi-common/domain-test.c
+++ b/avahi-common/domain-test.c
@@ -45,7 +45,7 @@ int main(int argc, char *argv[]) {
printf("%i\n", avahi_domain_equal("a", "aaa"));
-/* printf("%u = %u\n", avahi_domain_hash("\\Aaaab\\\\."), avahi_domain_hash("aaaa\\b\\\\")); */
+ printf("%u = %u\n", avahi_domain_hash("\\Aaaab\\\\."), avahi_domain_hash("aaaa\\b\\\\"));
return 0;
}
diff --git a/avahi-common/domain.c b/avahi-common/domain.c
index 5a51a39..3703a04 100644
--- a/avahi-common/domain.c
+++ b/avahi-common/domain.c
@@ -320,3 +320,20 @@ int avahi_is_valid_host_name(const char *t) {
return 1;
}
+
+unsigned avahi_domain_hash(const char *s) {
+ unsigned hash = 0;
+
+ for (;;) {
+ char c[65], *p;
+
+ if (!avahi_unescape_label(&s, c, sizeof(c)))
+ return hash;
+
+ if (!c[0])
+ continue;
+
+ for (p = c; *p; p++)
+ hash = 31 * hash + tolower(*p);
+ }
+}
diff --git a/avahi-common/domain.h b/avahi-common/domain.h
index 83a9332..c9cc39e 100644
--- a/avahi-common/domain.h
+++ b/avahi-common/domain.h
@@ -65,6 +65,11 @@ int avahi_is_valid_service_name(const char *t);
/** Return 1 when the specified string contains a valid non-FQDN host name (i.e. without dots), 0 otherwise */
int avahi_is_valid_host_name(const char *t);
+/** Return some kind of hash value for the domain, useful for using domains as hash table keys. */
+unsigned avahi_domain_hash(const char *name);
+
+
+
AVAHI_C_DECL_END
#endif
diff --git a/avahi-common/error.c b/avahi-common/error.c
index 3dca208..b845793 100644
--- a/avahi-common/error.c
+++ b/avahi-common/error.c
@@ -47,7 +47,8 @@ const char *avahi_strerror(int error) {
"Access denied",
"Invalid operation",
"An unexpected DBUS error occured",
- "Could not get a connection to the daemon"
+ "Could not get a connection to the daemon",
+ "Memory exhausted"
};
if (-error < 0 || -error >= -AVAHI_ERR_MAX)
diff --git a/avahi-common/error.h b/avahi-common/error.h
index 223ba02..943b49c 100644
--- a/avahi-common/error.h
+++ b/avahi-common/error.h
@@ -54,7 +54,8 @@ enum {
AVAHI_ERR_INVALID_OPERATION = -21, /**< Invalid operation */
AVAHI_ERR_DBUS_ERROR = -22, /**< An unexpected DBUS error occured */
AVAHI_ERR_NOT_CONNECTED = -23, /**< Could not get a connection to the daemon */
- AVAHI_ERR_MAX = -24
+ AVAHI_ERR_NO_MEMORY = -24, /**< Memory exhausted */
+ AVAHI_ERR_MAX = -25
};
/** Return a human readable error string for the specified error code */
diff --git a/avahi-common/gccmacro.h b/avahi-common/gccmacro.h
new file mode 100644
index 0000000..42fb153
--- /dev/null
+++ b/avahi-common/gccmacro.h
@@ -0,0 +1,47 @@
+#ifndef foogccmacrohfoo
+#define foogccmacrohfoo
+
+/* $Id$ */
+
+/***
+ This file is part of avahi.
+
+ avahi is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ avahi 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 Lesser General
+ Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with avahi; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef __GNUC__
+#define AVAHI_GCC_SENTINEL __attribute__ ((sentinel))
+#else
+#define AVAHI_GCC_SENTINEL
+#endif
+
+#ifdef __GNUC__
+#define AVAHI_GCC_PRINTF_ATTR(a,b) __attribute__ ((format (printf, a, b)))
+#else
+/** Macro for usage of GCC's printf compilation warnings */
+#define AVAHI_GCC_PRINTF_ATTR(a,b)
+#endif
+
+#define AVAHI_GCC_PRINTF_ATTR12 AVAHI_GCC_PRINTF_ATTR(1,2)
+#define AVAHI_GCC_PRINTF_ATTR23 AVAHI_GCC_PRINTF_ATTR(2,3)
+
+#ifdef __GNUC__
+#define AVAHI_GCC_NORETURN __attribute__((noreturn))
+#else
+#define AVAHI_GCC_NORETURN
+#endif
+
+#endif
diff --git a/avahi-common/malloc.c b/avahi-common/malloc.c
index 1883849..018a0c0 100644
--- a/avahi-common/malloc.c
+++ b/avahi-common/malloc.c
@@ -27,18 +27,78 @@
#include <string.h>
#include <assert.h>
#include <stdio.h>
+#include <unistd.h>
#include "malloc.h"
static const AvahiAllocator *allocator = NULL;
+static void oom(void) AVAHI_GCC_NORETURN;
+
+static void oom(void) {
+
+ static const char msg[] = "Out of memory, aborting ...\n";
+ const char *n = msg;
+
+ while (strlen(n) > 0) {
+ ssize_t r;
+
+ if ((r = write(2, n, strlen(n))) < 0)
+ break;
+
+ n += r;
+ }
+
+ abort();
+}
+
+/* Default implementation for avahi_malloc() */
+static void* xmalloc(size_t size) {
+ void *p;
+
+ if (size == 0)
+ return NULL;
+
+ if (!(p = malloc(size)))
+ oom();
+
+ return p;
+}
+
+/* Default implementation for avahi_realloc() */
+static void *xrealloc(void *p, size_t size) {
+
+ if (size == 0) {
+ free(p);
+ return NULL;
+ }
+
+ if (!(p = realloc(p, size)))
+ oom();
+
+ return p;
+}
+
+/* Default implementation for avahi_calloc() */
+static void *xcalloc(size_t nmemb, size_t size) {
+ void *p;
+
+ if (size == 0 || nmemb == 0)
+ return NULL;
+
+ if (!(p = calloc(nmemb, size)))
+ oom();
+
+ return p;
+}
+
void *avahi_malloc(size_t size) {
if (size <= 0)
return NULL;
if (!allocator)
- return malloc(size);
+ return xmalloc(size);
assert(allocator->malloc);
return allocator->malloc(size);
@@ -51,7 +111,7 @@ void *avahi_malloc0(size_t size) {
return NULL;
if (!allocator)
- return calloc(1, size);
+ return xcalloc(1, size);
if (allocator->calloc)
return allocator->calloc(1, size);
@@ -79,8 +139,13 @@ void avahi_free(void *p) {
void *avahi_realloc(void *p, size_t size) {
+ if (size == 0) {
+ avahi_free(p);
+ return NULL;
+ }
+
if (!allocator)
- return realloc(p, size);
+ return xrealloc(p, size);
assert(allocator->realloc);
return allocator->realloc(p, size);
diff --git a/avahi-common/malloc.h b/avahi-common/malloc.h
index b658357..6d10226 100644
--- a/avahi-common/malloc.h
+++ b/avahi-common/malloc.h
@@ -28,6 +28,7 @@
#include <stdarg.h>
#include <avahi-common/cdecl.h>
+#include <avahi-common/gccmacro.h>
AVAHI_C_DECL_BEGIN
@@ -73,12 +74,8 @@ struct AvahiAllocator {
* allocators. The structure is not copied! */
void avahi_set_allocator(const AvahiAllocator *a);
-#ifdef __GNUC__
-char *avahi_strdup_printf(const char *fmt, ... ) __attribute__ ((format(printf, 1, 2)));
-#else
/** Like sprintf() but store the result in a freshly allocated buffer. Free this with avahi_free() */
-char *avahi_strdup_printf(const char *fmt, ... );
-#endif
+char *avahi_strdup_printf(const char *fmt, ... ) AVAHI_GCC_PRINTF_ATTR12;
/** Same as avahi_strdup_printf() but take a va_list instead of varargs */
char *avahi_strdup_vprintf(const char *fmt, va_list ap);
diff --git a/avahi-common/simple-watch.c b/avahi-common/simple-watch.c
index acc0923..3caf371 100644
--- a/avahi-common/simple-watch.c
+++ b/avahi-common/simple-watch.c
@@ -51,7 +51,8 @@ struct AvahiSimplePoll {
int n_pollfds, max_pollfds, rebuild_pollfds;
struct timeval wakeup;
- int use_wakeup;
+ AvahiWakeupCallback wakeup_callback;
+ void *wakeup_userdata;
int req_cleanup;
@@ -141,17 +142,24 @@ static void watch_free(AvahiWatch *w) {
w->simple_poll->req_cleanup = 1;
}
-static void set_wakeup_time(AvahiPoll *api, const struct timeval *tv) {
+static void set_wakeup(AvahiPoll *api, const struct timeval *tv, AvahiWakeupCallback callback, void *userdata) {
AvahiSimplePoll *s;
assert(api);
s = api->userdata;
- if (tv) {
- s->wakeup = *tv;
- s->use_wakeup = 1;
+ if (callback) {
+ if (tv)
+ s->wakeup = *tv;
+ else {
+ s->wakeup.tv_sec = 0;
+ s->wakeup.tv_usec = 0;
+ }
+
+ s->wakeup_callback = callback;
+ s->wakeup_userdata = userdata;
} else
- s->use_wakeup = 0;
+ s->wakeup_callback = NULL;
}
static void destroy_watch(AvahiWatch *w) {
@@ -190,10 +198,10 @@ AvahiSimplePoll *avahi_simple_poll_new(void) {
s->api.watch_new = watch_new;
s->api.watch_free = watch_free;
s->api.watch_update = watch_update;
- s->api.set_wakeup_time = set_wakeup_time;
+ s->api.set_wakeup = set_wakeup;
s->pollfds = NULL;
s->max_pollfds = s->n_pollfds = 0;
- s->use_wakeup = 0;
+ s->wakeup_callback = NULL;
s->rebuild_pollfds = 0;
s->quit = 0;
s->n_watches = 0;
@@ -248,41 +256,84 @@ static int rebuild(AvahiSimplePoll *s) {
return 0;
}
-int avahi_simple_poll_iterate(AvahiSimplePoll *s, int block) {
- int timeout, r, ret = 0;
+static int start_wakeup_callback(AvahiSimplePoll *s) {
+ AvahiWakeupCallback callback;
+ void *userdata;
+
assert(s);
- if (s->quit)
- return 1;
+ /* Reset the wakeup functions, but allow changing of the two
+ values from the callback function */
+
+ callback = s->wakeup_callback;
+ userdata = s->wakeup_userdata;
+ s->wakeup_callback = NULL;
+ s->wakeup_userdata = NULL;
+
+ assert(callback);
+
+ callback(&s->api, userdata);
+ return 0;
+}
+
+int avahi_simple_poll_iterate(AvahiSimplePoll *s, int timeout) {
+ int r;
+ assert(s);
+ /* Cleanup things first */
if (s->req_cleanup)
cleanup(s, 0);
-
+
+ /* Check whether a quit was requested */
+ if (s->quit)
+ return 1;
+
+ /* Do we need to rebuild our array of pollfds? */
if (s->rebuild_pollfds)
if (rebuild(s) < 0)
return -1;
- if (block) {
- if (s->use_wakeup) {
- struct timeval now;
- AvahiUsec usec;
+ /* Calculate the wakeup time */
+ if (s->wakeup_callback) {
+ struct timeval now;
+ int t;
+ AvahiUsec usec;
- gettimeofday(&now, NULL);
+ gettimeofday(&now, NULL);
+ usec = avahi_timeval_diff(&s->wakeup, &now);
- usec = avahi_timeval_diff(&s->wakeup, &now);
-
- timeout = usec <= 0 ? 0 : (int) (usec / 1000);
- } else
- timeout = -1;
- } else
- timeout = 0;
+ if (usec <= 0)
+ /* Timeout elapsed */
+
+ return start_wakeup_callback(s);
+
+ /* Calculate sleep time. We add 1ms because otherwise we'd
+ * wake up too early most of the time */
+ t = (int) (usec / 1000) + 1;
+
+ if (timeout < 0 || timeout > t)
+ timeout = t;
+ }
if ((r = poll(s->pollfds, s->n_pollfds, timeout)) < 0)
return -1;
- else if (r > 0) {
+ /* Check whether the wakeup time has been reached now */
+ if (s->wakeup_callback) {
+ struct timeval now;
+
+ gettimeofday(&now, NULL);
+
+ if (avahi_timeval_compare(&s->wakeup, &now) <= 0)
+ /* Time elapsed */
+ return start_wakeup_callback(s);
+ }
+
+ if (r > 0) {
AvahiWatch *w;
+ /* Look for some kind of I/O event */
+
for (w = s->watches; w; w = w->watches_next) {
if (w->dead)
@@ -291,24 +342,15 @@ int avahi_simple_poll_iterate(AvahiSimplePoll *s, int block) {
assert(w->idx >= 0);
assert(w->idx < s->n_pollfds);
- if (s->pollfds[w->idx].revents > 0)
+ if (s->pollfds[w->idx].revents > 0) {
+ /* We execute only on callback in every iteration */
w->callback(w, w->pollfd.fd, s->pollfds[w->idx].revents, w->userdata);
-
- if (s->quit) {
- ret = 1;
- goto finish;
+ return 0;
}
}
}
- ret = 0;
-
-finish:
-
- if (s->req_cleanup)
- cleanup(s, 0);
-
- return ret;
+ return 0;
}
void avahi_simple_poll_quit(AvahiSimplePoll *w) {
diff --git a/avahi-common/simple-watch.h b/avahi-common/simple-watch.h
index 600e5ce..127ddc5 100644
--- a/avahi-common/simple-watch.h
+++ b/avahi-common/simple-watch.h
@@ -35,7 +35,7 @@ void avahi_simple_poll_free(AvahiSimplePoll *s);
AvahiPoll* avahi_simple_poll_get(AvahiSimplePoll *s);
-int avahi_simple_poll_iterate(AvahiSimplePoll *s, int block);
+int avahi_simple_poll_iterate(AvahiSimplePoll *s, int sleep_time);
void avahi_simple_poll_quit(AvahiSimplePoll *s);
diff --git a/avahi-common/strlst.h b/avahi-common/strlst.h
index 56bf525..10b7aa6 100644
--- a/avahi-common/strlst.h
+++ b/avahi-common/strlst.h
@@ -29,6 +29,7 @@
#include <stdarg.h>
#include <avahi-common/cdecl.h>
+#include <avahi-common/gccmacro.h>
AVAHI_C_DECL_BEGIN
@@ -47,7 +48,7 @@ typedef struct AvahiStringList {
/** Create a new string list by taking a variable list of NUL
* terminated strings. The strings are copied using g_strdup(). The
* argument list must be terminated by a NULL pointer. */
-AvahiStringList *avahi_string_list_new(const char *txt, ...);
+AvahiStringList *avahi_string_list_new(const char *txt, ...) AVAHI_GCC_SENTINEL;
/** Same as avahi_string_list_new() but pass a va_list structure */
AvahiStringList *avahi_string_list_new_va(va_list va);
@@ -79,7 +80,7 @@ AvahiStringList*avahi_string_list_add_anonymous(AvahiStringList *l, size_t size)
/** Same as avahi_string_list_add(), but takes a variable number of
* NUL terminated strings. The argument list must be terminated by a
* NULL pointer. Returns the new list start. */
-AvahiStringList *avahi_string_list_add_many(AvahiStringList *r, ...);
+AvahiStringList *avahi_string_list_add_many(AvahiStringList *r, ...) AVAHI_GCC_SENTINEL;
/** Same as avahi_string_list_add_many(), but use a va_list
* structure. Returns the new list start. */
diff --git a/avahi-common/watch-test.c b/avahi-common/watch-test.c
index f87a303..af46805 100644
--- a/avahi-common/watch-test.c
+++ b/avahi-common/watch-test.c
@@ -34,6 +34,7 @@
#include "timeval.h"
static AvahiPoll *api = NULL;
+static AvahiSimplePoll *simple_poll = NULL;
static void callback(AvahiWatch *w, int fd, AvahiWatchEvent event, void *userdata) {
@@ -51,31 +52,35 @@ static void callback(AvahiWatch *w, int fd, AvahiWatchEvent event, void *userdat
}
}
+static void wakeup(AvahiPoll *_api, void *userdata) {
+ static int i = 0;
+ struct timeval tv;
+
+ printf("Wakeup #%i\n", i++);
+
+ if (i > 10)
+ avahi_simple_poll_quit(simple_poll);
+ else {
+ avahi_elapse_time(&tv, 1000, 0);
+ api->set_wakeup(api, &tv, wakeup, NULL);
+ }
+}
+
int main(int argc, char *argv[]) {
- int i = 0;
- AvahiSimplePoll *s;
+ struct timeval tv;
- s = avahi_simple_poll_new();
- assert(s);
-
- api = avahi_simple_poll_get(s);
+ simple_poll = avahi_simple_poll_new();
+ api = avahi_simple_poll_get(simple_poll);
api->watch_new(api, 0, AVAHI_WATCH_IN, callback, NULL);
- for (;;) {
- struct timeval tv;
- printf("Iteration %i\n", i++);
-
- if (i > 100)
- avahi_simple_poll_quit(s);
+ avahi_elapse_time(&tv, 1000, 0);
+ api->set_wakeup(api, &tv, wakeup, NULL);
- avahi_elapse_time(&tv, 1000, 0);
-
- api->set_wakeup_time(api, &tv);
-
- if (avahi_simple_poll_iterate(s, 1) != 0)
+ /* Our main loop */
+ for (;;)
+ if (avahi_simple_poll_iterate(simple_poll, -1) != 0)
break;
- }
return 0;
}
diff --git a/avahi-common/watch.h b/avahi-common/watch.h
index b26c2ba..70dedb7 100644
--- a/avahi-common/watch.h
+++ b/avahi-common/watch.h
@@ -40,6 +40,7 @@ typedef enum {
} AvahiWatchEvent;
typedef void (*AvahiWatchCallback)(AvahiWatch *w, int fd, AvahiWatchEvent event, void *userdata);
+typedef void (*AvahiWakeupCallback)(AvahiPoll *api, void *userdata);
struct AvahiPoll {
void* userdata;
@@ -48,7 +49,7 @@ struct AvahiPoll {
void (*watch_update)(AvahiWatch *w, AvahiWatchEvent event);
void (*watch_free)(AvahiWatch *w);
- void (*set_wakeup_time)(AvahiPoll *api, const struct timeval *tv);
+ void (*set_wakeup)(AvahiPoll *api, const struct timeval *tv, AvahiWakeupCallback callback, void *userdata);
};
AVAHI_C_DECL_END