From e88161aec1eeb771b5940163a93349edfdd937e1 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Wed, 11 Feb 2009 17:02:34 +0000 Subject: [PATCH] Thu Jan 15 08:40:56 CST 2009 Pekka Pessi * s2check: added git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@11827 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- libs/sofia-sip/configure.ac | 1 + libs/sofia-sip/s2check/Makefile.am | 37 +++++ libs/sofia-sip/s2check/s2_localinfo.c | 205 ++++++++++++++++++++++++++ libs/sofia-sip/s2check/s2check.h | 50 +++++++ libs/sofia-sip/s2check/s2tcase.c | 104 +++++++++++++ 5 files changed, 397 insertions(+) create mode 100644 libs/sofia-sip/s2check/Makefile.am create mode 100644 libs/sofia-sip/s2check/s2_localinfo.c create mode 100644 libs/sofia-sip/s2check/s2check.h create mode 100644 libs/sofia-sip/s2check/s2tcase.c diff --git a/libs/sofia-sip/configure.ac b/libs/sofia-sip/configure.ac index b02060c1e4..9e63c60213 100644 --- a/libs/sofia-sip/configure.ac +++ b/libs/sofia-sip/configure.ac @@ -337,6 +337,7 @@ libsofia-sip-ua/tport/Makefile libsofia-sip-ua/url/Doxyfile libsofia-sip-ua/url/Makefile libsofia-sip-ua/features/sofia-sip/sofia_features.h +s2check/Makefile libsofia-sip-ua-glib/Makefile libsofia-sip-ua-glib/su-glib/Makefile libsofia-sip-ua-glib/su-glib/Doxyfile diff --git a/libs/sofia-sip/s2check/Makefile.am b/libs/sofia-sip/s2check/Makefile.am new file mode 100644 index 0000000000..15ccc01d7c --- /dev/null +++ b/libs/sofia-sip/s2check/Makefile.am @@ -0,0 +1,37 @@ +# +# Makefile.am for Sofia-SIP module and unit testing +# +# Copyright (C) 2009 Nokia Corporation +# Contact: Pekka Pessi +# Licensed under LGPL. See file COPYING. + +# ---------------------------------------------------------------------- +# Header paths + +INCLUDES = $(INTERNAL_INCLUDES) + +# ---------------------------------------------------------------------- +# Build targets + +noinst_LIBRARIES = libs2.a + +# ---------------------------------------------------------------------- +# Rules for building the targets + +libs2_a_SOURCES = s2check.h s2tcase.c \ + s2_localinfo.h s2_localinfo.c + +# ---------------------------------------------------------------------- +# Install and distribution rules + +EXTRA_DIST = + +# ---------------------------------------------------------------------- +# Tests + +TESTS = + +# ---------------------------------------------------------------------- +# Sofia specific rules + +include $(top_srcdir)/rules/sofia.am diff --git a/libs/sofia-sip/s2check/s2_localinfo.c b/libs/sofia-sip/s2check/s2_localinfo.c new file mode 100644 index 0000000000..5c822753d2 --- /dev/null +++ b/libs/sofia-sip/s2check/s2_localinfo.c @@ -0,0 +1,205 @@ +/* + * This file is part of the Sofia-SIP package + * + * Copyright (C) 2009 Nokia Corporation. + * + * Contact: Pekka Pessi + * + * This library 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. + * + * This library 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/**@CFILE s2_localinfo.c + * + * @brief s2_localinfo() stub returning well-known addresses for testing. + * + * @author Pekka Pessi + */ + +#include "config.h" + +#include +#include +#include + +#include +#include + +#define SU_LOCALINFO_TEST 1 + +#define su_getlocalinfo s2_getlocalinfo +#define su_freelocalinfo s2_freelocalinfo +#define su_gli_strerror s2_gli_strerror +#define su_copylocalinfo s2_copylocalinfo +#define su_sockaddr_scope s2_sockaddr_scope +#define su_getlocalip s2_getlocalip + +#include "su_localinfo.c" + +static char const *default_ifaces[] = { + "lo0\0" "127.0.0.1\0" "::1\0", + NULL +}; + +static char const **ifaces = default_ifaces; + +void s2_localinfo_ifaces(char const **replace_ifaces) +{ + ifaces = replace_ifaces; +} + +int +s2_getlocalinfo(su_localinfo_t const *hints, + su_localinfo_t **return_localinfo) +{ + int error = 0, ip4 = 0, ip6 = 0, i; + su_localinfo_t *result = NULL, **rr = &result; + su_localinfo_t hh[1] = {{ 0 }}; + + assert(return_localinfo); + + *return_localinfo = NULL; + + if (hints) { + /* Copy hints so that it can be modified */ + *hh = *hints; + if (hh->li_canonname) + hh->li_flags |= LI_CANONNAME; + } + + hints = hh; + + switch (hh->li_family) { +#if SU_HAVE_IN6 + case AF_INET6: + if (hh->li_flags & LI_V4MAPPED) + ip6 = ip4 = 1, hh->li_family = 0; + else + ip6 = 1; + break; +#endif + + case AF_INET: + ip4 = 1; + break; + + case 0: + ip6 = ip4 = 1; + break; + + default: + return -1; + } + + for (i = 0; ifaces[i]; i++) { + char const *iface = ifaces[i], *address = iface; + su_sockaddr_t su[1]; + + for (;(address += strlen(address) + 1)[0];) { + su_localinfo_t *li = NULL; + int scope = 0; + + memset(su, 0, sizeof su); + + if (0) + ; +#if SU_HAVE_IN6 + else if (ip4 && + (hints->li_flags & LI_V4MAPPED) != 0 && + host_is_ip4_address(address)) { + int32_t mapped; + su->su_len = (sizeof su->su_sin6); + su_inet_pton(su->su_family = AF_INET6, + address, + &mapped); + ((int32_t*)&su->su_sin6.sin6_addr)[2] = htonl(0xffff); + ((int32_t*)&su->su_sin6.sin6_addr)[3] = mapped; + scope = li_scope4(mapped); + } + else if (ip6 && host_is_ip6_address(address)) { + su->su_len = (sizeof su->su_sin6); + su_inet_pton(su->su_family = AF_INET6, + address, + &su->su_sin6.sin6_addr); + scope = li_scope6(&su->su_sin6.sin6_addr); + } +#endif + else if (ip4 && host_is_ip4_address(address)) { + su->su_len = (sizeof su->su_sin); + su_inet_pton(su->su_family = AF_INET, + address, + &su->su_sin.sin_addr); + scope = li_scope4(su->su_sin.sin_addr.s_addr); + } + else + continue; + + if (scope == 0) + continue; + if (hints->li_scope && (hints->li_scope & scope) == 0) + continue; + if (hints->li_index && hints->li_index != i + 1) + continue; + if (hints->li_ifname && strcmp(hints->li_ifname, iface) != 0) + continue; + if (hints->li_family && hints->li_family != su->su_family) + continue; + if (hints->li_canonname && !su_casematch(address, hints->li_canonname)) + continue; + + li = calloc(1, (sizeof *li) + (sizeof *su) + strlen(iface) + 1); + li->li_family = su->su_family; + li->li_scope = scope; + li->li_index = i + 1; + li->li_addrlen = su_sockaddr_size(su); + li->li_addr = memcpy((li + 1), su, (sizeof *su)); + if (hints->li_flags & LI_IFNAME) + li->li_ifname = strcpy((char *)li->li_addr + li->li_addrlen, iface); + + if ((hints->li_flags & LI_CANONNAME) || hints->li_canonname) { + li->li_flags |= LI_NUMERIC; + li->li_canonname = su_strdup(NULL, address); + } + +#define LI_MAPPED(li) \ + ((li)->li_family == AF_INET6 && \ + (IN6_IS_ADDR_V4MAPPED(&(li)->li_addr->su_sin6.sin6_addr) || \ + IN6_IS_ADDR_V4COMPAT(&(li)->li_addr->su_sin6.sin6_addr))) + + /* Insert according to scope, mappedness and family */ + for (rr = &result; *rr; rr = &(*rr)->li_next) { + if ((*rr)->li_scope < li->li_scope) + break; +#if SU_HAVE_IN6 + if (LI_MAPPED(*rr) > LI_MAPPED(li)) + break; +#endif + if ((*rr)->li_family < li->li_family) + break; + } + li->li_next = *rr; + *rr = li; + } + } + + *return_localinfo = result; + + if (result == NULL) + error = ELI_NOADDRESS; + + return error; +} + diff --git a/libs/sofia-sip/s2check/s2check.h b/libs/sofia-sip/s2check/s2check.h new file mode 100644 index 0000000000..b24addd031 --- /dev/null +++ b/libs/sofia-sip/s2check/s2check.h @@ -0,0 +1,50 @@ +/* + * This file is part of the Sofia-SIP package + * + * Copyright (C) 2009 Nokia Corporation. + * + * Contact: Pekka Pessi + * + * This library 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. + * + * This library 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef S2CHECK_H +/** Defined when has been included. */ +#define S2CHECK_H + +/**@internal @file s2check.h + * + * @brief Check-based testing + * + * @author Pekka Pessi + */ + +#include + +SOFIA_BEGIN_DECLS + +#undef tcase_add_test +/* Redirect tcase_add_test() to our function */ +#define tcase_add_test(tc, tf) s2_tcase_add_test(tc, tf, "" #tf "") + +void s2_tcase_add_test(TCase *, TFun, char const *name); + + + +SOFIA_END_DECLS + +#endif /* S2CHECK_H */ diff --git a/libs/sofia-sip/s2check/s2tcase.c b/libs/sofia-sip/s2check/s2tcase.c new file mode 100644 index 0000000000..a5ba648ca1 --- /dev/null +++ b/libs/sofia-sip/s2check/s2tcase.c @@ -0,0 +1,104 @@ +/* + * This file is part of the Sofia-SIP package + * + * Copyright (C) 2009 Nokia Corporation. + * + * Contact: Pekka Pessi + * + * This library 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. + * + * This library 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include "config.h" + +#if HAVE_CHECK + +#if HAVE_FNMATCH_H +#include +#endif + +static char const * const default_patterns[] = { "*", NULL }; +static char const * const *test_patterns = default_patterns; + +#undef tcase_add_test + +/** tcase_add_test() replacement. + * + * A special version of tcase_add_test() that inserts test function into + * tcase only if its name matches given pattern. + */ +void s2_tcase_add_test(TCase *tc, TFun tf, char const *name) +{ + char const * const *patterns; + +#if HAVE_FNMATCH_H + for (patterns = test_patterns; *patterns; patterns++) { + if (!fnmatch(*patterns, name, 0)) { + if (strcmp(*patterns, "*")) { + printf("%s: running\n", name); + } + tcase_add_test(tc, tf, name, 0, 0, 1); + return; + } + } +#else + for (patterns = test_patterns; *patterns; patterns++) { + if (!strcmp(*patterns, name) || !strcmp(*patterns, "*")) { + if (strcmp(*patterns, "*")) { + printf("%s: running\n", name); + } + tcase_add_test(tc, tf, name, 0, 0, 1); + return; + } + } +#endif +} + +/** Select tests based on pattern. + * + * Allow easy selection of test cases to run. Pattern can be a shell glob, + * or consists of multiple comma-separated patterns. + */ +void s2_select_tests(char const *pattern) +{ + size_t i; + char *cases, *s, **patterns; + + if (!pattern) + return; + + cases = strdup(pattern); + + /* Count commas */ + for (i = 2, s = cases; (s = strchr(s, ',')); s++) + i++; + + patterns = calloc(i, sizeof *patterns); + + /* Split by commas */ + for (i = 0, s = cases;; i++) { + patterns[i] = s; + if (s == NULL) + break; + s = strchr(s, ','); + if (s) + *s++ = '\0'; + } + + test_patterns = (char const * const *)patterns; +} + +#endif /* HAVE_CHECK */