From: Lennart Poettering Date: Fri, 12 Aug 2005 00:25:52 +0000 (+0000) Subject: Split avahi-common/util.h into X-Git-Url: https://git.meshlink.io/?a=commitdiff_plain;h=5ebf655c85076f200955458673a8bbf0dd927407;p=catta Split avahi-common/util.h into avahi-common/domain.h avahi-core/fdutil.h avahi-core/timeval.h git-svn-id: file:///home/lennart/svn/public/avahi/trunk@299 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe --- diff --git a/avahi-common/Makefile.am b/avahi-common/Makefile.am index 3b025be..20eaee3 100644 --- a/avahi-common/Makefile.am +++ b/avahi-common/Makefile.am @@ -32,7 +32,7 @@ avahi_commoninclude_HEADERS = \ strlst.h \ address.h \ alternative.h \ - util.h \ + domain.h \ cdecl.h \ defs.h \ malloc.h @@ -46,8 +46,7 @@ noinst_HEADERS = llist.h noinst_PROGRAMS = \ strlst-test \ domain-test \ - alternative-test \ - timeval-test + alternative-test lib_LTLIBRARIES = \ libavahi-common.la @@ -58,7 +57,7 @@ libavahi_common_la_SOURCES = \ alternative.c alternative.h \ error.c error.h \ strlst.c strlst.h \ - util.c util.h + domain.c domain.h libavahi_common_la_CFLAGS = $(AM_CFLAGS) libavahi_common_la_LIBADD = $(AM_LDADD) @@ -72,22 +71,15 @@ strlst_test_LDADD = $(AM_LDADD) alternative_test_SOURCES = \ alternative.c alternative.h \ malloc.c malloc.h \ - util.c util.h \ + domain.c domain.h \ alternative-test.c alternative_test_CFLAGS = $(AM_CFLAGS) alternative_test_LDADD = $(AM_LDADD) domain_test_SOURCES = \ - util.c util.h \ + domain.c domain.h \ malloc.c malloc.h \ domain-test.c domain_test_CFLAGS = $(AM_CFLAGS) domain_test_LDADD = $(AM_LDADD) -timeval_test_SOURCES = \ - util.c util.h \ - malloc.c malloc.h \ - timeval-test.c -timeval_test_CFLAGS = $(AM_CFLAGS) -timeval_test_LDADD = $(AM_LDADD) - diff --git a/avahi-common/address.c b/avahi-common/address.c index c638b41..50224ed 100644 --- a/avahi-common/address.c +++ b/avahi-common/address.c @@ -30,7 +30,6 @@ #include #include "address.h" -#include "util.h" #include "malloc.h" size_t avahi_address_get_size(const AvahiAddress *a) { diff --git a/avahi-common/alternative.c b/avahi-common/alternative.c index 53a1e6c..436a0d4 100644 --- a/avahi-common/alternative.c +++ b/avahi-common/alternative.c @@ -30,7 +30,6 @@ #include "alternative.h" #include "malloc.h" -#include "util.h" char * avahi_alternative_host_name(const char *s) { const char *p, *e; diff --git a/avahi-common/domain-test.c b/avahi-common/domain-test.c index a9ad0b6..0113a8b 100644 --- a/avahi-common/domain-test.c +++ b/avahi-common/domain-test.c @@ -25,7 +25,7 @@ #include -#include "util.h" +#include "domain.h" #include "malloc.h" int main(int argc, char *argv[]) { diff --git a/avahi-common/domain.c b/avahi-common/domain.c new file mode 100644 index 0000000..b1e7cfe --- /dev/null +++ b/avahi-common/domain.c @@ -0,0 +1,369 @@ +/* $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 HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "domain.h" +#include "malloc.h" + +char *avahi_get_host_name(void) { +#ifdef HOST_NAME_MAX + char t[HOST_NAME_MAX]; +#else + char t[256]; +#endif + gethostname(t, sizeof(t)); + t[sizeof(t)-1] = 0; + return avahi_normalize_name(t); +} + +static char *unescape_uneeded(const char *src, char *ret_dest, size_t size) { + int escaped = 0; + + assert(src); + assert(ret_dest); + assert(size > 0); + + for (; *src; src++) { + + if (!escaped && *src == '\\') + escaped = 1; + else if (escaped && (*src == '.' || *src == '\\')) { + + if ((size -= 2) <= 1) break; + + *(ret_dest++) = '\\'; + *(ret_dest++) = *src; + escaped = 0; + } else { + if (--size <= 1) break; + + *(ret_dest++) = *src; + escaped = 0; + } + + } + + *ret_dest = 0; + + return ret_dest; +} + +char *avahi_normalize_name(const char *s) { + char tmp[256]; + size_t l; + + assert(s); + + unescape_uneeded(s, tmp, sizeof(tmp)); + + l = strlen(tmp); + + while (l > 0 && tmp[l-1] == '.') + tmp[--l] = 0; + + return avahi_strdup(tmp); +} + + +/* Read the first label from string *name, unescape "\" and write it to dest */ +char *avahi_unescape_label(const char **name, char *dest, size_t size) { + unsigned i = 0; + char *d; + + assert(dest); + assert(size > 0); + assert(name); + + if (!**name) + return NULL; + + d = dest; + + for (;;) { + if (i >= size) + return NULL; + + if (**name == '.') { + (*name)++; + break; + } + + if (**name == 0) + break; + + if (**name == '\\') { + (*name) ++; + + if (**name == 0) + break; + } + + *(d++) = *((*name) ++); + i++; + } + + assert(i < size); + + *d = 0; + + return dest; +} + +/* Escape "\" and ".", append \0 */ +char *avahi_escape_label(const uint8_t* src, size_t src_length, char **ret_name, size_t *ret_size) { + char *r; + + assert(src); + assert(ret_name); + assert(*ret_name); + assert(ret_size); + assert(*ret_size > 0); + + r = *ret_name; + + while (src_length > 0) { + if (*src == '.' || *src == '\\') { + if (*ret_size < 3) + return NULL; + + *((*ret_name) ++) = '\\'; + (*ret_size) --; + } + + if (*ret_size < 2) + return NULL; + + *((*ret_name)++) = *src; + (*ret_size) --; + + src_length --; + src++; + } + + **ret_name = 0; + + return r; +} + +int avahi_domain_equal(const char *a, const char *b) { + assert(a); + assert(b); + + if (a == b) + return 1; + + for (;;) { + char ca[65], cb[65], *pa, *pb; + + pa = avahi_unescape_label(&a, ca, sizeof(ca)); + pb = avahi_unescape_label(&b, cb, sizeof(cb)); + + if (!pa && !pb) + return 1; + else if ((pa && !pb) || (!pa && pb)) + return 0; + + if (strcasecmp(pa, pb)) + return 0; + } + + return 1; +} + +int avahi_binary_domain_cmp(const char *a, const char *b) { + assert(a); + assert(b); + + if (a == b) + return 0; + + for (;;) { + char ca[65], cb[65], *pa, *pb; + int r; + + pa = avahi_unescape_label(&a, ca, sizeof(ca)); + pb = avahi_unescape_label(&b, cb, sizeof(cb)); + + if (!pa && !pb) + return 0; + else if (pa && !pb) + return 1; + else if (!pa && pb) + return -1; + + if ((r = strcmp(pa, pb))) + return r; + } +} + +unsigned avahi_strhash(const char *p) { + unsigned hash = 0; + + for (; *p; p++) + hash = 31 * hash + *p; + + return hash; +} + +unsigned avahi_domain_hash(const char *s) { + unsigned hash = 0; + + for (;;) { + char c[65]; + + if (!avahi_unescape_label(&s, c, sizeof(c))) + return hash; + + if (!c[0]) + continue; + + hash += avahi_strhash(avahi_strdown(c)); + } +} + +int avahi_valid_service_type(const char *t) { + const char *p; + assert(t); + + if (strlen(t) < 5) + return 0; + + if (*t != '_') + return 0; + + if (!(p = strchr(t, '.'))) + return 0; + + if (p - t > 63 || p - t < 2) + return 0; + + if (*(++p) != '_') + return 0; + + if (strchr(p, '.')) + return 0; + + if (strlen(p) > 63 || strlen(p) < 2) + return 0; + + return 1; +} + +int avahi_valid_domain_name(const char *t) { + const char *p, *dp; + int dot = 0; + + assert(t); + + if (*t == 0) + return 0; + + /* Domains may not start with a dot */ + if (*t == '.') + return 0; + + dp = t; + + for (p = t; *p; p++) { + + if (*p == '.') { + if (dot) /* Two subsequent dots */ + return 0; + + if (p - dp > 63) + return 0; + + dot = 1; + dp = p + 1; + } else + dot = 0; + + } + + if (p - dp > 63) + return 0; + + /* A trailing dot IS allowed */ + + return 1; +} + +int avahi_valid_service_name(const char *t) { + assert(t); + + if (*t == 0) + return 0; + + if (strlen(t) > 63) + return 0; + + return 1; +} + +int avahi_valid_host_name(const char *t) { + assert(t); + + if (*t == 0) + return 0; + + if (strlen(t) > 63) + return 0; + + if (strchr(t, '.')) + return 0; + + return 1; +} + +char *avahi_strdown(char *s) { + char *c; + + assert(s); + + for (c = s; *c; c++) + *c = (char) tolower(*c); + + return s; +} + +char *avahi_strup(char *s) { + char *c; + assert(s); + + for (c = s; *c; c++) + *c = (char) toupper(*c); + + return s; +} + diff --git a/avahi-common/domain.h b/avahi-common/domain.h new file mode 100644 index 0000000..4a94be1 --- /dev/null +++ b/avahi-common/domain.h @@ -0,0 +1,58 @@ +#ifndef foodomainhfoo +#define foodimainhfoo + +/* $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. +***/ + +#include +#include + +#include + +AVAHI_C_DECL_BEGIN + +char *avahi_normalize_name(const char *s); /* avahi_free() the result! */ +char *avahi_get_host_name(void); /* avahi_free() the result! */ + +int avahi_domain_equal(const char *a, const char *b); +int avahi_binary_domain_cmp(const char *a, const char *b); + +/* Read the first label from the textual domain name *name, unescape + * it and write it to dest, *name is changed to point to the next label*/ +char *avahi_unescape_label(const char **name, char *dest, size_t size); + +/* Escape the domain name in *src and write it to *ret_name */ +char *avahi_escape_label(const uint8_t* src, size_t src_length, char **ret_name, size_t *ret_size); + +unsigned avahi_strhash(const char *p); +unsigned avahi_domain_hash(const char *s); + +int avahi_valid_service_type(const char *t); +int avahi_valid_domain_name(const char *t); +int avahi_valid_service_name(const char *t); +int avahi_valid_host_name(const char *t); + +char *avahi_strup(char *s); +char *avahi_strdown(char *s); + +AVAHI_C_DECL_END + +#endif diff --git a/avahi-common/timeval-test.c b/avahi-common/timeval-test.c deleted file mode 100644 index 6f44034..0000000 --- a/avahi-common/timeval-test.c +++ /dev/null @@ -1,41 +0,0 @@ -/* $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 HAVE_CONFIG_H -#include -#endif - -#include -#include "util.h" - -int main(int argc, char *argv[]) { - - struct timeval a = { 5, 5 }, b; - - b = a; - - printf("%li.%li\n", a.tv_sec, a.tv_usec); - avahi_timeval_add(&a, -50); - - printf("%li.%li\n", a.tv_sec, a.tv_usec); - - printf("%lli\n", avahi_timeval_diff(&a, &b)); -} diff --git a/avahi-common/util.c b/avahi-common/util.c deleted file mode 100644 index cc80fe5..0000000 --- a/avahi-common/util.c +++ /dev/null @@ -1,540 +0,0 @@ -/* $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 HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "util.h" -#include "malloc.h" - -char *avahi_get_host_name(void) { -#ifdef HOST_NAME_MAX - char t[HOST_NAME_MAX]; -#else - char t[256]; -#endif - gethostname(t, sizeof(t)); - t[sizeof(t)-1] = 0; - return avahi_normalize_name(t); -} - -static char *unescape_uneeded(const char *src, char *ret_dest, size_t size) { - int escaped = 0; - - assert(src); - assert(ret_dest); - assert(size > 0); - - for (; *src; src++) { - - if (!escaped && *src == '\\') - escaped = 1; - else if (escaped && (*src == '.' || *src == '\\')) { - - if ((size -= 2) <= 1) break; - - *(ret_dest++) = '\\'; - *(ret_dest++) = *src; - escaped = 0; - } else { - if (--size <= 1) break; - - *(ret_dest++) = *src; - escaped = 0; - } - - } - - *ret_dest = 0; - - return ret_dest; -} - -char *avahi_normalize_name(const char *s) { - char tmp[256]; - size_t l; - - assert(s); - - unescape_uneeded(s, tmp, sizeof(tmp)); - - l = strlen(tmp); - - while (l > 0 && tmp[l-1] == '.') - tmp[--l] = 0; - - return avahi_strdup(tmp); -} - -int avahi_timeval_compare(const struct timeval *a, const struct timeval *b) { - assert(a); - assert(b); - - if (a->tv_sec < b->tv_sec) - return -1; - - if (a->tv_sec > b->tv_sec) - return 1; - - if (a->tv_usec < b->tv_usec) - return -1; - - if (a->tv_usec > b->tv_usec) - return 1; - - return 0; -} - -AvahiUsec avahi_timeval_diff(const struct timeval *a, const struct timeval *b) { - assert(a); - assert(b); - - if (avahi_timeval_compare(a, b) < 0) - return - avahi_timeval_diff(b, a); - - return ((AvahiUsec) a->tv_sec - b->tv_sec)*1000000 + a->tv_usec - b->tv_usec; -} - -struct timeval* avahi_timeval_add(struct timeval *a, AvahiUsec usec) { - AvahiUsec u; - assert(a); - - u = usec + a->tv_usec; - - if (u < 0) { - a->tv_usec = (long) (1000000 + (u % 1000000)); - a->tv_sec += (long) (-1 + (u / 1000000)); - } else { - a->tv_usec = (long) (u % 1000000); - a->tv_sec += (long) (u / 1000000); - } - - return a; -} - -AvahiUsec avahi_age(const struct timeval *a) { - struct timeval now; - - assert(a); - - gettimeofday(&now, NULL); - - return avahi_timeval_diff(&now, a); -} - - -struct timeval *avahi_elapse_time(struct timeval *tv, unsigned msec, unsigned jitter) { - assert(tv); - - gettimeofday(tv, NULL); - - if (msec) - avahi_timeval_add(tv, (AvahiUsec) msec*1000); - - if (jitter) - avahi_timeval_add(tv, (AvahiUsec) (jitter*1000.0*rand()/(RAND_MAX+1.0))); - - return tv; -} - -int avahi_set_cloexec(int fd) { - int n; - - assert(fd >= 0); - - if ((n = fcntl(fd, F_GETFD)) < 0) - return -1; - - if (n & FD_CLOEXEC) - return 0; - - return fcntl(fd, F_SETFD, n|FD_CLOEXEC); -} - -int avahi_set_nonblock(int fd) { - int n; - - assert(fd >= 0); - - if ((n = fcntl(fd, F_GETFL)) < 0) - return -1; - - if (n & O_NONBLOCK) - return 0; - - return fcntl(fd, F_SETFL, n|O_NONBLOCK); -} - -int avahi_wait_for_write(int fd) { - fd_set fds; - int r; - - FD_ZERO(&fds); - FD_SET(fd, &fds); - - if ((r = select(fd+1, NULL, &fds, NULL, NULL)) < 0) - return -1; - - assert(r > 0); - - return 0; -} - -/* Read the first label from string *name, unescape "\" and write it to dest */ -char *avahi_unescape_label(const char **name, char *dest, size_t size) { - unsigned i = 0; - char *d; - - assert(dest); - assert(size > 0); - assert(name); - - if (!**name) - return NULL; - - d = dest; - - for (;;) { - if (i >= size) - return NULL; - - if (**name == '.') { - (*name)++; - break; - } - - if (**name == 0) - break; - - if (**name == '\\') { - (*name) ++; - - if (**name == 0) - break; - } - - *(d++) = *((*name) ++); - i++; - } - - assert(i < size); - - *d = 0; - - return dest; -} - -/* Escape "\" and ".", append \0 */ -char *avahi_escape_label(const uint8_t* src, size_t src_length, char **ret_name, size_t *ret_size) { - char *r; - - assert(src); - assert(ret_name); - assert(*ret_name); - assert(ret_size); - assert(*ret_size > 0); - - r = *ret_name; - - while (src_length > 0) { - if (*src == '.' || *src == '\\') { - if (*ret_size < 3) - return NULL; - - *((*ret_name) ++) = '\\'; - (*ret_size) --; - } - - if (*ret_size < 2) - return NULL; - - *((*ret_name)++) = *src; - (*ret_size) --; - - src_length --; - src++; - } - - **ret_name = 0; - - return r; -} - -int avahi_domain_equal(const char *a, const char *b) { - assert(a); - assert(b); - - if (a == b) - return 1; - - for (;;) { - char ca[65], cb[65], *pa, *pb; - - pa = avahi_unescape_label(&a, ca, sizeof(ca)); - pb = avahi_unescape_label(&b, cb, sizeof(cb)); - - if (!pa && !pb) - return 1; - else if ((pa && !pb) || (!pa && pb)) - return 0; - - if (strcasecmp(pa, pb)) - return 0; - } - - return 1; -} - -int avahi_binary_domain_cmp(const char *a, const char *b) { - assert(a); - assert(b); - - if (a == b) - return 0; - - for (;;) { - char ca[65], cb[65], *pa, *pb; - int r; - - pa = avahi_unescape_label(&a, ca, sizeof(ca)); - pb = avahi_unescape_label(&b, cb, sizeof(cb)); - - if (!pa && !pb) - return 0; - else if (pa && !pb) - return 1; - else if (!pa && pb) - return -1; - - if ((r = strcmp(pa, pb))) - return r; - } -} - -void avahi_hexdump(const void* p, size_t size) { - const uint8_t *c = p; - assert(p); - - printf("Dumping %u bytes from %p:\n", size, p); - - while (size > 0) { - unsigned i; - - for (i = 0; i < 16; i++) { - if (i < size) - printf("%02x ", c[i]); - else - printf(" "); - } - - for (i = 0; i < 16; i++) { - if (i < size) - printf("%c", c[i] >= 32 && c[i] < 127 ? c[i] : '.'); - else - printf(" "); - } - - printf("\n"); - - c += 16; - - if (size <= 16) - break; - - size -= 16; - } -} - -unsigned avahi_strhash(const char *p) { - unsigned hash = 0; - - for (; *p; p++) - hash = 31 * hash + *p; - - return hash; -} - -unsigned avahi_domain_hash(const char *s) { - unsigned hash = 0; - - for (;;) { - char c[65]; - - if (!avahi_unescape_label(&s, c, sizeof(c))) - return hash; - - if (!c[0]) - continue; - - hash += avahi_strhash(avahi_strdown(c)); - } -} - -char *avahi_format_mac_address(const uint8_t* mac, size_t size) { - char *r, *t; - unsigned i; - static const char hex[] = "0123456789abcdef"; - - t = r = avahi_new(char, size > 0 ? size*3 : 1); - - if (size <= 0) { - *r = 0; - return r; - } - - for (i = 0; i < size; i++) { - *(t++) = hex[*mac >> 4]; - *(t++) = hex[*mac & 0xF]; - *(t++) = ':'; - - mac++; - } - - *(--t) = 0; - return r; -} - -int avahi_valid_service_type(const char *t) { - const char *p; - assert(t); - - if (strlen(t) < 5) - return 0; - - if (*t != '_') - return 0; - - if (!(p = strchr(t, '.'))) - return 0; - - if (p - t > 63 || p - t < 2) - return 0; - - if (*(++p) != '_') - return 0; - - if (strchr(p, '.')) - return 0; - - if (strlen(p) > 63 || strlen(p) < 2) - return 0; - - return 1; -} - -int avahi_valid_domain_name(const char *t) { - const char *p, *dp; - int dot = 0; - - assert(t); - - if (*t == 0) - return 0; - - /* Domains may not start with a dot */ - if (*t == '.') - return 0; - - dp = t; - - for (p = t; *p; p++) { - - if (*p == '.') { - if (dot) /* Two subsequent dots */ - return 0; - - if (p - dp > 63) - return 0; - - dot = 1; - dp = p + 1; - } else - dot = 0; - - } - - if (p - dp > 63) - return 0; - - /* A trailing dot IS allowed */ - - return 1; -} - -int avahi_valid_service_name(const char *t) { - assert(t); - - if (*t == 0) - return 0; - - if (strlen(t) > 63) - return 0; - - return 1; -} - -int avahi_valid_host_name(const char *t) { - assert(t); - - if (*t == 0) - return 0; - - if (strlen(t) > 63) - return 0; - - if (strchr(t, '.')) - return 0; - - return 1; -} - -char *avahi_strdown(char *s) { - char *c; - - assert(s); - - for (c = s; *c; c++) - *c = (char) tolower(*c); - - return s; -} - -char *avahi_strup(char *s) { - char *c; - assert(s); - - for (c = s; *c; c++) - *c = (char) toupper(*c); - - return s; -} - diff --git a/avahi-common/util.h b/avahi-common/util.h deleted file mode 100644 index 65252e3..0000000 --- a/avahi-common/util.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef fooutilhfoo -#define fooutilhfoo - -/* $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. -***/ - -#include -#include -#include - -#include - -AVAHI_C_DECL_BEGIN - -typedef int64_t AvahiUsec; - -char *avahi_normalize_name(const char *s); /* avahi_free() the result! */ -char *avahi_get_host_name(void); /* avahi_free() the result! */ - -int avahi_timeval_compare(const struct timeval *a, const struct timeval *b); -AvahiUsec avahi_timeval_diff(const struct timeval *a, const struct timeval *b); -struct timeval* avahi_timeval_add(struct timeval *a, AvahiUsec usec); - -AvahiUsec avahi_age(const struct timeval *a); -struct timeval *avahi_elapse_time(struct timeval *tv, unsigned msec, unsigned jitter); - -int avahi_set_cloexec(int fd); -int avahi_set_nonblock(int fd); -int avahi_wait_for_write(int fd); - -int avahi_domain_equal(const char *a, const char *b); -int avahi_binary_domain_cmp(const char *a, const char *b); - -void avahi_hexdump(const void *p, size_t size); - -/* Read the first label from the textual domain name *name, unescape - * it and write it to dest, *name is changed to point to the next label*/ -char *avahi_unescape_label(const char **name, char *dest, size_t size); - -/* Escape the domain name in *src and write it to *ret_name */ -char *avahi_escape_label(const uint8_t* src, size_t src_length, char **ret_name, size_t *ret_size); - -unsigned avahi_strhash(const char *p); -unsigned avahi_domain_hash(const char *s); - -char *avahi_format_mac_address(const uint8_t* mac, size_t size); - -int avahi_valid_service_type(const char *t); -int avahi_valid_domain_name(const char *t); -int avahi_valid_service_name(const char *t); -int avahi_valid_host_name(const char *t); - -char *avahi_strdown(char *s); -char *avahi_strup(char *s); - -AVAHI_C_DECL_END - -#endif diff --git a/avahi-core/Makefile.am b/avahi-core/Makefile.am index 2e436a6..e15f295 100644 --- a/avahi-core/Makefile.am +++ b/avahi-core/Makefile.am @@ -46,7 +46,8 @@ noinst_PROGRAMS = \ conformance-test \ avahi-reflector \ dns-test \ - timeeventq-test + timeeventq-test \ + timeval-test libavahi_core_la_SOURCES = \ timeeventq.c timeeventq.h\ @@ -72,7 +73,10 @@ libavahi_core_la_SOURCES = \ rr.c rr.h \ core.h \ log.c log.h \ - browse-dns-server.c + browse-dns-server.c \ + fdutil.h fdutil.c \ + timeval.h timeval.c \ + util.c util.h libavahi_core_la_CFLAGS = $(AM_CFLAGS) libavahi_core_la_LIBADD = $(AM_LDADD) $(COMMON_LDADD) @@ -101,6 +105,7 @@ dns_test_SOURCES = \ dns.c dns.h \ dns-test.c \ log.c log.h \ + util.c util.h \ rr.c rr.h dns_test_CFLAGS = $(AM_CFLAGS) dns_test_LDADD = $(AM_LDADD) $(COMMON_LDADD) @@ -108,10 +113,17 @@ dns_test_LDADD = $(AM_LDADD) $(COMMON_LDADD) timeeventq_test_SOURCES = \ timeeventq-test.c \ timeeventq.h timeeventq.c \ + timeval.c timeval.h \ prioq.h prioq.c timeeventq_test_CFLAGS = $(AM_CFLAGS) timeeventq_test_LDADD = $(AM_LDADD) $(COMMON_LDADD) +timeval_test_SOURCES = \ + timeval.c timeval.h \ + timeval-test.c +timeval_test_CFLAGS = $(AM_CFLAGS) +timeval_test_LDADD = $(AM_LDADD) + valgrind: avahi-test libtool --mode=execute valgrind ./avahi-test diff --git a/avahi-core/announce.c b/avahi-core/announce.c index 5d9e8cf..3787f8f 100644 --- a/avahi-core/announce.c +++ b/avahi-core/announce.c @@ -24,7 +24,7 @@ #endif #include "announce.h" -#include "util.h" +#include "timeval.h" #define AVAHI_ANNOUNCEMENT_JITTER_MSEC 250 #define AVAHI_PROBE_JITTER_MSEC 250 diff --git a/avahi-core/browse-dns-server.c b/avahi-core/browse-dns-server.c index 057f3e3..7b29ec6 100644 --- a/avahi-core/browse-dns-server.c +++ b/avahi-core/browse-dns-server.c @@ -25,8 +25,8 @@ #include +#include #include "browse.h" -#include "util.h" #include "log.h" #include "rr.h" diff --git a/avahi-core/browse-domain.c b/avahi-core/browse-domain.c index de3cb1b..71bc67f 100644 --- a/avahi-core/browse-domain.c +++ b/avahi-core/browse-domain.c @@ -23,8 +23,8 @@ #include #endif +#include #include "browse.h" -#include "util.h" struct AvahiDomainBrowser { AvahiServer *server; diff --git a/avahi-core/browse-service-type.c b/avahi-core/browse-service-type.c index 3534b6f..e769e91 100644 --- a/avahi-core/browse-service-type.c +++ b/avahi-core/browse-service-type.c @@ -25,8 +25,8 @@ #include +#include #include "browse.h" -#include "util.h" #include "log.h" struct AvahiServiceTypeBrowser { diff --git a/avahi-core/browse-service.c b/avahi-core/browse-service.c index 34a2536..35fcc53 100644 --- a/avahi-core/browse-service.c +++ b/avahi-core/browse-service.c @@ -25,8 +25,8 @@ #include +#include #include "browse.h" -#include "util.h" #include "log.h" struct AvahiServiceBrowser { diff --git a/avahi-core/browse.c b/avahi-core/browse.c index 42c13da..e2d996e 100644 --- a/avahi-core/browse.c +++ b/avahi-core/browse.c @@ -24,7 +24,7 @@ #endif #include "browse.h" -#include "util.h" +#include "timeval.h" #include "log.h" struct AvahiRecordBrowser { diff --git a/avahi-core/cache.c b/avahi-core/cache.c index 2f3296f..dddd5ee 100644 --- a/avahi-core/cache.c +++ b/avahi-core/cache.c @@ -25,7 +25,7 @@ #include -#include "util.h" +#include "timeval.h" #include "cache.h" #include "log.h" diff --git a/avahi-core/conformance-test.c b/avahi-core/conformance-test.c index 13704c3..7a4c601 100644 --- a/avahi-core/conformance-test.c +++ b/avahi-core/conformance-test.c @@ -31,7 +31,6 @@ #include #include "core.h" -#include "util.h" #include "alternative.h" #include "log.h" diff --git a/avahi-core/dns-test.c b/avahi-core/dns-test.c index 6b98ef3..bf141f5 100644 --- a/avahi-core/dns-test.c +++ b/avahi-core/dns-test.c @@ -23,9 +23,10 @@ #include #endif +#include #include "dns.h" -#include "util.h" #include "log.h" +#include "util.h" int main(int argc, char *argv[]) { gchar t[256]; diff --git a/avahi-core/dns.c b/avahi-core/dns.c index 2801386..9663fc4 100644 --- a/avahi-core/dns.c +++ b/avahi-core/dns.c @@ -29,8 +29,8 @@ #include #include +#include #include "dns.h" -#include "util.h" AvahiDnsPacket* avahi_dns_packet_new(guint mtu) { AvahiDnsPacket *p; diff --git a/avahi-core/fdutil.c b/avahi-core/fdutil.c new file mode 100644 index 0000000..de7b0cf --- /dev/null +++ b/avahi-core/fdutil.c @@ -0,0 +1,73 @@ +/* $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 HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "fdutil.h" + +int avahi_set_cloexec(int fd) { + int n; + + assert(fd >= 0); + + if ((n = fcntl(fd, F_GETFD)) < 0) + return -1; + + if (n & FD_CLOEXEC) + return 0; + + return fcntl(fd, F_SETFD, n|FD_CLOEXEC); +} + +int avahi_set_nonblock(int fd) { + int n; + + assert(fd >= 0); + + if ((n = fcntl(fd, F_GETFL)) < 0) + return -1; + + if (n & O_NONBLOCK) + return 0; + + return fcntl(fd, F_SETFL, n|O_NONBLOCK); +} + +int avahi_wait_for_write(int fd) { + fd_set fds; + int r; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + + if ((r = select(fd+1, NULL, &fds, NULL, NULL)) < 0) + return -1; + + assert(r > 0); + + return 0; +} diff --git a/avahi-core/fdutil.h b/avahi-core/fdutil.h new file mode 100644 index 0000000..047b9bb --- /dev/null +++ b/avahi-core/fdutil.h @@ -0,0 +1,35 @@ +#ifndef foofdutilhfoo +#define foofdutilhfoo + +/* $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. +***/ + +#include + +AVAHI_C_DECL_BEGIN + +int avahi_set_cloexec(int fd); +int avahi_set_nonblock(int fd); +int avahi_wait_for_write(int fd); + +AVAHI_C_DECL_END + +#endif diff --git a/avahi-core/probe-sched.c b/avahi-core/probe-sched.c index ad23234..d7f9ca0 100644 --- a/avahi-core/probe-sched.c +++ b/avahi-core/probe-sched.c @@ -23,8 +23,10 @@ #include #endif +#include + #include "probe-sched.h" -#include "util.h" +#include "timeval.h" #include "log.h" #define AVAHI_PROBE_HISTORY_MSEC 150 diff --git a/avahi-core/query-sched.c b/avahi-core/query-sched.c index 129b15e..6e9234f 100644 --- a/avahi-core/query-sched.c +++ b/avahi-core/query-sched.c @@ -24,7 +24,7 @@ #endif #include "query-sched.h" -#include "util.h" +#include "timeval.h" #define AVAHI_QUERY_HISTORY_MSEC 100 #define AVAHI_QUERY_DEFER_MSEC 100 diff --git a/avahi-core/resolve-address.c b/avahi-core/resolve-address.c index c386875..fa50c39 100644 --- a/avahi-core/resolve-address.c +++ b/avahi-core/resolve-address.c @@ -24,7 +24,7 @@ #endif #include "browse.h" -#include "util.h" +#include "timeval.h" struct AvahiAddressResolver { AvahiServer *server; diff --git a/avahi-core/resolve-host-name.c b/avahi-core/resolve-host-name.c index c01c1a4..f50ddb4 100644 --- a/avahi-core/resolve-host-name.c +++ b/avahi-core/resolve-host-name.c @@ -23,8 +23,9 @@ #include #endif +#include +#include "timeval.h" #include "browse.h" -#include "util.h" struct AvahiHostNameResolver { AvahiServer *server; diff --git a/avahi-core/resolve-service.c b/avahi-core/resolve-service.c index 135543f..bf4f7b9 100644 --- a/avahi-core/resolve-service.c +++ b/avahi-core/resolve-service.c @@ -25,8 +25,9 @@ #include +#include #include "browse.h" -#include "util.h" +#include "timeval.h" struct AvahiServiceResolver { AvahiServer *server; diff --git a/avahi-core/response-sched.c b/avahi-core/response-sched.c index e1024a6..6027287 100644 --- a/avahi-core/response-sched.c +++ b/avahi-core/response-sched.c @@ -24,7 +24,7 @@ #endif #include "response-sched.h" -#include "util.h" +#include "timeval.h" #include "log.h" #define AVAHI_RESPONSE_HISTORY_MSEC 500 diff --git a/avahi-core/rr.c b/avahi-core/rr.c index 1a30146..4ec3c11 100644 --- a/avahi-core/rr.c +++ b/avahi-core/rr.c @@ -29,7 +29,7 @@ #include #include -#include "util.h" +#include #include "rr.h" AvahiKey *avahi_key_new(const gchar *name, guint16 class, guint16 type) { diff --git a/avahi-core/server.c b/avahi-core/server.c index 2bbc1f0..d913738 100644 --- a/avahi-core/server.c +++ b/avahi-core/server.c @@ -31,8 +31,10 @@ #include #include +#include + #include "server.h" -#include "util.h" +#include "timeval.h" #include "iface.h" #include "socket.h" #include "browse.h" diff --git a/avahi-core/socket.c b/avahi-core/socket.c index 842d09a..fc312d5 100644 --- a/avahi-core/socket.c +++ b/avahi-core/socket.c @@ -37,7 +37,7 @@ #include #include "dns.h" -#include "util.h" +#include "fdutil.h" #include "socket.h" #include "log.h" diff --git a/avahi-core/timeeventq-test.c b/avahi-core/timeeventq-test.c index 91eceb6..6ac55b8 100644 --- a/avahi-core/timeeventq-test.c +++ b/avahi-core/timeeventq-test.c @@ -25,8 +25,8 @@ #include -#include "util.h" #include "timeeventq.h" +#include "timeval.h" static AvahiTimeEventQueue *q = NULL; diff --git a/avahi-core/timeeventq.c b/avahi-core/timeeventq.c index fbdb6d5..d466cd4 100644 --- a/avahi-core/timeeventq.c +++ b/avahi-core/timeeventq.c @@ -24,7 +24,7 @@ #endif #include "timeeventq.h" -#include "util.h" +#include "timeval.h" static gint compare(gconstpointer _a, gconstpointer _b) { const AvahiTimeEvent *a = _a, *b = _b; diff --git a/avahi-core/timeval-test.c b/avahi-core/timeval-test.c new file mode 100644 index 0000000..7dedf41 --- /dev/null +++ b/avahi-core/timeval-test.c @@ -0,0 +1,41 @@ +/* $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 HAVE_CONFIG_H +#include +#endif + +#include +#include "timeval.h" + +int main(int argc, char *argv[]) { + + struct timeval a = { 5, 5 }, b; + + b = a; + + printf("%li.%li\n", a.tv_sec, a.tv_usec); + avahi_timeval_add(&a, -50); + + printf("%li.%li\n", a.tv_sec, a.tv_usec); + + printf("%lli\n", avahi_timeval_diff(&a, &b)); +} diff --git a/avahi-core/timeval.c b/avahi-core/timeval.c new file mode 100644 index 0000000..e5732cd --- /dev/null +++ b/avahi-core/timeval.c @@ -0,0 +1,101 @@ +/* $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 HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "timeval.h" + +int avahi_timeval_compare(const struct timeval *a, const struct timeval *b) { + assert(a); + assert(b); + + if (a->tv_sec < b->tv_sec) + return -1; + + if (a->tv_sec > b->tv_sec) + return 1; + + if (a->tv_usec < b->tv_usec) + return -1; + + if (a->tv_usec > b->tv_usec) + return 1; + + return 0; +} + +AvahiUsec avahi_timeval_diff(const struct timeval *a, const struct timeval *b) { + assert(a); + assert(b); + + if (avahi_timeval_compare(a, b) < 0) + return - avahi_timeval_diff(b, a); + + return ((AvahiUsec) a->tv_sec - b->tv_sec)*1000000 + a->tv_usec - b->tv_usec; +} + +struct timeval* avahi_timeval_add(struct timeval *a, AvahiUsec usec) { + AvahiUsec u; + assert(a); + + u = usec + a->tv_usec; + + if (u < 0) { + a->tv_usec = (long) (1000000 + (u % 1000000)); + a->tv_sec += (long) (-1 + (u / 1000000)); + } else { + a->tv_usec = (long) (u % 1000000); + a->tv_sec += (long) (u / 1000000); + } + + return a; +} + +AvahiUsec avahi_age(const struct timeval *a) { + struct timeval now; + + assert(a); + + gettimeofday(&now, NULL); + + return avahi_timeval_diff(&now, a); +} + + +struct timeval *avahi_elapse_time(struct timeval *tv, unsigned msec, unsigned jitter) { + assert(tv); + + gettimeofday(tv, NULL); + + if (msec) + avahi_timeval_add(tv, (AvahiUsec) msec*1000); + + if (jitter) + avahi_timeval_add(tv, (AvahiUsec) (jitter*1000.0*rand()/(RAND_MAX+1.0))); + + return tv; +} + diff --git a/avahi-core/timeval.h b/avahi-core/timeval.h new file mode 100644 index 0000000..c046a19 --- /dev/null +++ b/avahi-core/timeval.h @@ -0,0 +1,43 @@ +#ifndef footimevalhfoo +#define footimevalhfoo + +/* $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. +***/ + +#include +#include + +#include + +AVAHI_C_DECL_BEGIN + +typedef int64_t AvahiUsec; + +int avahi_timeval_compare(const struct timeval *a, const struct timeval *b); +AvahiUsec avahi_timeval_diff(const struct timeval *a, const struct timeval *b); +struct timeval* avahi_timeval_add(struct timeval *a, AvahiUsec usec); + +AvahiUsec avahi_age(const struct timeval *a); +struct timeval *avahi_elapse_time(struct timeval *tv, unsigned msec, unsigned jitter); + +AVAHI_C_DECL_END + +#endif diff --git a/avahi-core/util.c b/avahi-core/util.c new file mode 100644 index 0000000..514f0d9 --- /dev/null +++ b/avahi-core/util.c @@ -0,0 +1,93 @@ +/* $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 HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include + +#include "util.h" + +void avahi_hexdump(const void* p, size_t size) { + const uint8_t *c = p; + assert(p); + + printf("Dumping %u bytes from %p:\n", size, p); + + while (size > 0) { + unsigned i; + + for (i = 0; i < 16; i++) { + if (i < size) + printf("%02x ", c[i]); + else + printf(" "); + } + + for (i = 0; i < 16; i++) { + if (i < size) + printf("%c", c[i] >= 32 && c[i] < 127 ? c[i] : '.'); + else + printf(" "); + } + + printf("\n"); + + c += 16; + + if (size <= 16) + break; + + size -= 16; + } +} + + +char *avahi_format_mac_address(const uint8_t* mac, size_t size) { + char *r, *t; + unsigned i; + static const char hex[] = "0123456789abcdef"; + + t = r = g_new(char, size > 0 ? size*3 : 1); + + if (size <= 0) { + *r = 0; + return r; + } + + for (i = 0; i < size; i++) { + *(t++) = hex[*mac >> 4]; + *(t++) = hex[*mac & 0xF]; + *(t++) = ':'; + + mac++; + } + + *(--t) = 0; + return r; +} + diff --git a/avahi-core/util.h b/avahi-core/util.h new file mode 100644 index 0000000..ec124bc --- /dev/null +++ b/avahi-core/util.h @@ -0,0 +1,37 @@ +#ifndef fooutilhfoo +#define fooutilhfoo + +/* $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. +***/ + +#include + +#include + +AVAHI_C_DECL_BEGIN + +void avahi_hexdump(const void *p, size_t size); + +char *avahi_format_mac_address(const uint8_t* mac, size_t size); + +AVAHI_C_DECL_END + +#endif diff --git a/avahi-daemon/dbus-protocol.c b/avahi-daemon/dbus-protocol.c index e4f7bfd..41cef18 100644 --- a/avahi-daemon/dbus-protocol.c +++ b/avahi-daemon/dbus-protocol.c @@ -599,8 +599,6 @@ static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, gint32 interface, protocol; gchar *type, *name, *domain, *host; guint16 port; - gchar **txt = NULL; - gint txt_len; AvahiStringList *strlst; DBusMessageIter iter, sub; int j; diff --git a/avahi-dnsconfd/main.c b/avahi-dnsconfd/main.c index 957c91e..90cd55c 100644 --- a/avahi-dnsconfd/main.c +++ b/avahi-dnsconfd/main.c @@ -39,7 +39,6 @@ #include -#include #include #include