diff --git a/.gitignore b/.gitignore index 9a3e486..27e6228 100644 --- a/.gitignore +++ b/.gitignore @@ -34,8 +34,6 @@ Doxyfile .*.sw? -src/libdebug/libdebug.a +src/liblogging/liblogging.a src/liboptions/liboptions.a -src/libosmocc/libosmocc.a -src/libtimer/libtimer.a src/sip/osmo-cc-sip-endpoint diff --git a/configure.ac b/configure.ac index 06106ef..387ad82 100644 --- a/configure.ac +++ b/configure.ac @@ -85,11 +85,12 @@ PKG_CHECK_MODULES(SOFIA, sofia-sip-ua >= 1.12) AC_CHECK_LIB([m], [main]) AC_CHECK_LIB([pthread], [main]) +PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.9.0) +PKG_CHECK_MODULES(LIBOSMOCC, libosmocc >= 1.0.0) + AC_OUTPUT( src/liboptions/Makefile - src/libdebug/Makefile - src/libtimer/Makefile - src/libosmocc/Makefile + src/liblogging/Makefile src/sip/Makefile src/Makefile Makefile) diff --git a/src/Makefile.am b/src/Makefile.am index 6c73336..57ca36e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,8 +2,6 @@ AUTOMAKE_OPTIONS = foreign SUBDIRS = \ liboptions \ - libdebug \ - libtimer \ - libosmocc \ + liblogging \ sip diff --git a/src/libdebug/Makefile.am b/src/libdebug/Makefile.am deleted file mode 100644 index 210a097..0000000 --- a/src/libdebug/Makefile.am +++ /dev/null @@ -1,7 +0,0 @@ -AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) - -noinst_LIBRARIES = libdebug.a - -libdebug_a_SOURCES = \ - debug.c - diff --git a/src/libdebug/debug.c b/src/libdebug/debug.c deleted file mode 100644 index f7b91e0..0000000 --- a/src/libdebug/debug.c +++ /dev/null @@ -1,330 +0,0 @@ -/* Simple debug functions for level and category filtering - * - * (C) 2016 by Andreas Eversberg - * All Rights Reserved - * - * 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 3 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, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "debug.h" - -const char *debug_level[] = { - "debug ", - "info ", - "notice ", - "error ", - NULL, -}; - -struct debug_cat { - const char *name; - const char *color; -} debug_cat[] = { - { "options", "\033[0;33m" }, - { "sender", "\033[1;33m" }, - { "sound", "\033[0;35m" }, - { "dsp", "\033[0;31m" }, - { "anetz", "\033[1;34m" }, - { "bnetz", "\033[1;34m" }, - { "cnetz", "\033[1;34m" }, - { "nmt", "\033[1;34m" }, - { "amps", "\033[1;34m" }, - { "r2000", "\033[1;34m" }, - { "imts", "\033[1;34m" }, - { "mpt1327", "\033[1;34m" }, - { "jollycom", "\033[1;34m" }, - { "eurosignal", "\033[1;34m" }, - { "pocsag", "\033[1;34m" }, - { "golay", "\033[1;34m" }, - { "5-ton-folge", "\033[1;34m" }, - { "frame", "\033[0;36m" }, - { "call", "\033[0;37m" }, - { "cc", "\033[1;32m" }, - { "database", "\033[0;33m" }, - { "transaction", "\033[0;32m" }, - { "dms", "\033[0;33m" }, - { "sms", "\033[1;37m" }, - { "sdr", "\033[1;31m" }, - { "uhd", "\033[1;35m" }, - { "soapy", "\033[1;35m" }, - { "wave", "\033[1;33m" }, - { "radio", "\033[1;34m" }, - { "am791x", "\033[0;31m" }, - { "uart", "\033[0;32m" }, - { "device", "\033[0;33m" }, - { "datenklo", "\033[1;34m" }, - { "zeit", "\033[1;34m" }, - { "sim layer 1", "\033[0;31m" }, - { "sim layer 2", "\033[0;33m" }, - { "sim ICL layer", "\033[0;36m" }, - { "sim layer 7", "\033[0;37m" }, - { "mtp layer 2", "\033[1;33m" }, - { "mtp layer 3", "\033[1;36m" }, - { "MuP", "\033[1;37m" }, - { "router", "\033[1;35m" }, - { "stderr", "\033[1;37m" }, - { "ss5", "\033[1;34m" }, - { "isdn", "\033[1;35m" }, - { "misdn", "\033[0;34m" }, - { "dss1", "\033[1;34m" }, - { "sip", "\033[1;35m" }, - { "telephone", "\033[1;34m" }, - { "uk0", "\033[1;34m" }, - { "ph", "\033[0;33m" }, - { "dcf77", "\033[1;34m" }, - { "jitter", "\033[0;36m" }, - { NULL, NULL } -}; - -int debuglevel = DEBUG_INFO; -int debug_date = 0; -uint64_t debug_mask[2] = { ~0, ~0 }; -extern int num_kanal; - -void (*clear_console_text)(void) = NULL; -void (*print_console_text)(void) = NULL; - -int debug_limit_scroll = 0; - -static int lock_initialized = 0; -static pthread_mutex_t debug_mutex; - -void lock_debug(void) -{ - int rc; - - if (!lock_initialized) { - rc = pthread_mutex_init(&debug_mutex, NULL); - if (rc == 0) - lock_initialized = 1; - } - if (lock_initialized) - pthread_mutex_lock(&debug_mutex); -} - -void unlock_debug(void) -{ - if (lock_initialized) - pthread_mutex_unlock(&debug_mutex); -} - -void get_win_size(int *w, int *h) -{ - struct winsize win; - int rc; - - rc = ioctl(0, TIOCGWINSZ, &win); - if (rc) { - *w = 80; - *h = 25; - return; - } - - *h = win.ws_row; - *w = win.ws_col; -} - -void _printdebug(const char *file, const char __attribute__((unused)) *function, int line, int cat, int level, const char *kanal, const char *fmt, ...) -{ - char buffer[4096], *b = buffer; - int s = sizeof(buffer) - 1; - const char *p; - va_list args; - int w, h = 0; // make GCC happy - - if (debuglevel > level) - return; - - if (!(debug_mask[cat >> 6] & ((uint64_t)1 << (cat & 63)))) - return; - - lock_debug(); - - buffer[sizeof(buffer) - 1] = '\0'; - - /* if kanal is used, prefix the channel number */ - if (num_kanal > 1 && kanal) { - sprintf(buffer, "(chan %s) ", kanal); - b = strchr(buffer, '\0'); - s -= strlen(buffer); - } - - va_start(args, fmt); - vsnprintf(b, s, fmt, args); - va_end(args); - - while ((p = strchr(file, '/'))) - file = p + 1; - if (clear_console_text) - clear_console_text(); - if (debug_limit_scroll) { - get_win_size(&w, &h); - printf("\0337\033[%d;%dr\0338", debug_limit_scroll + 1, h); - } - if (debug_date) { - struct timeval tv; - struct tm *tm; - - gettimeofday(&tv, NULL); - tm = localtime(&tv.tv_sec); - - printf("%04d-%02d-%02d %02d:%02d:%02d.%03d ", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(tv.tv_usec / 10000.0)); - } - printf("%s%s %4d %s-%s: %s\033[0;39m", debug_cat[cat].color, file, line, debug_cat[cat].name, debug_level[level], buffer); - if (debug_limit_scroll) - printf("\0337\033[%d;%dr\0338", 1, h); - if (print_console_text) - print_console_text(); - fflush(stdout); - - unlock_debug(); -} - -const char *debug_amplitude(double level) -{ - static char text[42]; - - strcpy(text, " : "); - if (level > 1.0) - level = 1.0; - if (level < -1.0) - level = -1.0; - text[20 + (int)(level * 20)] = '*'; - - return text; -} - -#define level2db(level) (20 * log10(level)) - -const char *debug_db(double level_db) -{ - static char text[128]; - int l; - - strcpy(text, ": . : . : . : . : . : . : . : . | . : . : . : . : . : . : . : . :"); - if (level_db <= 0.0) - return text; - l = (int)round(level2db(level_db)); - if (l > 48) - return text; - if (l < -48) - return text; - text[l + 48] = '*'; - - return text; -} - -void debug_print_help(void) -{ - printf(" -v --verbose | ,[,[,...]] | list\n"); - printf(" Use 'list' to get a list of all levels and categories\n"); - printf(" Verbose level: digit of debug level (default = '%d')\n", debuglevel); - printf(" Verbose level+category: level digit followed by one or more categories\n"); - printf(" -> If no category is specified, all categories are selected\n"); - printf(" -v --verbose date\n"); - printf(" Show date with debug output\n"); -} - -void debug_list_cat(void) -{ - int i; - - printf("Give number of debug level:\n"); - for (i = 0; debug_level[i]; i++) - printf(" %d = %s\n", i, debug_level[i]); - printf("\n"); - - printf("Give name(s) of debug category:\n"); - for (i = 0; debug_cat[i].name; i++) - printf(" %s%s\033[0;39m\n", debug_cat[i].color, debug_cat[i].name); - printf("\n"); -} - -int parse_debug_opt(const char *optarg) -{ - int i, max_level = 0; - char *dup, *dstring, *p; - - if (!strcasecmp(optarg, "date")) { - debug_date = 1; - return 0; - } - - for (i = 0; debug_level[i]; i++) - max_level = i; - - dup = dstring = strdup(optarg); - p = strsep(&dstring, ","); - for (i = 0; i < p[i]; i++) { - if (p[i] < '0' || p[i] > '9') { - fprintf(stderr, "Only digits are allowed for debug level!\n"); - free(dup); - return -EINVAL; - } - } - debuglevel = atoi(p); - if (debuglevel > max_level) { - fprintf(stderr, "Debug level too high, use 'list' to show available levels!\n"); - free(dup); - return -EINVAL; - } - if (dstring) - memset(debug_mask, 0, sizeof(debug_mask)); - while((p = strsep(&dstring, ","))) { - for (i = 0; debug_cat[i].name; i++) { - if (!strcasecmp(p, debug_cat[i].name)) - break; - } - if (!debug_cat[i].name) { - fprintf(stderr, "Given debug category '%s' unknown, use 'list' to show available categories!\n", p); - free(dup); - return -EINVAL; - } - debug_mask[i >> 6] |= ((uint64_t)1 << (i & 63)); - } - - free(dup); - return 0; -} - -const char *debug_hex(const uint8_t *data, int len) -{ - static char *text = NULL; - char *p; - int i; - - if (text) - free(text); - p = text = calloc(1, len * 3 + 1); - for (i = 0; i < len; i++) { - sprintf(p, "%02x ", *data++); - p += 3; - } - if (text[0]) - p[-1] = '\0'; - - return text; -} - diff --git a/src/libdebug/debug.h b/src/libdebug/debug.h deleted file mode 100644 index 5942651..0000000 --- a/src/libdebug/debug.h +++ /dev/null @@ -1,86 +0,0 @@ - -#define DEBUG_DEBUG 0 /* debug info, not for normal use */ -#define DEBUG_INFO 1 /* all info about process */ -#define DEBUG_NOTICE 2 /* something unexpected happens */ -#define DEBUG_ERROR 3 /* there is an error with this software */ - -#define DOPTIONS 0 -#define DSENDER 1 -#define DSOUND 2 -#define DDSP 3 -#define DANETZ 4 -#define DBNETZ 5 -#define DCNETZ 6 -#define DNMT 7 -#define DAMPS 8 -#define DR2000 9 -#define DIMTS 10 -#define DMPT1327 11 -#define DJOLLY 12 -#define DEURO 13 -#define DPOCSAG 14 -#define DGOLAY 15 -#define DFUENF 16 -#define DFRAME 17 -#define DCALL 18 -#define DCC 19 -#define DDB 20 -#define DTRANS 21 -#define DDMS 22 -#define DSMS 23 -#define DSDR 24 -#define DUHD 25 -#define DSOAPY 26 -#define DWAVE 27 -#define DRADIO 28 -#define DAM791X 29 -#define DUART 30 -#define DDEVICE 31 -#define DDATENKLO 32 -#define DZEIT 33 -#define DSIM1 34 -#define DSIM2 35 -#define DSIMI 36 -#define DSIM7 37 -#define DMTP2 38 -#define DMTP3 39 -#define DMUP 40 -#define DROUTER 41 -#define DSTDERR 42 -#define DSS5 43 -#define DISDN 44 -#define DMISDN 45 -#define DDSS1 46 -#define DSIP 47 -#define DTEL 48 -#define DUK0 49 -#define DPH 50 -#define DDCF77 51 -#define DJITTER 52 -//NOTE: increment mask array, if 127 is exceeded - -void lock_debug(void); -void unlock_debug(void); - -void get_win_size(int *w, int *h); - -#define PDEBUG(cat, level, fmt, arg...) _printdebug(__FILE__, __FUNCTION__, __LINE__, cat, level, NULL, fmt, ## arg) -#define PDEBUG_CHAN(cat, level, fmt, arg...) _printdebug(__FILE__, __FUNCTION__, __LINE__, cat, level, CHAN, fmt, ## arg) -void _printdebug(const char *file, const char *function, int line, int cat, int level, const char *chan_str, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 7, 8))); - -const char *debug_amplitude(double level); -const char *debug_db(double level_db); - -void debug_print_help(void); -void debug_list_cat(void); -int parse_debug_opt(const char *opt); - -extern int debuglevel; - -extern void (*clear_console_text)(void); -extern void (*print_console_text)(void); - -extern int debug_limit_scroll; - -const char *debug_hex(const uint8_t *data, int len); - diff --git a/src/liblogging/Makefile.am b/src/liblogging/Makefile.am new file mode 100644 index 0000000..a1b1e18 --- /dev/null +++ b/src/liblogging/Makefile.am @@ -0,0 +1,8 @@ +AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) + +noinst_LIBRARIES = liblogging.a + +liblogging_a_SOURCES = \ + logging.c \ + categories.c + diff --git a/src/liblogging/categories.c b/src/liblogging/categories.c new file mode 100644 index 0000000..e23907f --- /dev/null +++ b/src/liblogging/categories.c @@ -0,0 +1,27 @@ + +#include +#include +#include "categories.h" + +/* All logging categories used by this project. */ + +struct log_info_cat log_categories[] = { + [DLCC] = { + .name = "DLCC", + .description = "libosmo-cc CC Layer", + .color = "\033[0;37m", + }, + [DOPTIONS] = { + .name = "DOPTIONS", + .description = "config options", + .color = "\033[0;33m", + }, + [DSIP] = { + .name = "DSIP", + .description = "SIP processing", + .color = "\033[1;35m", + }, +}; + +size_t log_categories_size = ARRAY_SIZE(log_categories); + diff --git a/src/liblogging/categories.h b/src/liblogging/categories.h new file mode 100644 index 0000000..7bea97b --- /dev/null +++ b/src/liblogging/categories.h @@ -0,0 +1,10 @@ + +enum { + DLCC, + DOPTIONS, + DSIP, +}; + +extern struct log_info_cat log_categories[]; +extern size_t log_categories_size; + diff --git a/src/liblogging/logging.c b/src/liblogging/logging.c new file mode 100644 index 0000000..4268c06 --- /dev/null +++ b/src/liblogging/logging.c @@ -0,0 +1,264 @@ +/* Logging (on segmented part of the window) + * + * (C) 2016 by Andreas Eversberg + * All Rights Reserved + * + * 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 3 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include "logging.h" + +int loglevel = LOGL_INFO; + +static int scroll_window_start = 0; +static int scroll_window_end = 0; +static int scroll_window_height = 0; + +void lock_logging(void) +{ + log_tgt_mutex_lock(); +} + +void unlock_logging(void) +{ + log_tgt_mutex_unlock(); +} + +void get_win_size(int *w, int *h) +{ + struct winsize win; + int rc; + + rc = ioctl(0, TIOCGWINSZ, &win); + if (rc) { + *w = 80; + *h = 25; + return; + } + + if (h) + *h = win.ws_row; + if (w) + *w = win.ws_col; +} + +void enable_limit_scroll(bool enable) +{ + /* Before the window is set, keep scrolling everything. */ + if (scroll_window_height == 0) + return; + + /* If window is too small. */ + if (scroll_window_end - scroll_window_start <= 0) + return; + + if (enable) { + printf("\0337\033[%d;%dr\0338", scroll_window_start, scroll_window_end); + } else + printf("\0337\033[%d;%dr\0338", 1, scroll_window_height); + fflush(stdout); +} + +void logging_limit_scroll_top(int lines) +{ + lock_logging(); + + get_win_size(NULL, &scroll_window_height); + scroll_window_start = lines + 1; + if (scroll_window_end == 0) + scroll_window_end = scroll_window_height; + + enable_limit_scroll(true); + + unlock_logging(); +} + +void logging_limit_scroll_bottom(int lines) +{ + int i; + + lock_logging(); + + get_win_size(NULL, &scroll_window_height); + scroll_window_end = scroll_window_height - lines; + if (scroll_window_start == 0) + scroll_window_start = 1; + + /* Make space by adding empty lines. */ + for (i = scroll_window_end; i < scroll_window_height; i++) + printf("\n"); + /* Go up by number of lines to be in window. */ + printf("\033[%dA", scroll_window_height - scroll_window_end); + /* Enable window. */ + enable_limit_scroll(true); + + unlock_logging(); +} + +const char *debug_amplitude(double level) +{ + static char text[42]; + + strcpy(text, " : "); + if (level > 1.0) + level = 1.0; + if (level < -1.0) + level = -1.0; + text[20 + (int)(level * 20)] = '*'; + + return text; +} + +#define level2db(level) (20 * log10(level)) + +const char *debug_db(double level_db) +{ + static char text[128]; + int l; + + strcpy(text, ": . : . : . : . : . : . : . : . | . : . : . : . : . : . : . : . :"); + if (level_db <= 0.0) + return text; + l = (int)round(level2db(level_db)); + if (l > 48) + return text; + if (l < -48) + return text; + text[l + 48] = '*'; + + return text; +} + +void logging_print_help(void) +{ + printf(" -v --verbose | ,[,[,...]] | list\n"); + printf(" Use 'list' to get a list of all levels and categories.\n"); + printf(" Verbose level: digit of debug level (default = '%d')\n", loglevel); + printf(" Verbose level+category: level digit followed by one or more categories\n"); + printf(" -> If no category is specified, all categories are selected\n"); + printf(" -v --verbose date\n"); + printf(" Show date with debug output\n"); +} + +static unsigned char log_levels[] = { LOGL_DEBUG, LOGL_INFO, LOGL_NOTICE, LOGL_ERROR }; +static char *log_level_names[] = { "debug", "info", "notice", "error" }; + +static void list_cat(void) +{ + int i; + + printf("Give number of debug level:\n"); + for (i = 0; i < (int)sizeof(log_levels); i++) + printf(" %d = %s\n", log_levels[i], log_level_names[i]); + printf("\n"); + + printf("Give name(s) of debug category:\n"); + for (i = 0; i < (int)log_categories_size; i++) { + if (!log_categories[i].name) + continue; + printf(" "); + if (log_categories[i].color) + printf("%s", log_categories[i].color); + if (log_categories[i].name) + printf("%s\033[0;39m = %s\n", log_categories[i].name, log_categories[i].description); + } + printf("\n"); +} + +int parse_logging_opt(const char *optarg) +{ + int i; + char *dup, *dstring, *p; + + if (!strcasecmp(optarg, "list")) { + list_cat(); + return 1; + } + + if (!strcasecmp(optarg, "date")) { + log_set_print_timestamp(osmo_stderr_target, 1); + return 0; + } + + dup = dstring = strdup(optarg); + p = strsep(&dstring, ","); + for (i = 0; i < p[i]; i++) { + if (p[i] < '0' || p[i] > '9') { + fprintf(stderr, "Only digits are allowed for debug level!\n"); + free(dup); + return -EINVAL; + } + } + loglevel = atoi(p); + for (i = 0; i < (int)sizeof(log_levels); i++) { + if (log_levels[i] == loglevel) + break; + } + if (i == (int)sizeof(log_levels)) { + fprintf(stderr, "Logging level does not exist, use '-v list' to show available levels!\n"); + free(dup); + return -EINVAL; + } + /* Set loglevel and enable all categories, if dstring is not set. Else set loglevel and disable all categories. */ + for (i = 0; i < (int)log_categories_size; i++) + log_set_category_filter(osmo_stderr_target, i, (!dstring), loglevel); + /* Enable each given category. */ + while((p = strsep(&dstring, ","))) { + for (i = 0; i < (int)log_categories_size; i++) { + if (!log_category_name(i)) + continue; + if (!strcasecmp(p, log_category_name(i))) + break; + } + if (i == (int)log_categories_size) { + fprintf(stderr, "Given logging category '%s' unknown, use '-v list' to show available categories!\n", p); + free(dup); + return -EINVAL; + } + log_set_category_filter(osmo_stderr_target, i, 1, loglevel); + } + + free(dup); + return 0; +} + +/* Call after configuation above. */ +void logging_init(void) +{ + int i; + + struct log_info log_info = { + .cat = log_categories, + .num_cat = log_categories_size, + }; + + osmo_cc_set_log_cat(DLCC); + + osmo_init_logging2(NULL, &log_info); + log_set_print_timestamp(osmo_stderr_target, 0); + log_set_print_level(osmo_stderr_target, 1); + log_set_print_category_hex(osmo_stderr_target, 0); + log_set_print_category(osmo_stderr_target, 1); + + /* Set loglevel and enable all categories. */ + for (i = 0; i < (int)log_categories_size; i++) + log_set_category_filter(osmo_stderr_target, i, 1, loglevel); +} + diff --git a/src/liblogging/logging.h b/src/liblogging/logging.h new file mode 100644 index 0000000..67f1434 --- /dev/null +++ b/src/liblogging/logging.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include "categories.h" + +extern int loglevel; + +#define LOGP_CHAN(cat, level, fmt, arg...) LOGP(cat, level, "(chan %s) " fmt, CHAN, ## arg) + +void get_win_size(int *w, int *h); +void lock_logging(void); +void unlock_logging(void); +void enable_limit_scroll(bool enable); +void logging_limit_scroll_top(int lines); +void logging_limit_scroll_bottom(int lines); +const char *debug_amplitude(double level); +const char *debug_db(double level_db); +void logging_print_help(void); +int parse_logging_opt(const char *optarg); +void logging_init(void); + diff --git a/src/liboptions/options.c b/src/liboptions/options.c index d49e698..cc19b89 100644 --- a/src/liboptions/options.c +++ b/src/liboptions/options.c @@ -23,7 +23,7 @@ #include #include #include "options.h" -#include "../libdebug/debug.h" +#include "../liblogging/logging.h" typedef struct option { struct option *next; @@ -47,7 +47,7 @@ char *options_strdup(const char *s) o = malloc(sizeof(struct options_strdup_entry) + strlen(s)); if (!o) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "No mem!\n"); + LOGP(DOPTIONS, LOGL_ERROR, "No mem!\n"); abort(); } o->next = options_strdup_list; @@ -64,19 +64,19 @@ void option_add(int short_option, const char *long_option, int parameter_count) /* check if option already exists or is not allowed */ for (option = option_head; option; option = option->next) { if (!strcmp(option->long_option, "config")) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Option '%s' is not allowed to add, please fix!\n", option->long_option); + LOGP(DOPTIONS, LOGL_ERROR, "Option '%s' is not allowed to add, please fix!\n", option->long_option); abort(); } if (option->short_option == short_option || !strcmp(option->long_option, long_option)) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Option '%s' added twice, please fix!\n", option->long_option); + LOGP(DOPTIONS, LOGL_ERROR, "Option '%s' added twice, please fix!\n", option->long_option); abort(); } } option = calloc(1, sizeof(*option)); if (!option) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "No mem!\n"); + LOGP(DOPTIONS, LOGL_ERROR, "No mem!\n"); abort(); } @@ -115,7 +115,7 @@ int options_config_file(int argc, char *argv[], const char *config_file, int (*h /* open config file */ fp = fopen(config, "r"); if (!fp) { - PDEBUG(DOPTIONS, DEBUG_INFO, "Config file '%s' seems not to exist, using command line options only.\n", config); + LOGP(DOPTIONS, LOGL_INFO, "Config file '%s' seems not to exist, using command line options only.\n", config); return 1; } @@ -201,21 +201,21 @@ int options_config_file(int argc, char *argv[], const char *config_file, int (*h /* search option */ for (option = option_head; option; option = option->next) { if (opt[0] == option->short_option && opt[1] == '\0') { - PDEBUG(DOPTIONS, DEBUG_INFO, "Config file option '%s' ('%s'), parameter%s\n", opt, option->long_option, params); + LOGP(DOPTIONS, LOGL_INFO, "Config file option '%s' ('%s'), parameter%s\n", opt, option->long_option, params); break; } if (!strcmp(opt, option->long_option)) { - PDEBUG(DOPTIONS, DEBUG_INFO, "Config file option '%s', parameter%s\n", opt, params); + LOGP(DOPTIONS, LOGL_INFO, "Config file option '%s', parameter%s\n", opt, params); break; } } if (!option) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given option '%s' in config file '%s' at line %d is not a valid option, use '-h' for help!\n", opt, config_file, line); + LOGP(DOPTIONS, LOGL_ERROR, "Given option '%s' in config file '%s' at line %d is not a valid option, use '-h' for help!\n", opt, config_file, line); rc = -EINVAL; goto done; } if (option->parameter_count != i) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given option '%s' in config file '%s' at line %d requires %d parameter(s), use '-h' for help!\n", opt, config_file, line, option->parameter_count); + LOGP(DOPTIONS, LOGL_ERROR, "Given option '%s' in config file '%s' at line %d requires %d parameter(s), use '-h' for help!\n", opt, config_file, line, option->parameter_count); return -EINVAL; } rc = handle_options(option->short_option, 0, args); @@ -242,11 +242,11 @@ int options_command_line(int argc, char *argv[], int (*handle_options)(int short /* --config */ if (!strcmp(argv[argi], "--config")) { if (argi > 1) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given command line option '%s' must be the first option specified, use '-h' for help!\n", argv[argi]); + LOGP(DOPTIONS, LOGL_ERROR, "Given command line option '%s' must be the first option specified, use '-h' for help!\n", argv[argi]); return -EINVAL; } if (argc <= 2) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given command line option '%s' requires 1 parameter, use '-h' for help!\n", argv[argi]); + LOGP(DOPTIONS, LOGL_ERROR, "Given command line option '%s' requires 1 parameter, use '-h' for help!\n", argv[argi]); return -EINVAL; } argi += 1; @@ -255,7 +255,7 @@ int options_command_line(int argc, char *argv[], int (*handle_options)(int short if (argv[argi][0] == '-') { if (argv[argi][1] != '-') { if (strlen(argv[argi]) != 2) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given command line option '%s' exceeds one character, use '-h' for help!\n", argv[argi]); + LOGP(DOPTIONS, LOGL_ERROR, "Given command line option '%s' exceeds one character, use '-h' for help!\n", argv[argi]); return -EINVAL; } /* -x */ @@ -265,9 +265,9 @@ int options_command_line(int argc, char *argv[], int (*handle_options)(int short params[0] = '\0'; for (i = 0; i < option->parameter_count; i++) sprintf(strchr(params, '\0'), " '%s'", argv[argi + 1 + i]); - PDEBUG(DOPTIONS, DEBUG_INFO, "Command line option '%s' ('--%s'), parameter%s\n", argv[argi], option->long_option, params); + LOGP(DOPTIONS, LOGL_INFO, "Command line option '%s' ('--%s'), parameter%s\n", argv[argi], option->long_option, params); } else - PDEBUG(DOPTIONS, DEBUG_INFO, "Command line option '%s' ('--%s')\n", argv[argi], option->long_option); + LOGP(DOPTIONS, LOGL_INFO, "Command line option '%s' ('--%s')\n", argv[argi], option->long_option); break; } } @@ -279,19 +279,19 @@ int options_command_line(int argc, char *argv[], int (*handle_options)(int short params[0] = '\0'; for (i = 0; i < option->parameter_count; i++) sprintf(strchr(params, '\0'), " '%s'", argv[argi + 1 + i]); - PDEBUG(DOPTIONS, DEBUG_INFO, "Command line option '%s', parameter%s\n", argv[argi], params); + LOGP(DOPTIONS, LOGL_INFO, "Command line option '%s', parameter%s\n", argv[argi], params); } else - PDEBUG(DOPTIONS, DEBUG_INFO, "Command line option '%s'\n", argv[argi]); + LOGP(DOPTIONS, LOGL_INFO, "Command line option '%s'\n", argv[argi]); break; } } } if (!option) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given command line option '%s' is not a valid option, use '-h' for help!\n", argv[argi]); + LOGP(DOPTIONS, LOGL_ERROR, "Given command line option '%s' is not a valid option, use '-h' for help!\n", argv[argi]); return -EINVAL; } if (argi + option->parameter_count >= argc) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given command line option '%s' requires %d parameter(s), use '-h' for help!\n", argv[argi], option->parameter_count); + LOGP(DOPTIONS, LOGL_ERROR, "Given command line option '%s' requires %d parameter(s), use '-h' for help!\n", argv[argi], option->parameter_count); return -EINVAL; } rc = handle_options(option->short_option, argi + 1, argv); @@ -306,7 +306,7 @@ int options_command_line(int argc, char *argv[], int (*handle_options)(int short /* no more options, so we check if there is an option after a non-option parameter */ for (i = argi; i < argc; i++) { if (argv[i][0] == '-') { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given command line option '%s' behind command line parameter '%s' not allowed! Please put all command line options before command line parameter(s).\n", argv[i], argv[argi]); + LOGP(DOPTIONS, LOGL_ERROR, "Given command line option '%s' behind command line parameter '%s' not allowed! Please put all command line options before command line parameter(s).\n", argv[i], argv[argi]); return -EINVAL; } } diff --git a/src/libosmocc/Makefile.am b/src/libosmocc/Makefile.am deleted file mode 100644 index 27c0f6c..0000000 --- a/src/libosmocc/Makefile.am +++ /dev/null @@ -1,15 +0,0 @@ -AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) - -noinst_LIBRARIES = libosmocc.a - -libosmocc_a_SOURCES = \ - message.c \ - socket.c \ - cause.c \ - screen.c \ - endpoint.c \ - session.c \ - sdp.c \ - rtp.c \ - helper.c - diff --git a/src/libosmocc/cause.c b/src/libosmocc/cause.c deleted file mode 100644 index df2b07b..0000000 --- a/src/libosmocc/cause.c +++ /dev/null @@ -1,251 +0,0 @@ -/* OSMO-CC Processing: convert causes - * - * (C) 2019 by Andreas Eversberg - * All Rights Reserved - * - * 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 3 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, see . - */ - -#include -#include -#include "message.h" -#include "cause.h" - -/* stolen from freeswitch, did some corrections */ -/* map sip responses to QSIG cause codes ala RFC4497 section 8.4.4 */ -static uint8_t status2isdn_cause(uint16_t status) -{ - switch (status) { - case 200: - return 16; //SWITCH_CAUSE_NORMAL_CLEARING; - case 401: - case 402: - case 403: - case 407: - case 603: - return 21; //SWITCH_CAUSE_CALL_REJECTED; - case 404: - case 485: - case 604: - return 1; //SWITCH_CAUSE_UNALLOCATED_NUMBER; - case 408: - case 504: - return 102; //SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE; - case 410: - return 22; //SWITCH_CAUSE_NUMBER_CHANGED; - case 413: - case 414: - case 416: - case 420: - case 421: - case 423: - case 505: - case 513: - return 127; //SWITCH_CAUSE_INTERWORKING; - case 480: - return 18; //SWITCH_CAUSE_NO_USER_RESPONSE; - case 400: - case 481: - case 500: - case 503: - return 41; //SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE; - case 486: - case 600: - return 17; //SWITCH_CAUSE_USER_BUSY; - case 484: - return 28; //SWITCH_CAUSE_INVALID_NUMBER_FORMAT; - case 488: - case 606: - return 65; //SWITCH_CAUSE_BERER_CAPABILITY_NOT_IMPLEMENTED; - case 502: - return 38; //SWITCH_CAUSE_NETWORK_OUT_OF_ORDER; - case 405: - return 63; //SWITCH_CAUSE_SERVICE_UNAVAILABLE; - case 406: - case 415: - case 501: - return 79; //SWITCH_CAUSE_SERVICE_NOT_IMPLEMENTED; - case 482: - case 483: - return 25; //SWITCH_CAUSE_EXCHANGE_ROUTING_ERROR; - case 487: - return 31; //??? SWITCH_CAUSE_ORIGINATOR_CANCEL; (not specified) - default: - return 31; //SWITCH_CAUSE_NORMAL_UNSPECIFIED; - } -} - -static uint16_t isdn2status_cause(uint8_t cause, uint8_t location) -{ - switch (cause) { - case 1: - return 404; - case 2: - return 404; - case 3: - return 404; - case 17: - return 486; - case 18: - return 408; - case 19: - return 480; - case 20: - return 480; - case 21: - if (location == OSMO_CC_LOCATION_USER) - return 603; - return 403; - case 22: - //return 301; - return 410; - case 23: - return 410; - case 26: - return 404; - case 27: - return 502; - case 28: - return 484; - case 29: - return 501; - case 31: - return 480; - case 34: - return 503; - case 38: - return 503; - case 41: - return 503; - case 42: - return 503; - case 47: - return 503; - case 55: - return 403; - case 57: - return 403; - case 58: - return 503; - case 65: - return 488; - case 69: - return 501; - case 70: - return 488; - case 79: - return 501; - case 87: - return 403; - case 88: - return 503; - case 102: - return 504; - case 111: - return 500; - case 127: - return 500; - default: - return 468; - } -} - -static uint8_t socket2isdn_cause(uint8_t sock) -{ - switch (sock) { - case OSMO_CC_SOCKET_CAUSE_FAILED: - return 47; - case OSMO_CC_SOCKET_CAUSE_BROKEN_PIPE: - return 41; - case OSMO_CC_SOCKET_CAUSE_VERSION_MISMATCH: - return 38; - case OSMO_CC_SOCKET_CAUSE_TIMEOUT: - return 41; - default: - return 31; - } -} - -void osmo_cc_convert_cause(struct osmo_cc_ie_cause *cause) -{ - /* complete cause, from socket cause */ - if (cause->socket_cause && cause->isdn_cause == 0 && ntohs(cause->sip_cause_networkorder) == 0) - cause->isdn_cause = socket2isdn_cause(cause->socket_cause); - - /* convert ISDN cause to SIP cause */ - if (cause->isdn_cause && ntohs(cause->sip_cause_networkorder) == 0) { - cause->sip_cause_networkorder = htons(isdn2status_cause(cause->isdn_cause, cause->location)); - } - - /* convert SIP cause to ISDN cause */ - if (ntohs(cause->sip_cause_networkorder) && cause->isdn_cause == 0) { - cause->isdn_cause = status2isdn_cause(ntohs(cause->sip_cause_networkorder)); - } - - /* no cause at all: use Normal Call Clearing */ - if (cause->isdn_cause == 0 && ntohs(cause->sip_cause_networkorder) == 0) { - cause->isdn_cause = OSMO_CC_ISDN_CAUSE_NORM_CALL_CLEAR; - cause->sip_cause_networkorder = htons(486); - } -} - -void osmo_cc_convert_cause_msg(osmo_cc_msg_t *msg) -{ - void *ie; - uint8_t type; - uint16_t length; - void *value; - - /* search for (all) cause IE and convert the values, if needed */ - ie = msg->data; - while ((value = osmo_cc_msg_sep_ie(msg, &ie, &type, &length))) { - if (type == OSMO_CC_IE_CAUSE && length >= sizeof(struct osmo_cc_ie_cause)) { - osmo_cc_convert_cause(value); - } - } -} - -uint8_t osmo_cc_collect_cause(uint8_t old_cause, uint8_t new_cause) -{ - /* first cause */ - if (old_cause == 0) - return new_cause; - - /* first prio: return 17 */ - if (old_cause == OSMO_CC_ISDN_CAUSE_USER_BUSY - || new_cause == OSMO_CC_ISDN_CAUSE_USER_BUSY) - return OSMO_CC_ISDN_CAUSE_USER_BUSY; - - /* second prio: return 21 */ - if (old_cause == OSMO_CC_ISDN_CAUSE_CALL_REJECTED - || new_cause == OSMO_CC_ISDN_CAUSE_CALL_REJECTED) - return OSMO_CC_ISDN_CAUSE_CALL_REJECTED; - - /* third prio: return other than 88 and 18 (what ever was first) */ - if (old_cause != OSMO_CC_ISDN_CAUSE_INCOMPAT_DEST - && old_cause != OSMO_CC_ISDN_CAUSE_USER_NOTRESPOND) - return old_cause; - if (new_cause != OSMO_CC_ISDN_CAUSE_INCOMPAT_DEST - && new_cause != OSMO_CC_ISDN_CAUSE_USER_NOTRESPOND) - return new_cause; - - /* fourth prio: return 88 */ - if (old_cause == OSMO_CC_ISDN_CAUSE_INCOMPAT_DEST - || new_cause == OSMO_CC_ISDN_CAUSE_INCOMPAT_DEST) - return OSMO_CC_ISDN_CAUSE_INCOMPAT_DEST; - - /* fith prio: return 18 */ - return OSMO_CC_ISDN_CAUSE_USER_NOTRESPOND; -} - diff --git a/src/libosmocc/cause.h b/src/libosmocc/cause.h deleted file mode 100644 index 22319f4..0000000 --- a/src/libosmocc/cause.h +++ /dev/null @@ -1,5 +0,0 @@ - -void osmo_cc_convert_cause(struct osmo_cc_ie_cause *cause); -void osmo_cc_convert_cause_msg(osmo_cc_msg_t *msg); -uint8_t osmo_cc_collect_cause(uint8_t old_cause, uint8_t new_cause); - diff --git a/src/libosmocc/endpoint.c b/src/libosmocc/endpoint.c deleted file mode 100644 index cb591b8..0000000 --- a/src/libosmocc/endpoint.c +++ /dev/null @@ -1,1568 +0,0 @@ -/* Endpoint and call process handling - * - * (C) 2019 by Andreas Eversberg - * All Rights Reserved - * - * 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 3 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, see . - */ - -#include -#include -#include -#include -#include -#include -#include "../libtimer/timer.h" -#include "../libdebug/debug.h" -#include "endpoint.h" - -osmo_cc_endpoint_t *osmo_cc_endpoint_list = NULL; - -static osmo_cc_call_t *call_new(osmo_cc_endpoint_t *ep, uint32_t callref) -{ - osmo_cc_call_t *call, **cp; - - call = calloc(1, sizeof(*call)); - if (!call) { - PDEBUG(DCC, DEBUG_ERROR, "No memory for call process instance.\n"); - abort(); - } - - PDEBUG(DCC, DEBUG_DEBUG, "Creating new call with callref %u.\n", callref); - - call->ep = ep; - call->callref = callref; - - /* attach to call process list */ - cp = &ep->call_list; - while (*cp) - cp = &((*cp)->next); - *cp = call; - - /* return new entry */ - return call; -} - -static void call_delete(osmo_cc_call_t *call) -{ - osmo_cc_call_t **cp; - - PDEBUG(DCC, DEBUG_DEBUG, "Destroying call with callref %u.\n", call->callref); - - /* detach from call process list */ - cp = &call->ep->call_list; - while (*cp != call) - cp = &((*cp)->next); - *cp = call->next; - - /* flush message queue */ - while (call->sock_queue) { - osmo_cc_msg_t *msg = osmo_cc_msg_list_dequeue(&call->sock_queue, NULL); - osmo_cc_free_msg(msg); - } - - /* free remote peer */ - free((char *)call->attached_name); - free((char *)call->attached_host); - - free(call); -} - -static const char *state_names[] = { - "IDLE", - "INIT-OUT", - "INIT-IN", - "OVERLAP-OUT", - "OVERLAP-IN", - "PROCEEDING-OUT", - "PROCEEDING-IN", - "ALERTING-OUT", - "ALERTING-IN", - "CONNECTING-OUT", - "CONNECTING-IN", - "ACTIVE", - "DISCONNECTING-OUT", - "DISCONNECTING-IN", - "DISCONNECT-COLLISION", - "RELEASING-OUT", - "ATTACH-SENT", - "ATTACH-OUT", - "ATTACH-WAIT", - "ATTACH-IN", -}; - -static void new_call_state(osmo_cc_call_t *call, enum osmo_cc_state new_state) -{ - PDEBUG(DCC, DEBUG_DEBUG, "Changing call state with callref %u from %s to %s.\n", call->callref, state_names[call->state], state_names[new_state]); - call->state = new_state; -} - -/* helper to forward message to lower layer */ -static void forward_to_ll(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - if (call->lower_layer_released) - return; - - if (msg->type == OSMO_CC_MSG_SETUP_REQ - || msg->type == OSMO_CC_MSG_SETUP_RSP) { - /* screen towards lower layer */ - msg = osmo_cc_screen_msg(call->ep, msg, 0, NULL); - } - - osmo_cc_msg_list_enqueue(&call->ep->ll_queue, msg, call->callref); -} - -static void sock_reject_msg(osmo_cc_socket_t *os, uint32_t callref, uint8_t location, uint8_t socket_cause, uint8_t isdn_cause, uint16_t sip_cause) -{ - osmo_cc_msg_t *msg; - - /* create message */ - msg = osmo_cc_new_msg(OSMO_CC_MSG_REJ_IND); - - /* add cause */ - osmo_cc_add_ie_cause(msg, location, isdn_cause, sip_cause, socket_cause); - osmo_cc_convert_cause_msg(msg); - - /* message to socket */ - osmo_cc_sock_send_msg(os, callref, msg, NULL, 0); -} - -static void ll_reject_msg(osmo_cc_call_t *call, uint8_t location, uint8_t socket_cause, uint8_t isdn_cause, uint16_t sip_cause) -{ - osmo_cc_msg_t *msg; - - /* create message */ - msg = osmo_cc_new_msg(OSMO_CC_MSG_REJ_REQ); - - /* add cause */ - osmo_cc_add_ie_cause(msg, location, isdn_cause, sip_cause, socket_cause); - osmo_cc_convert_cause_msg(msg); - - /* message to lower layer */ - forward_to_ll(call, msg); -} - -static int split_address(const char *address, const char **host_p, uint16_t *port_p) -{ - const char *portstring; - - *host_p = osmo_cc_host_of_address(address); - if (!(*host_p)) { - PDEBUG(DCC, DEBUG_ERROR, "Host IP in given address '%s' is invalid.\n", address); - return -EINVAL; - } - portstring = osmo_cc_port_of_address(address); - if (!portstring) { - PDEBUG(DCC, DEBUG_ERROR, "Port number in given address '%s' is not specified or invalid.\n", address); - return -EINVAL; - } - *port_p = atoi(portstring); - - return 0; -} - - -osmo_cc_call_t *osmo_cc_get_attached_interface(osmo_cc_endpoint_t *ep, const char *interface) -{ - osmo_cc_call_t *att; - - for (att = ep->call_list; att; att = att->next) { - if (att->state != OSMO_CC_STATE_ATTACH_IN) - continue; - /* no interface given, just use the attached peer */ - if (!interface[0]) - break; - /* no interface name given on attached peer, ignore it */ - if (!att->attached_name || !att->attached_name[0]) - continue; - /* interface given, use the attached peer with the same interface name */ - if (!strcmp(interface, att->attached_name)) - break; - } - - return att; -} -/* helper to forward message to upper layer */ -static void forward_to_ul(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - const char *address = NULL, *host = NULL; - uint16_t port; - int rc; - - if (call->upper_layer_released) - return; - - if (msg->type == OSMO_CC_MSG_SETUP_IND - || msg->type == OSMO_CC_MSG_SETUP_CNF) { - /* screen towards upper layer */ - msg = osmo_cc_screen_msg(call->ep, msg, 1, &address); - } - - /* no socket: forward message to upper layer */ - if (call->ep->ul_msg_cb) { - call->ep->ul_msg_cb(call, msg); - return; - } - - /* if remote peer is included in the setup message */ - if (address && msg->type == OSMO_CC_MSG_SETUP_IND) { - rc = split_address(address, &host, &port); - if (rc < 0) { - PDEBUG(DCC, DEBUG_ERROR, "Given remote peer's address '%s' in setup message is invalid, rejecting call.\n", address); -reject: - /* reject, due to error */ - osmo_cc_free_msg(msg); - new_call_state(call, OSMO_CC_STATE_IDLE); - ll_reject_msg(call, call->ep->serving_location, 0, OSMO_CC_ISDN_CAUSE_DEST_OOO, 0); - call_delete(call); - return; - } - PDEBUG(DCC, DEBUG_DEBUG, "Using host IP '%s' and port '%d' from setup message.\n", host, port); - } - - /* for attach message, use remote peer */ - if (msg->type == OSMO_CC_MSG_ATTACH_IND) { - host = call->ep->remote_host; - port = call->ep->remote_port; - PDEBUG(DCC, DEBUG_DEBUG, "Using host IP '%s' and port '%d' from remote address for attach message.\n", host, port); - } - - /* if there is no remote peer in the setup message, use remote peer */ - if (!address && msg->type == OSMO_CC_MSG_SETUP_IND && call->ep->remote_host) { - host = call->ep->remote_host; - port = call->ep->remote_port; - PDEBUG(DCC, DEBUG_DEBUG, "Using host IP '%s' and port '%d' from remote address for setup message.\n", host, port); - } - - /* if there is no remote peer set, try to use the interface name */ - if (!host && msg->type == OSMO_CC_MSG_SETUP_IND) { - char interface[256]; - osmo_cc_call_t *att; - - rc = osmo_cc_get_ie_called_interface(msg, 0, interface, sizeof(interface)); - if (rc < 0) - interface[0] = '\0'; - /* check for incoming attachment */ - att = osmo_cc_get_attached_interface(call->ep, interface); - if (!att && !interface[0]) { - PDEBUG(DCC, DEBUG_ERROR, "No remote peer attached, rejecting call.\n"); - goto reject; - } - if (!att) { - PDEBUG(DCC, DEBUG_ERROR, "No remote peer attached for given interface '%s', rejecting call.\n", interface); - goto reject; - } - host = att->attached_host; - port = att->attached_port; - PDEBUG(DCC, DEBUG_DEBUG, "Using host IP '%s' and port '%d' from attached peer for setup message.\n", host, port); - } - - /* add local interface name to setup message */ - // FIXME: should we do that if there is already an interface name given? - if (msg->type == OSMO_CC_MSG_SETUP_IND && call->ep->local_name) - osmo_cc_add_ie_calling_interface(msg, call->ep->local_name); - - /* forward message to socket */ - osmo_cc_sock_send_msg(&call->ep->os, call->callref, msg, host, port); -} - -/* send attach indication to socket */ -void send_attach_ind(struct timer *timer) -{ - osmo_cc_endpoint_t *ep = (osmo_cc_endpoint_t *)timer->priv; - osmo_cc_call_t *call; - osmo_cc_msg_t *msg; - - PDEBUG(DCC, DEBUG_DEBUG, "Trying to attach to remote peer \"%s\".\n", ep->remote_host); - - /* create new call for attachment */ - call = osmo_cc_call_new(ep); - - /* create attach message */ - msg = osmo_cc_new_msg(OSMO_CC_MSG_ATTACH_IND); - - /* set interface name and address */ - osmo_cc_add_ie_calling_interface(msg, ep->local_name); - osmo_cc_add_ie_socket_address(msg, ep->local_address); - - /* message to socket */ - forward_to_ul(call, msg); - - /* set state */ - new_call_state(call, OSMO_CC_STATE_ATTACH_SENT); -} - -void attach_rsp(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - PDEBUG(DCC, DEBUG_INFO, "Attached to remote peer \"%s\".\n", call->ep->remote_address); - - /* set state */ - new_call_state(call, OSMO_CC_STATE_ATTACH_OUT); - - /* drop message */ - osmo_cc_free_msg(msg); -} - -void attach_rel(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* (re-)start timer for next attachment */ - if (call->state == OSMO_CC_STATE_ATTACH_SENT - || call->state == OSMO_CC_STATE_ATTACH_OUT) { - timer_start(&call->ep->attach_timer, OSMO_CC_ATTACH_TIMER); - PDEBUG(DCC, DEBUG_INFO, "Attachment to remote peer \"%s\" failed, retrying.\n", call->ep->remote_address); - } - - if (call->attached_name) - PDEBUG(DCC, DEBUG_INFO, "Peer with remote interface \"%s\" detached from us.\n", call->attached_name); - - /* change state */ - new_call_state(call, OSMO_CC_STATE_IDLE); - - /* unset interface */ - free((char *)call->attached_name); - call->attached_name = NULL; - free((char *)call->attached_host); - call->attached_host = NULL; - - /* drop message */ - osmo_cc_free_msg(msg); - - /* destroy */ - call_delete(call); -} - -void attach_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - char address[256]; - char interface[256]; - const char *host; - uint16_t port; - int rc; - - /* get peer from message */ - rc = osmo_cc_get_ie_socket_address(msg, 0, address, sizeof(address)); - if (rc < 0) - address[0] = '\0'; - if (!address[0]) { - PDEBUG(DCC, DEBUG_ERROR, "Attachment request from remote peer has no remote address set, rejecting.\n"); - -rel: - /* change to REL_REQ */ - msg->type = OSMO_CC_MSG_REL_IND; - PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type)); - - /* message to socket */ - forward_to_ul(call, msg); - - /* destroy */ - call_delete(call); - - return; - } - rc = split_address(address, &host, &port); - if (rc < 0) { - PDEBUG(DCC, DEBUG_ERROR, "Given remote peer's address '%s' in attach message is invalid, rejecting call.\n", address); - goto rel; - } - free((char *)call->attached_host); - call->attached_host = strdup(host); - call->attached_port = port; - - rc = osmo_cc_get_ie_calling_interface(msg, 0, interface, sizeof(interface)); - if (rc < 0) - interface[0] = '\0'; - if (interface[0]) { - free((char *)call->attached_name); - call->attached_name = strdup(interface); - } - - PDEBUG(DCC, DEBUG_INFO, "Remote peer with socket address '%s' and port '%d' and interface '%s' attached to us.\n", call->attached_host, call->attached_port, call->attached_name); - - /* changing to confirm message */ - msg->type = OSMO_CC_MSG_ATTACH_CNF; - PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type)); - - /* message to socket */ - forward_to_ul(call, msg); - - /* set state */ - new_call_state(call, OSMO_CC_STATE_ATTACH_IN); -} - -static void setup_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* change state */ - new_call_state(call, OSMO_CC_STATE_INIT_OUT); - - /* to lower layer */ - forward_to_ll(call, msg); -} - -static void setup_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* change state */ - new_call_state(call, OSMO_CC_STATE_INIT_IN); - - /* to upper layer */ - forward_to_ul(call, msg); -} - -static void rej_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* change state */ - new_call_state(call, OSMO_CC_STATE_IDLE); - - /* to lower layer */ - forward_to_ll(call, msg); - - /* destroy */ - call_delete(call); -} - -static void rej_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* change state */ - new_call_state(call, OSMO_CC_STATE_IDLE); - - /* to upper layer */ - forward_to_ul(call, msg); - - /* destroy */ - call_delete(call); -} - -static void setup_ack_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* change state */ - new_call_state(call, OSMO_CC_STATE_OVERLAP_IN); - - /* to lower layer */ - forward_to_ll(call, msg); -} - -static void setup_ack_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* change state */ - new_call_state(call, OSMO_CC_STATE_OVERLAP_OUT); - - /* to upper layer */ - forward_to_ul(call, msg); -} - -static void proc_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* change state */ - new_call_state(call, OSMO_CC_STATE_PROCEEDING_IN); - - /* to lower layer */ - forward_to_ll(call, msg); -} - -static void proc_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* change state */ - new_call_state(call, OSMO_CC_STATE_PROCEEDING_OUT); - - /* to upper layer */ - forward_to_ul(call, msg); -} - -static void alert_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* change state */ - new_call_state(call, OSMO_CC_STATE_ALERTING_IN); - - /* to lower layer */ - forward_to_ll(call, msg); -} - -static void alert_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* change state */ - new_call_state(call, OSMO_CC_STATE_ALERTING_OUT); - - /* to upper layer */ - forward_to_ul(call, msg); -} - -static void setup_rsp(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* change state */ - new_call_state(call, OSMO_CC_STATE_CONNECTING_IN); - - /* to lower layer */ - forward_to_ll(call, msg); -} - -static void setup_cnf(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* change state */ - new_call_state(call, OSMO_CC_STATE_CONNECTING_OUT); - - /* to upper layer */ - forward_to_ul(call, msg); -} - -static void setup_comp_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* change state */ - new_call_state(call, OSMO_CC_STATE_ACTIVE); - - /* to lower layer */ - forward_to_ll(call, msg); -} - -static void setup_comp_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* change state */ - new_call_state(call, OSMO_CC_STATE_ACTIVE); - - /* to upper layer */ - forward_to_ul(call, msg); -} - -static void info_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* to lower layer */ - forward_to_ll(call, msg); -} - -static void info_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* to upper layer */ - forward_to_ul(call, msg); -} - -static void progress_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* to lower layer */ - forward_to_ll(call, msg); -} - -static void progress_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* to upper layer */ - forward_to_ul(call, msg); -} - -static void notify_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* to lower layer */ - forward_to_ll(call, msg); -} - -static void notify_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* to upper layer */ - forward_to_ul(call, msg); -} - -static void update_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* to lower layer */ - forward_to_ll(call, msg); -} - -static void update_cnf(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* to upper layer */ - forward_to_ul(call, msg); -} - -static void disc_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* change state */ - new_call_state(call, OSMO_CC_STATE_DISCONNECTING_OUT); - - /* to lower layer */ - forward_to_ll(call, msg); -} - -static void disc_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* change state */ - new_call_state(call, OSMO_CC_STATE_DISCONNECTING_IN); - - /* to upper layer */ - forward_to_ul(call, msg); -} - -static void rel_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* terminate process, if there is no lower layer anmore */ - if (call->lower_layer_released) { - /* change state */ - new_call_state(call, OSMO_CC_STATE_IDLE); - - /* drop message */ - osmo_cc_free_msg(msg); - - /* destroy */ - call_delete(call); - - return; - } - - /* change state */ - new_call_state(call, OSMO_CC_STATE_RELEASING_OUT); - - /* to lower layer */ - forward_to_ll(call, msg); -} - -static void rel_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* change state */ - new_call_state(call, OSMO_CC_STATE_IDLE); - - /* to upper layer */ - forward_to_ul(call, msg); - - /* destroy */ - call_delete(call); -} - -static void rel_cnf(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* change state */ - new_call_state(call, OSMO_CC_STATE_IDLE); - - /* drop message */ - osmo_cc_free_msg(msg); - - /* destroy */ - call_delete(call); -} - -static void disc_collision_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* release to lower layer wheen there is no upper layer */ - if (call->upper_layer_released) { - /* change state */ - new_call_state(call, OSMO_CC_STATE_RELEASING_OUT); - - /* change to REL_REQ */ - msg->type = OSMO_CC_MSG_REL_REQ; - PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type)); - - /* to lower layer */ - forward_to_ll(call, msg); - - return; - } - - /* change state */ - new_call_state(call, OSMO_CC_STATE_DISC_COLLISION); - - /* to upper layer */ - forward_to_ul(call, msg); -} - -static void disc_collision_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* release to upper layer wheen there is no lower layer */ - if (call->lower_layer_released) { - /* change to REL_REQ */ - msg->type = OSMO_CC_MSG_REL_IND; - PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type)); - - /* to upper layer */ - forward_to_ul(call, msg); - - /* destroy */ - call_delete(call); - - return; - } - - /* change state */ - new_call_state(call, OSMO_CC_STATE_DISC_COLLISION); - - /* to lower layer */ - forward_to_ll(call, msg); -} - -static void rel_collision(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* change state */ - if (call->state != OSMO_CC_STATE_IDLE) - new_call_state(call, OSMO_CC_STATE_IDLE); - - /* drop message */ - osmo_cc_free_msg(msg); - - /* destroy */ - call_delete(call); -} - -static void rej_ind_disc(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* change state */ - new_call_state(call, OSMO_CC_STATE_IDLE); - - /* change to REL_IND */ - msg->type = OSMO_CC_MSG_REL_IND; - PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type)); - - /* to upper layer */ - forward_to_ul(call, msg); - - /* destroy */ - call_delete(call); -} - -static void rej_req_disc(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* change state */ - new_call_state(call, OSMO_CC_STATE_IDLE); - - /* change to REL_REQ */ - msg->type = OSMO_CC_MSG_REL_REQ; - PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type)); - - /* to lower layer */ - forward_to_ll(call, msg); - - /* destroy */ - call_delete(call); -} - -static void rel_ind_other(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - // FIXME: does this event really happens in this state? - // just to be safe we handle it - /* if thereis no upper layer, we are done */ - if (call->upper_layer_released) { - /* drop message */ - osmo_cc_free_msg(msg); - - /* destroy */ - call_delete(call); - - return; - } - - /* change state */ - new_call_state(call, OSMO_CC_STATE_DISCONNECTING_IN); - - /* change to DISC_IND */ - msg->type = OSMO_CC_MSG_DISC_IND; - PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type)); - call->lower_layer_released = 1; - - /* to upper layer */ - forward_to_ul(call, msg); -} - -static void rel_req_other(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - // FIXME: does this event really happens in this state? - // just to be safe we handle it - /* if thereis no lower layer, we are done */ - if (call->lower_layer_released) { - /* drop message */ - osmo_cc_free_msg(msg); - - /* destroy */ - call_delete(call); - - return; - } - - /* change state */ - new_call_state(call, OSMO_CC_STATE_DISCONNECTING_OUT); - - /* change to DISC_REQ */ - msg->type = OSMO_CC_MSG_DISC_REQ; - PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type)); - call->upper_layer_released = 1; - - /* to lower layer */ - forward_to_ll(call, msg); -} - -#define SBIT(a) (1 << a) -#define ALL_STATES (~0) - -static struct statemachine { - uint32_t states; - int type; - void (*action)(osmo_cc_call_t *call, osmo_cc_msg_t *msg); -} statemachine_list[] = { - /* attachment states */ - {SBIT(OSMO_CC_STATE_ATTACH_SENT), - OSMO_CC_MSG_ATTACH_RSP, attach_rsp}, - {SBIT(OSMO_CC_STATE_ATTACH_OUT) | SBIT(OSMO_CC_STATE_ATTACH_SENT), - OSMO_CC_MSG_REL_REQ, attach_rel}, - {SBIT(OSMO_CC_STATE_IDLE), - OSMO_CC_MSG_ATTACH_REQ, attach_req}, - {SBIT(OSMO_CC_STATE_ATTACH_IN), - OSMO_CC_MSG_REL_REQ, attach_rel}, - - /* call setup toward lower layer protocol */ - {SBIT(OSMO_CC_STATE_IDLE), - OSMO_CC_MSG_SETUP_REQ, setup_req}, - {SBIT(OSMO_CC_STATE_INIT_OUT), - OSMO_CC_MSG_SETUP_ACK_IND, setup_ack_ind}, - {SBIT(OSMO_CC_STATE_INIT_OUT) | SBIT(OSMO_CC_STATE_OVERLAP_OUT), - OSMO_CC_MSG_PROC_IND, proc_ind}, - {SBIT(OSMO_CC_STATE_INIT_OUT) | SBIT(OSMO_CC_STATE_OVERLAP_OUT) | - SBIT(OSMO_CC_STATE_PROCEEDING_OUT), - OSMO_CC_MSG_ALERT_IND, alert_ind}, - {SBIT(OSMO_CC_STATE_INIT_OUT) | SBIT(OSMO_CC_STATE_OVERLAP_OUT) | - SBIT(OSMO_CC_STATE_PROCEEDING_OUT) | SBIT(OSMO_CC_STATE_ALERTING_OUT), - OSMO_CC_MSG_SETUP_CNF, setup_cnf}, - {SBIT(OSMO_CC_STATE_OVERLAP_OUT) | SBIT(OSMO_CC_STATE_PROCEEDING_OUT) | - SBIT(OSMO_CC_STATE_ALERTING_OUT), - OSMO_CC_MSG_PROGRESS_IND, progress_ind}, - {SBIT(OSMO_CC_STATE_OVERLAP_OUT), - OSMO_CC_MSG_INFO_REQ, info_req}, - {SBIT(OSMO_CC_STATE_PROCEEDING_OUT) | SBIT(OSMO_CC_STATE_ALERTING_OUT), - OSMO_CC_MSG_NOTIFY_IND, notify_ind}, - {SBIT(OSMO_CC_STATE_CONNECTING_OUT), - OSMO_CC_MSG_SETUP_COMP_REQ, setup_comp_req}, - - /* call setup from lower layer protocol */ - {SBIT(OSMO_CC_STATE_IDLE), - OSMO_CC_MSG_SETUP_IND, setup_ind}, - {SBIT(OSMO_CC_STATE_INIT_IN), - OSMO_CC_MSG_SETUP_ACK_REQ, setup_ack_req}, - {SBIT(OSMO_CC_STATE_INIT_IN) | SBIT(OSMO_CC_STATE_OVERLAP_IN), - OSMO_CC_MSG_PROC_REQ, proc_req}, - {SBIT(OSMO_CC_STATE_INIT_IN) | SBIT(OSMO_CC_STATE_OVERLAP_IN) | - SBIT(OSMO_CC_STATE_PROCEEDING_IN), - OSMO_CC_MSG_ALERT_REQ, alert_req}, - {SBIT(OSMO_CC_STATE_INIT_IN) | SBIT(OSMO_CC_STATE_OVERLAP_IN) | - SBIT(OSMO_CC_STATE_PROCEEDING_IN) | SBIT(OSMO_CC_STATE_ALERTING_IN), - OSMO_CC_MSG_SETUP_RSP, setup_rsp}, - {SBIT(OSMO_CC_STATE_OVERLAP_IN) | SBIT(OSMO_CC_STATE_PROCEEDING_IN) | - SBIT(OSMO_CC_STATE_ALERTING_IN), - OSMO_CC_MSG_PROGRESS_REQ, progress_req}, - {SBIT(OSMO_CC_STATE_OVERLAP_IN), - OSMO_CC_MSG_INFO_IND, info_ind}, - {SBIT(OSMO_CC_STATE_PROCEEDING_IN) | SBIT(OSMO_CC_STATE_ALERTING_IN), - OSMO_CC_MSG_NOTIFY_REQ, notify_req}, - {SBIT(OSMO_CC_STATE_CONNECTING_IN), - OSMO_CC_MSG_SETUP_COMP_IND, setup_comp_ind}, - - /* active state */ - {SBIT(OSMO_CC_STATE_ACTIVE), - OSMO_CC_MSG_NOTIFY_IND, notify_ind}, - {SBIT(OSMO_CC_STATE_ACTIVE), - OSMO_CC_MSG_NOTIFY_REQ, notify_req}, - {SBIT(OSMO_CC_STATE_ACTIVE), - OSMO_CC_MSG_INFO_IND, info_ind}, - {SBIT(OSMO_CC_STATE_ACTIVE), - OSMO_CC_MSG_INFO_REQ, info_req}, - {SBIT(OSMO_CC_STATE_ACTIVE), - OSMO_CC_MSG_UPDATE_REQ, update_req}, - {SBIT(OSMO_CC_STATE_ACTIVE), - OSMO_CC_MSG_UPDATE_CNF, update_cnf}, - - /* call release */ - {SBIT(OSMO_CC_STATE_INIT_OUT) | SBIT(OSMO_CC_STATE_INIT_IN) | - SBIT(OSMO_CC_STATE_OVERLAP_OUT) | SBIT(OSMO_CC_STATE_OVERLAP_IN) | - SBIT(OSMO_CC_STATE_PROCEEDING_OUT) | SBIT(OSMO_CC_STATE_PROCEEDING_IN) | - SBIT(OSMO_CC_STATE_ALERTING_OUT) | SBIT(OSMO_CC_STATE_ALERTING_IN) | - SBIT(OSMO_CC_STATE_CONNECTING_OUT) | SBIT(OSMO_CC_STATE_CONNECTING_IN) | - SBIT(OSMO_CC_STATE_ACTIVE), - OSMO_CC_MSG_DISC_REQ, disc_req}, - {SBIT(OSMO_CC_STATE_INIT_OUT) | SBIT(OSMO_CC_STATE_INIT_IN) | - SBIT(OSMO_CC_STATE_OVERLAP_OUT) | SBIT(OSMO_CC_STATE_OVERLAP_IN) | - SBIT(OSMO_CC_STATE_PROCEEDING_OUT) | SBIT(OSMO_CC_STATE_PROCEEDING_IN) | - SBIT(OSMO_CC_STATE_ALERTING_OUT) | SBIT(OSMO_CC_STATE_ALERTING_IN) | - SBIT(OSMO_CC_STATE_CONNECTING_OUT) | SBIT(OSMO_CC_STATE_CONNECTING_IN) | - SBIT(OSMO_CC_STATE_ACTIVE), - OSMO_CC_MSG_DISC_IND, disc_ind}, - {SBIT(OSMO_CC_STATE_INIT_OUT), - OSMO_CC_MSG_REJ_IND, rej_ind}, - {SBIT(OSMO_CC_STATE_INIT_IN), - OSMO_CC_MSG_REJ_REQ, rej_req}, - {SBIT(OSMO_CC_STATE_DISCONNECTING_OUT), - OSMO_CC_MSG_REL_IND, rel_ind}, - {SBIT(OSMO_CC_STATE_DISCONNECTING_IN), - OSMO_CC_MSG_REL_REQ, rel_req}, - {SBIT(OSMO_CC_STATE_RELEASING_OUT), - OSMO_CC_MSG_REL_CNF, rel_cnf}, - - /* race condition where disconnect is received after disconnecting (disconnect collision) */ - {SBIT(OSMO_CC_STATE_DISCONNECTING_OUT), - OSMO_CC_MSG_DISC_IND, disc_collision_ind}, - {SBIT(OSMO_CC_STATE_DISCONNECTING_IN), - OSMO_CC_MSG_DISC_REQ, disc_collision_req}, - {SBIT(OSMO_CC_STATE_DISC_COLLISION), - OSMO_CC_MSG_REL_IND, rel_ind}, - {SBIT(OSMO_CC_STATE_DISC_COLLISION), - OSMO_CC_MSG_REL_REQ, rel_req}, - - /* race condition where release is received after releasing (release collision) */ - {SBIT(OSMO_CC_STATE_RELEASING_OUT), - OSMO_CC_MSG_REL_IND, rel_collision}, - {SBIT(OSMO_CC_STATE_IDLE), - OSMO_CC_MSG_REL_REQ, rel_collision}, - - /* race condition where reject is received after disconnecting */ - {SBIT(OSMO_CC_STATE_DISCONNECTING_OUT), - OSMO_CC_MSG_REJ_IND, rej_ind_disc}, - {SBIT(OSMO_CC_STATE_DISCONNECTING_IN), - OSMO_CC_MSG_REJ_REQ, rej_req_disc}, - - /* turn release into disconnect, so release is possible in any state */ - {ALL_STATES, - OSMO_CC_MSG_REL_IND, rel_ind_other}, - {ALL_STATES, - OSMO_CC_MSG_REL_REQ, rel_req_other}, -}; - -#define STATEMACHINE_LEN \ - (sizeof(statemachine_list) / sizeof(struct statemachine)) - -static void handle_msg(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - int i; - - /* Find function for current state and message */ - for (i = 0; i < (int)STATEMACHINE_LEN; i++) - if ((msg->type == statemachine_list[i].type) - && ((1 << call->state) & statemachine_list[i].states)) - break; - if (i == STATEMACHINE_LEN) { - PDEBUG(DCC, DEBUG_INFO, "Message %s unhandled at state %s (callref %d)\n", - osmo_cc_msg_value2name(msg->type), state_names[call->state], call->callref); - osmo_cc_free_msg(msg); - return; - } - - PDEBUG(DCC, DEBUG_INFO, "Handle message %s at state %s (callref %d)\n", - osmo_cc_msg_value2name(msg->type), state_names[call->state], call->callref); - if (debuglevel <= DEBUG_INFO) - osmo_cc_debug_ie(msg, DEBUG_INFO); - statemachine_list[i].action(call, msg); -} - -static int handle_call(osmo_cc_call_t *call) -{ - /* may handle only one message, since call may be destroyed when handling */ - if (call->sock_queue) { - osmo_cc_msg_t *msg = osmo_cc_msg_list_dequeue(&call->sock_queue, NULL); - handle_msg(call, msg); - return 1; - } - - return 0; -} - -static int osmo_cc_handle_endpoint(osmo_cc_endpoint_t *ep) -{ - int work = 0; - uint32_t callref; - osmo_cc_call_t *call; - - /* may handle only one message, since call may be destroyed when handling */ - if (ep->ll_queue) { - osmo_cc_msg_t *msg = osmo_cc_msg_list_dequeue(&ep->ll_queue, &callref); - ep->ll_msg_cb(ep, callref, msg); - work |= 1; - } - - /* handle only one call, because it might have been removed */ - for (call = ep->call_list; call; call = call->next) { - work |= handle_call(call); - if (work) - break; - } - - return work; -} - -/* main handler - * note that it must be called in a loop (with other handlers) until no work was done - */ -int osmo_cc_handle(void) -{ - int work = 0; - osmo_cc_endpoint_t *ep; - - for (ep = osmo_cc_endpoint_list; ep; ep = ep->next) { - work |= osmo_cc_handle_endpoint(ep); - work |= osmo_cc_handle_socket(&ep->os); - } - - return work; -} - -osmo_cc_call_t *osmo_cc_call_by_callref(osmo_cc_endpoint_t *ep, uint32_t callref) -{ - osmo_cc_call_t *call; - - if (!callref) - return NULL; - - for (call = ep->call_list; call; call = call->next) { - if (call->callref == callref) { - return call; - } - } - - return NULL; -} - - -void osmo_cc_ll_msg(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg) -{ - osmo_cc_call_t *call; - - if (!(msg->type & 1)) { - PDEBUG(DCC, DEBUG_ERROR, "Received message from lower layer that is not an _IND nor _CNF, please fix!\n"); - osmo_cc_free_msg(msg); - return; - } - - call = osmo_cc_call_by_callref(ep, callref); - if (call) { - /* complete cause */ - osmo_cc_convert_cause_msg(msg); - handle_msg(call, msg); - return; - } - - /* if no ref exists */ -} - -/* message from upper layer (socket) */ -void osmo_cc_ul_msg(void *priv, uint32_t callref, osmo_cc_msg_t *msg) -{ - osmo_cc_endpoint_t *ep = priv; - osmo_cc_call_t *call; - - if ((msg->type & 1)) { - PDEBUG(DCC, DEBUG_ERROR, "Received message from socket that is not an _REQ nor _RSP, please fix!\n"); - osmo_cc_free_msg(msg); - return; - } - - call = osmo_cc_call_by_callref(ep, callref); - if (call) { - /* if we are not in INIT-IN state, we change a CC-REJ-REQ into CC-REL_REQ. - * this happens, if the socket fails. - */ - if (call->state != OSMO_CC_STATE_INIT_IN - && msg->type == OSMO_CC_MSG_REJ_REQ) - msg->type = OSMO_CC_MSG_REL_REQ; - - osmo_cc_msg_list_enqueue(&call->sock_queue, msg, call->callref); - return; - } - - /* if no ref exists */ - - /* reject and release are ignored */ - if (msg->type == OSMO_CC_MSG_REJ_REQ - || msg->type == OSMO_CC_MSG_REL_REQ) { - osmo_cc_free_msg(msg); - return; - } - - /* reject if not a setup/attach or release message */ - if (msg->type != OSMO_CC_MSG_SETUP_REQ - && msg->type != OSMO_CC_MSG_ATTACH_REQ) { - sock_reject_msg(&ep->os, callref, ep->serving_location, 0, OSMO_CC_ISDN_CAUSE_INVAL_CALLREF, 0); - osmo_cc_free_msg(msg); - return; - } - - /* create call instance with one socket reference */ - call = call_new(ep, callref); - - osmo_cc_msg_list_enqueue(&call->sock_queue, msg, call->callref); -} - -static void osmo_cc_help_name(void) -{ - printf("Name options:\n\n"); - - printf("name \n"); - - printf("Allows to override endpoint name given by application.\n"); -} - -static int osmo_cc_set_name(osmo_cc_endpoint_t *ep, const char *text) -{ - if (!strncasecmp(text, "name", 4)) { - text += 4; - /* remove spaces after keyword */ - while (*text) { - if (*text > 32) - break; - text++; - } - } else { - PDEBUG(DCC, DEBUG_ERROR, "Invalid name definition '%s'\n", text); - return -EINVAL; - } - - free((char *)ep->local_name); - ep->local_name = strdup(text); - - return 0; -} - -static void osmo_cc_help_address(void) -{ - printf("Address options:\n\n"); - - printf("local :\n"); - printf("local []:\n"); - printf("remote :\n"); - printf("remote []:\n\n"); - printf("remote auto\n\n"); - printf("remote none\n\n"); - - printf("These options can be used to define local and remote IP and port for the socket\n"); - printf("interface. Note that IPv6 addresses must be enclosed by '[' and ']'.\n\n"); - - printf("If no local address was given, the IPv4 loopback IP and port %d is used. If\n", OSMO_CC_DEFAULT_PORT); - printf("this port is already in use, the first free higher port is used.\n\n"); - - printf("If no remote address is given, the local IP is used. If the local port is %d,\n", OSMO_CC_DEFAULT_PORT); - printf("the remote port will be %d. If not, the remote port will be %d. This way it is\n", OSMO_CC_DEFAULT_PORT + 1, OSMO_CC_DEFAULT_PORT); - printf("possible to link two interfaces without any IP configuration required.\n\n"); - - printf("Use 'remote auto' to enable and 'remote none' to disable. This can be useful to\n"); - printf("override application default.\n\n"); -} - -static int osmo_cc_set_address(osmo_cc_endpoint_t *ep, const char *text) -{ - const char **address_p, **host_p; - uint16_t *port_p; - int local = 0; - int rc; - - if (!strncasecmp(text, "local", 5)) { - text += 5; - /* remove spaces after keyword */ - while (*text) { - if (*text > 32) - break; - text++; - } - address_p = &ep->local_address; - host_p = &ep->local_host; - port_p = &ep->local_port; - local = 1; - } else if (!strncasecmp(text, "remote", 6)) { - text += 6; - /* remove spaces after keyword */ - while (*text) { - if (*text > 32) - break; - text++; - } - if (!strcasecmp(text, "auto")) { - PDEBUG(DCC, DEBUG_DEBUG, "setting automatic remote peer selection\n"); - ep->remote_auto = 1; - return 0; - } - if (!strcasecmp(text, "none")) { - PDEBUG(DCC, DEBUG_DEBUG, "disable automatic remote peer selection\n"); - ep->remote_auto = 0; - return 0; - } - ep->remote_auto = 0; - address_p = &ep->remote_address; - host_p = &ep->remote_host; - port_p = &ep->remote_port; - } else { - PDEBUG(DCC, DEBUG_ERROR, "Invalid local or remote address definition '%s'\n", text); - return -EINVAL; - } - - if (*address_p) { - free((char *)*address_p); - *address_p = NULL; - } - if (*host_p) { - free((char *)*host_p); - *host_p = NULL; - } - rc = split_address(text, host_p, port_p); - if (rc < 0) { - /* unset, so that this is not treated with free() */ - *host_p = NULL; - return rc; - } - *address_p = strdup(text); - *host_p = strdup(*host_p); - - if (local) { - enum osmo_cc_session_addrtype addrtype; - addrtype = osmo_cc_address_type(*host_p); - if (addrtype == osmo_cc_session_addrtype_unknown) { - PDEBUG(DCC, DEBUG_ERROR, "Given local address '%s' is invalid.\n", *host_p); - return -EINVAL; - } - osmo_cc_set_local_peer(&ep->session_config, osmo_cc_session_nettype_inet, addrtype, *host_p); - return 0; - } - - return 0; -} - -static void osmo_cc_help_rtp(void) -{ - printf("RTP options:\n\n"); - - printf("rtp-peer \n"); - printf("rtp-peer \n"); - printf("rtp-ports \n\n"); - - printf("These options can be used to alter the local IP and port range for RTP traffic.\n"); - printf("By default the local peer is used, which is loopback by default. To connect\n"); - printf("interfaces, between machines, local machine's IP must be given.\n\n"); -} - -static int osmo_cc_set_rtp(osmo_cc_endpoint_t *ep, const char *text) -{ - int peer = 0, ports = 0; - - if (!strncasecmp(text, "rtp-peer", 8)) { - text += 8; - peer = 1; - } else if (!strncasecmp(text, "rtp-ports", 9)) { - text += 9; - ports = 1; - } else { - PDEBUG(DCC, DEBUG_ERROR, "Invalid RTP definition '%s'\n", text); - return -EINVAL; - } - - /* remove spaces after keyword */ - while (*text) { - if (*text > 32) - break; - text++; - } - - if (peer) { - enum osmo_cc_session_addrtype addrtype; - addrtype = osmo_cc_address_type(text); - if (addrtype == osmo_cc_session_addrtype_unknown) { - PDEBUG(DCC, DEBUG_ERROR, "Given RTP address '%s' is invalid.\n", text); - return -EINVAL; - } - osmo_cc_set_local_peer(&ep->session_config, osmo_cc_session_nettype_inet, addrtype, text); - return 0; - } - - if (ports) { - int from = 0, to = 0; - - /* from port */ - while (*text > ' ') { - if (*text < '0' || *text > '9') { - PDEBUG(DCC, DEBUG_ERROR, "Given 'from' port in '%s' is invalid.\n", text); - return -EINVAL; - } - from = from * 10 + *text - '0'; - text++; - } - - /* remove spaces after keyword */ - while (*text) { - if (*text > 32) - break; - text++; - } - - /* to port */ - while (*text > ' ') { - if (*text < '0' || *text > '9') { - PDEBUG(DCC, DEBUG_ERROR, "Given 'to' port in '%s' is invalid.\n", text); - return -EINVAL; - } - to = to * 10 + *text - '0'; - text++; - } - - osmo_cc_set_rtp_ports(&ep->session_config, from, to); - return 0; - } - - return -EINVAL; -} - -void osmo_cc_help(void) -{ - osmo_cc_help_name(); - osmo_cc_help_address(); - osmo_cc_help_rtp(); - osmo_cc_help_screen(); -} - -/* create a new endpoint instance */ -int osmo_cc_new(osmo_cc_endpoint_t *ep, const char *version, const char *name, uint8_t serving_location, void (*ll_msg_cb)(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg), void (*ul_msg_cb)(osmo_cc_call_t *call, osmo_cc_msg_t *msg), void *priv, int argc, const char *argv[]) -{ - osmo_cc_endpoint_t **epp; - int rc; - int i; - - PDEBUG(DCC, DEBUG_DEBUG, "Creating new endpoint instance.\n"); - - if (!!strcmp(version, OSMO_CC_VERSION)) { - PDEBUG(DCC, DEBUG_ERROR, "Application was compiled for different Osmo-CC version.\n"); - return OSMO_CC_RC_VERSION_MISMATCH; - } - - memset(ep, 0, sizeof(*ep)); - - /* attach to list */ - epp = &osmo_cc_endpoint_list; - while (*epp) - epp = &((*epp)->next); - *epp = ep; - - if (name) - ep->local_name = strdup(name); - ep->ll_msg_cb = ll_msg_cb; - ep->ul_msg_cb = ul_msg_cb; - ep->serving_location = serving_location; - ep->priv = priv; - - osmo_cc_set_local_peer(&ep->session_config, osmo_cc_session_nettype_inet, osmo_cc_session_addrtype_ipv4, "127.0.0.1"); - osmo_cc_set_rtp_ports(&ep->session_config, 16384, 32767); - - /* apply args */ - for (i = 0; i < argc; i++) { - if (!strncasecmp(argv[i], "name", 4)) { - rc = osmo_cc_set_name(ep, argv[i]); - if (rc < 0) { - return rc; - } - } else - if (!strncasecmp(argv[i], "local", 5)) { - rc = osmo_cc_set_address(ep, argv[i]); - if (rc < 0) { - return rc; - } - } else - if (!strncasecmp(argv[i], "remote", 6)) { - rc = osmo_cc_set_address(ep, argv[i]); - if (rc < 0) { - return rc; - } - } else - if (!strncasecmp(argv[i], "rtp", 3)) { - rc = osmo_cc_set_rtp(ep, argv[i]); - if (rc < 0) { - return rc; - } - } else - if (!strncasecmp(argv[i], "screen", 6)) { - rc = osmo_cc_add_screen(ep, argv[i]); - if (rc < 0) { - return rc; - } - } else { - PDEBUG(DCC, DEBUG_ERROR, "Unknown osmo-cc argument \"%s\"\n", argv[i]); - return -EINVAL; - } - } - - /* open socket */ - if (!ul_msg_cb) { - char address[256]; - const char *host; - uint16_t port; - enum osmo_cc_session_addrtype addrtype; - - host = ep->local_host; - port = ep->local_port; - if (!host) { - host = "127.0.0.1"; - PDEBUG(DCC, DEBUG_DEBUG, "No local peer set, using default \"%s\"\n", host); - } - rc = osmo_cc_open_socket(&ep->os, host, port, ep, osmo_cc_ul_msg, serving_location); - if (rc < 0) { - return rc; - } - port = rc; - if (!ep->local_host) { - ep->local_host = strdup(host); - /* create address string */ - addrtype = osmo_cc_address_type(host); - if (addrtype == osmo_cc_session_addrtype_ipv6) - sprintf(address, "[%s]:%d", host, port); - else - sprintf(address, "%s:%d", host, port); - ep->local_address = strdup(address); - } - ep->local_port = port; - /* auto configure */ - if (ep->remote_auto) { - free((char *)ep->remote_host); - ep->remote_host = strdup(ep->local_host); - PDEBUG(DCC, DEBUG_DEBUG, "Remote peer set to auto, using local peer's host \"%s\" for remote peer.\n", ep->remote_host); - if (rc == OSMO_CC_DEFAULT_PORT) - ep->remote_port = OSMO_CC_DEFAULT_PORT + 1; - else - ep->remote_port = OSMO_CC_DEFAULT_PORT; - PDEBUG(DCC, DEBUG_DEBUG, " -> Using remote port %d.\n", ep->remote_port); - /* create address string */ - free((char *)ep->remote_address); - addrtype = osmo_cc_address_type(ep->remote_host); - if (addrtype == osmo_cc_session_addrtype_ipv6) - sprintf(address, "[%s]:%d", ep->remote_host, ep->remote_port); - else - sprintf(address, "%s:%d", ep->remote_host, ep->remote_port); - ep->remote_address = strdup(address); - } - /* attach to remote host */ - timer_init(&ep->attach_timer, send_attach_ind, ep); - if (ep->remote_host) { - send_attach_ind(&ep->attach_timer); - } - } - - return 0; -} - -/* destroy an endpoint instance */ -void osmo_cc_delete(osmo_cc_endpoint_t *ep) -{ - osmo_cc_endpoint_t **epp; - - PDEBUG(DCC, DEBUG_DEBUG, "Destroying endpoint instance.\n"); - - /* detach from list >*/ - epp = &osmo_cc_endpoint_list; - while (*epp && *epp != ep) - epp = &((*epp)->next); - if (*epp) - *epp = ep->next; - - /* remove timer */ - timer_exit(&ep->attach_timer); - - /* flush screen lists */ - osmo_cc_flush_screen(ep->screen_calling_in); - osmo_cc_flush_screen(ep->screen_called_in); - osmo_cc_flush_screen(ep->screen_calling_out); - osmo_cc_flush_screen(ep->screen_called_out); - - /* free local and remote peer */ - free((char *)ep->local_name); - free((char *)ep->local_address); - free((char *)ep->local_host); - free((char *)ep->remote_address); - free((char *)ep->remote_host); - - /* destroying all child callesses (calls) */ - while(ep->call_list) - call_delete(ep->call_list); - - /* flush message queue */ - while(ep->ll_queue) { - osmo_cc_msg_t *msg = osmo_cc_msg_list_dequeue(&ep->ll_queue, NULL); - osmo_cc_free_msg(msg); - } - - /* remove socket */ - osmo_cc_close_socket(&ep->os); - - memset(ep, 0, sizeof(*ep)); -} - -/* create new call instance */ -osmo_cc_call_t *osmo_cc_call_new(osmo_cc_endpoint_t *ep) -{ - return call_new(ep, osmo_cc_new_callref()); -} - -/* destroy call instance */ -void osmo_cc_call_delete(osmo_cc_call_t *call) -{ - call_delete(call); -} - -/* check valid IP and return address type (protocol) */ -enum osmo_cc_session_addrtype osmo_cc_address_type(const char *address) -{ - struct sockaddr_storage sa; - int rc; - - rc = inet_pton(AF_INET, address, &sa); - if (rc > 0) - return osmo_cc_session_addrtype_ipv4; - rc = inet_pton(AF_INET6, address, &sa); - if (rc > 0) - return osmo_cc_session_addrtype_ipv6; - - return osmo_cc_session_addrtype_unknown; -} - -/* get host from address */ -const char *osmo_cc_host_of_address(const char *address) -{ - static char host[256]; - char *p; - - if (strlen(address) >= sizeof(host)) { - PDEBUG(DCC, DEBUG_ERROR, "String way too long!\n"); - return NULL; - } - - if (address[0] == '[' && (p = strchr(address, ']'))) { - memcpy(host, address + 1, p - address - 1); - host[p - address - 1] = '\0'; - return host; - } - - strcpy(host, address); - if ((p = strchr(host, ':'))) - *p = '\0'; - - return host; -} - -/* get port from address */ -const char *osmo_cc_port_of_address(const char *address) -{ - const char *p; - int i; - - if (address[0] == '[' && (p = strchr(address, ']'))) - address = p + 1; - - if (!(p = strchr(address, ':'))) - return NULL; - p++; - - /* check for zero */ - if (p[0] == '0') - return NULL; - - /* check for digits */ - for (i = 0; i < (int)strlen(p); i++) { - if (p[i] < '0' || p[i] > '9') - return NULL; - } - - /* check for magnitude */ - if (atoi(p) > 65535) - return NULL; - - return p; -} - diff --git a/src/libosmocc/endpoint.h b/src/libosmocc/endpoint.h deleted file mode 100644 index 4425532..0000000 --- a/src/libosmocc/endpoint.h +++ /dev/null @@ -1,131 +0,0 @@ -#ifndef OSMO_CC_ENDPOINT_H -#define OSMO_CC_ENDPOINT_H - -#include "message.h" -#include "socket.h" -#include "cause.h" - -/* special osmo-cc error codes */ -#define OSMO_CC_RC_SEE_ERRNO -1 -#define OSMO_CC_RC_VERSION_MISMATCH 1 - -#define OSMO_CC_ATTACH_TIMER 2 - -/* call control state */ -enum osmo_cc_state { - OSMO_CC_STATE_IDLE = 0, - /* call states */ - OSMO_CC_STATE_INIT_OUT, /* outgoing CC-SETUP-REQ sent */ - OSMO_CC_STATE_INIT_IN, /* incoming CC-SETUP-IND received */ - OSMO_CC_STATE_OVERLAP_OUT, /* received CC-SETUP-ACK-IND on outgoing call */ - OSMO_CC_STATE_OVERLAP_IN, /* sent CC-SETUP-ACK-REQ on incoming call */ - OSMO_CC_STATE_PROCEEDING_OUT, /* received CC-PROC-IND on outgoing call */ - OSMO_CC_STATE_PROCEEDING_IN, /* sent CC-PROC-REQ on incoming call */ - OSMO_CC_STATE_ALERTING_OUT, /* received CC-ALERT-IND on outgoing call */ - OSMO_CC_STATE_ALERTING_IN, /* sent CC-ALERT-REQ on incoming call */ - OSMO_CC_STATE_CONNECTING_OUT, /* received CC-SETUP-CNF on outgoing call */ - OSMO_CC_STATE_CONNECTING_IN, /* sent CC-SETUP-RSP on incoming call */ - OSMO_CC_STATE_ACTIVE, /* received or sent CC-SETUP-COMPL-* */ - OSMO_CC_STATE_DISCONNECTING_OUT, /* sent CC-DISC-REQ */ - OSMO_CC_STATE_DISCONNECTING_IN, /* received CC-DISC-IND */ - OSMO_CC_STATE_DISC_COLLISION, /* received CC-DISC-IND after sending CC-DISC_REQ */ - OSMO_CC_STATE_RELEASING_OUT, /* sent CC-REL-REQ */ - /* attachment states */ - OSMO_CC_STATE_ATTACH_SENT, /* outgoing CC-ATT-REQ sent to socket */ - OSMO_CC_STATE_ATTACH_OUT, /* received CC-ATT-RSP on outgoing socket */ - OSMO_CC_STATE_ATTACH_WAIT, /* wait for outgoing attachment after failure */ - OSMO_CC_STATE_ATTACH_IN, /* incoming CC-ATT-REQ received from socket*/ -}; - -/* sample type */ -typedef int16_t osmo_cc_sample_t; - -#define OSMO_CC_SAMPLE_MILLIWATT 23170 /* peak sine at -3 dB of full sample range */ -#define OSMO_CC_SAMPLE_SPEECH 3672 /* peak speech at -16 dB of milliwatt */ -#define OSMO_CC_SAMPLE_MIN -32768 /* lowest level */ -#define OSMO_CC_SAMPLE_MAX 32767 /* highest level */ - -#include "session.h" - -struct osmo_cc_call; - -typedef struct osmo_cc_screen_list { - struct osmo_cc_screen_list *next; - int has_from_type; - uint8_t from_type; - int has_from_present; - uint8_t from_present; - char from[128]; - int has_to_type; - uint8_t to_type; - int has_to_present; - uint8_t to_present; - char to[128]; -} osmo_cc_screen_list_t; - -/* endpoint instance */ -typedef struct osmo_cc_endpoint { - struct osmo_cc_endpoint *next; - void *priv; - void (*ll_msg_cb)(struct osmo_cc_endpoint *ep, uint32_t callref, osmo_cc_msg_t *msg); - void (*ul_msg_cb)(struct osmo_cc_call *call, osmo_cc_msg_t *msg); - osmo_cc_msg_list_t *ll_queue; /* messages towards lower layer */ - struct osmo_cc_call *call_list; - const char *local_name; /* name of interface */ - const char *local_address; /* host+port */ - const char *local_host; - uint16_t local_port; - const char *remote_address; /* host+port */ - const char *remote_host; - uint16_t remote_port; - uint8_t serving_location; - osmo_cc_socket_t os; - osmo_cc_screen_list_t *screen_calling_in; - osmo_cc_screen_list_t *screen_called_in; - osmo_cc_screen_list_t *screen_calling_out; - osmo_cc_screen_list_t *screen_called_out; - int remote_auto; /* automatic remote address */ - struct timer attach_timer; /* timer to retry attachment */ - osmo_cc_session_config_t session_config; /* SDP/RTP default configuration */ -} osmo_cc_endpoint_t; - -extern osmo_cc_endpoint_t *osmo_cc_endpoint_list; - -/* call process */ -typedef struct osmo_cc_call { - struct osmo_cc_call *next; - osmo_cc_endpoint_t *ep; - enum osmo_cc_state state; - int lower_layer_released; /* when lower layer sent release, while upper layer gets a disconnect */ - int upper_layer_released; /* when upper layer sent release, while lower layer gets a disconnect */ - uint32_t callref; - osmo_cc_msg_list_t *sock_queue; /* messages from socket */ - const char *attached_host; /* host and port from remote peer that attached to us */ - uint16_t attached_port; - const char *attached_name; /* interface name from remote peer that attached to us */ -} osmo_cc_call_t; - -/* returns 0 if ok - * returns <0 for error as indicated - * returns >=1 to indicate osmo-cc error code - */ - -void osmo_cc_help(void); -int osmo_cc_new(osmo_cc_endpoint_t *ep, const char *version, const char *name, uint8_t serving_location, void (*ll_msg_cb)(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg), void (*ul_msg_cb)(osmo_cc_call_t *call, osmo_cc_msg_t *msg), void *priv, int argc, const char *argv[]); -void osmo_cc_delete(struct osmo_cc_endpoint *ep); -int osmo_cc_handle(void); -osmo_cc_call_t *osmo_cc_call_by_callref(osmo_cc_endpoint_t *ep, uint32_t callref); -osmo_cc_call_t *osmo_cc_get_attached_interface(osmo_cc_endpoint_t *ep, const char *interface); -void osmo_cc_ll_msg(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg); -void osmo_cc_ul_msg(void *priv, uint32_t callref, osmo_cc_msg_t *msg); -osmo_cc_call_t *osmo_cc_call_new(osmo_cc_endpoint_t *ep); -void osmo_cc_call_delete(struct osmo_cc_call *call); -enum osmo_cc_session_addrtype osmo_cc_address_type(const char *address); -const char *osmo_cc_host_of_address(const char *address); -const char *osmo_cc_port_of_address(const char *address); - -#include "rtp.h" -#include "sdp.h" -#include "screen.h" - -#endif /* OSMO_CC_ENDPOINT_H */ diff --git a/src/libosmocc/helper.c b/src/libosmocc/helper.c deleted file mode 100644 index 4eeee92..0000000 --- a/src/libosmocc/helper.c +++ /dev/null @@ -1,191 +0,0 @@ -/* Osmo-CC: helpers to simplify Osmo-CC usage - * - * (C) 2016 by Andreas Eversberg - * All Rights Reserved - * - * 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 3 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, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include "../libtimer/timer.h" -#include "../libdebug/debug.h" -#include "endpoint.h" -#include "helper.h" - -osmo_cc_session_t *osmo_cc_helper_audio_offer(osmo_cc_session_config_t *conf, void *priv, struct osmo_cc_helper_audio_codecs *codecs, void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len), osmo_cc_msg_t *msg, int debug) -{ - osmo_cc_session_t *session; - osmo_cc_session_media_t *media; - const char *sdp; - int i; - - session = osmo_cc_new_session(conf, priv, NULL, NULL, NULL, 0, 0, NULL, NULL, debug); - if (!session) - return NULL; - - media = osmo_cc_add_media(session, 0, 0, NULL, osmo_cc_session_media_type_audio, 0, osmo_cc_session_media_proto_rtp, 1, 1, receiver, debug); - osmo_cc_rtp_open(media); - - for (i = 0; codecs[i].payload_name; i++) - osmo_cc_add_codec(media, codecs[i].payload_name, codecs[i].payload_rate, codecs[i].payload_channels, codecs[i].encoder, codecs[i].decoder, debug); - - sdp = osmo_cc_session_send_offer(session); - osmo_cc_add_ie_sdp(msg, sdp); - - return session; -} - -const char *osmo_cc_helper_audio_accept(osmo_cc_session_config_t *conf, void *priv, struct osmo_cc_helper_audio_codecs *codecs, void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len), osmo_cc_msg_t *msg, osmo_cc_session_t **session_p, osmo_cc_session_codec_t **codec_p, int force_our_codec) -{ - char offer_sdp[65536]; - const char *accept_sdp; - osmo_cc_session_media_t *media, *selected_media; - osmo_cc_session_codec_t *codec, *selected_codec, *telephone_event; - int rc; - int i, selected_codec_i, telephone_event_i; - - if (*session_p) { - PDEBUG(DCC, DEBUG_ERROR, "Session already set, please fix!\n"); - abort(); - } - if (*codec_p) { - PDEBUG(DCC, DEBUG_ERROR, "Codec already set, please fix!\n"); - abort(); - } - - /* SDP IE */ - rc = osmo_cc_get_ie_sdp(msg, 0, offer_sdp, sizeof(offer_sdp)); - if (rc < 0) { - PDEBUG(DCC, DEBUG_ERROR, "There is no SDP included in setup request.\n"); - return NULL; - } - - *session_p = osmo_cc_session_receive_offer(conf, priv, offer_sdp); - if (!*session_p) { - PDEBUG(DCC, DEBUG_ERROR, "Failed to parse SDP.\n"); - return NULL; - } - - selected_media = NULL; - osmo_cc_session_for_each_media((*session_p)->media_list, media) { - /* only audio */ - if (media->description.type != osmo_cc_session_media_type_audio) - continue; - selected_codec_i = -1; - selected_codec = NULL; - telephone_event_i = -1; - telephone_event = NULL; - osmo_cc_session_for_each_codec(media->codec_list, codec) { - if (!!strcasecmp(codec->payload_name, "telephone-event")) { - for (i = 0; codecs[i].payload_name; i++) { - if (osmo_cc_session_if_codec(codec, codecs[i].payload_name, codecs[i].payload_rate, codecs[i].payload_channels)) { - /* select the first matchting codec or the one we prefer */ - if (selected_codec_i < 0 || i < selected_codec_i) { - selected_codec = codec; - selected_codec_i = i; - selected_media = media; - } - /* if we don't force our preferred codec, use the preferred one from the remote */ - if (!force_our_codec) - break; - } - } - } else { - /* special case: add telephone-event, if supported */ - for (i = 0; codecs[i].payload_name; i++) { - if (!!strcasecmp(codecs[i].payload_name, "telephone-event")) - continue; - telephone_event = codec; - telephone_event_i = i; - break; - } - } - } - /* codec is selected within this media, we are done */ - if (selected_codec) - break; - } - if (!selected_codec) { - PDEBUG(DCC, DEBUG_ERROR, "No codec found in setup message that we support.\n"); - osmo_cc_free_session(*session_p); - return NULL; - } - osmo_cc_session_accept_codec(selected_codec, codecs[selected_codec_i].encoder, codecs[selected_codec_i].decoder); - if (telephone_event) - osmo_cc_session_accept_codec(telephone_event, codecs[telephone_event_i].encoder, codecs[telephone_event_i].decoder); - osmo_cc_session_accept_media(selected_media, 0, 0, NULL, 1, 1, receiver); - osmo_cc_rtp_open(selected_media); - osmo_cc_rtp_connect(selected_media); - *codec_p = selected_codec; - - accept_sdp = osmo_cc_session_send_answer(*session_p); - if (!accept_sdp) { - osmo_cc_free_session(*session_p); - return NULL; - } - - return accept_sdp; -} - -int osmo_cc_helper_audio_negotiate(osmo_cc_msg_t *msg, osmo_cc_session_t **session_p, osmo_cc_session_codec_t **codec_p) -{ - char sdp[65536]; - osmo_cc_session_media_t *media; - int rc; - - if (!(*session_p)) { - PDEBUG(DCC, DEBUG_ERROR, "Session not set, please fix!\n"); - abort(); - } - - /* once done, just ignore further messages that reply to setup */ - if (*codec_p) - return 0; - - /* SDP IE */ - rc = osmo_cc_get_ie_sdp(msg, 0, sdp, sizeof(sdp)); - if (rc < 0) - return 0; // no reply in this message - - rc = osmo_cc_session_receive_answer(*session_p, sdp); - if (rc < 0) - return rc; - - osmo_cc_session_for_each_media((*session_p)->media_list, media) { - /* only audio */ - if (media->description.type != osmo_cc_session_media_type_audio) - continue; - /* select first codec, if one was accpeted */ - if (media->codec_list) - *codec_p = media->codec_list; - if (*codec_p) { - osmo_cc_rtp_connect(media); - /* no more media streams */ - break; - } - } - if (!(*codec_p)) { - PDEBUG(DCC, DEBUG_ERROR, "No codec found in setup reply message that we support.\n"); - return -EIO; - } - - return 0; -} - diff --git a/src/libosmocc/helper.h b/src/libosmocc/helper.h deleted file mode 100644 index 0d3585e..0000000 --- a/src/libosmocc/helper.h +++ /dev/null @@ -1,13 +0,0 @@ - -struct osmo_cc_helper_audio_codecs { - const char *payload_name; - uint32_t payload_rate; - int payload_channels; - void (*encoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); - void (*decoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); -}; - -osmo_cc_session_t *osmo_cc_helper_audio_offer(osmo_cc_session_config_t *conf, void *priv, struct osmo_cc_helper_audio_codecs *codecs, void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len), osmo_cc_msg_t *msg, int debug); -const char *osmo_cc_helper_audio_accept(osmo_cc_session_config_t *conf, void *priv, struct osmo_cc_helper_audio_codecs *codecs, void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len), osmo_cc_msg_t *msg, osmo_cc_session_t **session_p, osmo_cc_session_codec_t **codec_p, int force_our_codec); -int osmo_cc_helper_audio_negotiate(osmo_cc_msg_t *msg, osmo_cc_session_t **session_p, osmo_cc_session_codec_t **codec_p); - diff --git a/src/libosmocc/message.c b/src/libosmocc/message.c deleted file mode 100644 index ab66a9f..0000000 --- a/src/libosmocc/message.c +++ /dev/null @@ -1,1291 +0,0 @@ -/* Osmo-CC: Message handling - * - * (C) 2016 by Andreas Eversberg - * All Rights Reserved - * - * 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 3 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, see . - */ - -#include -#include -#include -#include -#include -#include "../libdebug/debug.h" -#include "message.h" - -#define _OSMO_CC_VALUE2NAME(array) { \ - if (value < 0 || (size_t)value >= (sizeof(array) / sizeof(array[0])) || array[value] == NULL) \ - return ""; \ - else \ - return array[value]; \ -} - -#define _OSMO_CC_NAME2VALUE(array) { \ - int value; \ - for (value = 0; (size_t)value < (sizeof(array) / sizeof(array[0])); value++) { \ - if (!strcasecmp(array[value], name)) \ - return value; \ - } \ - return -1; \ -} - -static const char *osmo_cc_msg_name[OSMO_CC_MSG_NUM] = { - [OSMO_CC_MSG_SETUP_REQ] = "CC-SETUP-REQ", - [OSMO_CC_MSG_SETUP_IND] = "CC-SETUP-IND", - [OSMO_CC_MSG_REJ_REQ] = "CC-REJ-REQ", - [OSMO_CC_MSG_REJ_IND] = "CC-REJ-IND", - [OSMO_CC_MSG_SETUP_ACK_REQ] = "CC-SETUP-ACK-REQ", - [OSMO_CC_MSG_SETUP_ACK_IND] = "CC-SETUP-ACK-IND", - [OSMO_CC_MSG_PROC_REQ] = "CC-PROC-REQ", - [OSMO_CC_MSG_PROC_IND] = "CC-PROC-IND", - [OSMO_CC_MSG_ALERT_REQ] = "CC-ALERT-REQ", - [OSMO_CC_MSG_ALERT_IND] = "CC-ALERT-IND", - [OSMO_CC_MSG_SETUP_RSP] = "CC-SETUP-RSP", - [OSMO_CC_MSG_SETUP_CNF] = "CC-SETUP-CNF", - [OSMO_CC_MSG_SETUP_COMP_REQ] = "CC-SETUP-COMP-REQ", - [OSMO_CC_MSG_SETUP_COMP_IND] = "CC-SETUP-COMP-IND", - [OSMO_CC_MSG_DISC_REQ] = "CC-DISC-REQ", - [OSMO_CC_MSG_DISC_IND] = "CC-DISC-IND", - [OSMO_CC_MSG_REL_REQ] = "CC-REL-REQ", - [OSMO_CC_MSG_REL_CNF] = "CC-REL-CNF", - [OSMO_CC_MSG_REL_IND] = "CC-REL-IND", - [OSMO_CC_MSG_PROGRESS_REQ] = "CC-PROGRESS-REQ", - [OSMO_CC_MSG_PROGRESS_IND] = "CC-PROGRESS-IND", - [OSMO_CC_MSG_NOTIFY_REQ] = "CC-NOTIFY-REQ", - [OSMO_CC_MSG_NOTIFY_IND] = "CC-NOTIFY-IND", - [OSMO_CC_MSG_INFO_REQ] = "CC-INFO-REQ", - [OSMO_CC_MSG_INFO_IND] = "CC-INFO-IND", - [OSMO_CC_MSG_ATTACH_REQ] = "CC-ATTACH-REQ", - [OSMO_CC_MSG_ATTACH_IND] = "CC-ATTACH-IND", - [OSMO_CC_MSG_ATTACH_RSP] = "CC-ATTACH-RSP", - [OSMO_CC_MSG_ATTACH_CNF] = "CC-ATTACH-CNF", -}; - -const char *osmo_cc_msg_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_msg_name) -int osmo_cc_msg_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_msg_name) - -static const char *osmo_cc_ie_name[OSMO_CC_IE_NUM] = { - [OSMO_CC_IE_CALLED] = "IE_CALLED", - [OSMO_CC_IE_CALLED_SUB] = "IE_CALLED_SUB", - [OSMO_CC_IE_CALLED_NAME] = "IE_CALLED_NAME", - [OSMO_CC_IE_CALLED_INTERFACE] = "IE_CALLED_INTERFACE", - [OSMO_CC_IE_DTMF] = "IE_DTMF", - [OSMO_CC_IE_KEYPAD] = "IE_KEYPAD", - [OSMO_CC_IE_COMPLETE] = "IE_COMPLETE", - [OSMO_CC_IE_CALLING] = "IE_CALLING", - [OSMO_CC_IE_CALLING_SUB] = "IE_CALLING_SUB", - [OSMO_CC_IE_CALLING_NAME] = "IE_CALLING_NAME", - [OSMO_CC_IE_CALLING_INTERFACE] = "IE_CALLING_INTERFACE", - [OSMO_CC_IE_CALLING_NETWORK] = "IE_CALLING_NETWORK", - [OSMO_CC_IE_REDIR] = "IE_REDIR", - [OSMO_CC_IE_PROGRESS] = "IE_PROGRESS", - [OSMO_CC_IE_NOTIFY] = "IE_NOTIFY", - [OSMO_CC_IE_DISPLAY] = "IE_DISPLAY", - [OSMO_CC_IE_CAUSE] = "IE_CAUSE", - [OSMO_CC_IE_BEARER] = "IE_BEARER", - [OSMO_CC_IE_SDP] = "IE_SDP", - [OSMO_CC_IE_SOCKET_ADDRESS] = "IE_SOCKET_ADDRESS", - [OSMO_CC_IE_PRIVATE] = "IE_PRIVATE", -}; - -const char *osmo_cc_ie_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_ie_name) -int osmo_cc_ie_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_ie_name) - -static const char *osmo_cc_type_name[OSMO_CC_TYPE_NUM] = { - [OSMO_CC_TYPE_UNKNOWN] = "unknown", - [OSMO_CC_TYPE_INTERNATIONAL] = "international", - [OSMO_CC_TYPE_NATIONAL] = "national", - [OSMO_CC_TYPE_NETWORK] = "network", - [OSMO_CC_TYPE_SUBSCRIBER] = "subscriber", - [OSMO_CC_TYPE_ABBREVIATED] = "abbreviated", - [OSMO_CC_TYPE_RESERVED] = "reserved", -}; - -const char *osmo_cc_type_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_type_name) -int osmo_cc_type_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_type_name) - -static const char *osmo_cc_plan_name[OSMO_CC_PLAN_NUM] = { - [OSMO_CC_PLAN_UNKNOWN] = "unknown", - [OSMO_CC_PLAN_TELEPHONY] = "telephony", - [OSMO_CC_PLAN_DATA] = "data", - [OSMO_CC_PLAN_TTY] = "tty", - [OSMO_CC_PLAN_NATIONAL_STANDARD] = "national standard", - [OSMO_CC_PLAN_PRIVATE] = "private", - [OSMO_CC_PLAN_RESERVED] = "reserved", -}; - -const char *osmo_cc_plan_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_plan_name) -int osmo_cc_plan_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_plan_name) - -static const char *osmo_cc_present_name[OSMO_CC_PRESENT_NUM] = { - [OSMO_CC_PRESENT_ALLOWED] = "allowed", - [OSMO_CC_PRESENT_RESTRICTED] = "restricted", - [OSMO_CC_PRESENT_NOT_AVAIL] = "not available", - [OSMO_CC_PRESENT_RESERVED] = "reserved", -}; - -const char *osmo_cc_present_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_present_name) -int osmo_cc_present_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_present_name) - -static const char *osmo_cc_screen_name[OSMO_CC_SCREEN_NUM] = { - [OSMO_CC_SCREEN_USER_UNSCREENED] = "unscreened", - [OSMO_CC_SCREEN_USER_VERIFIED_PASSED] = "user provided and passed", - [OSMO_CC_SCREEN_USER_VERIFIED_FAILED] = "user provided an failed", - [OSMO_CC_SCREEN_NETWORK] = "network provided", -}; - -const char *osmo_cc_screen_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_screen_name) -int osmo_cc_screen_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_screen_name) - -static const char *osmo_cc_redir_reason_name[OSMO_CC_REDIR_REASON_NUM] = { - [OSMO_CC_REDIR_REASON_UNKNOWN] = "unknown", - [OSMO_CC_REDIR_REASON_CFB] = "call forward busy", - [OSMO_CC_REDIR_REASON_CFNR] = "call forward no response", - [OSMO_CC_REDIR_REASON_CD] = "call deflect", - [OSMO_CC_REDIR_REASON_CF_OUTOFORDER] = "call forward out of order", - [OSMO_CC_REDIR_REASON_CF_BY_DTE] = "call froward by dte", - [OSMO_CC_REDIR_REASON_CFU] = "call forward unconditional", -}; - -const char *osmo_cc_redir_reason_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_redir_reason_name) -int osmo_cc_redir_reason_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_redir_reason_name) - -static const char *osmo_cc_notify_name[OSMO_CC_NOTIFY_NUM] = { - [OSMO_CC_NOTIFY_USER_SUSPENDED] = "user suspended", - [OSMO_CC_NOTIFY_USER_RESUMED] = "user resumed", - [OSMO_CC_NOTIFY_BEARER_SERVICE_CHANGE] = "bearer service change", - [OSMO_CC_NOTIFY_CALL_COMPLETION_DELAY] = "call completion delay", - [OSMO_CC_NOTIFY_CONFERENCE_ESTABLISHED] = "conference established", - [OSMO_CC_NOTIFY_CONFERENCE_DISCONNECTED] = "conference disconnected", - [OSMO_CC_NOTIFY_OTHER_PARTY_ADDED] = "ohter party added", - [OSMO_CC_NOTIFY_ISOLATED] = "isolated", - [OSMO_CC_NOTIFY_REATTACHED] = "reattached", - [OSMO_CC_NOTIFY_OTHER_PARTY_ISOLATED] = "ohter party isolated", - [OSMO_CC_NOTIFY_OTHER_PARTY_REATTACHED] = "ohter party reattached", - [OSMO_CC_NOTIFY_OTHER_PARTY_SPLIT] = "other party split", - [OSMO_CC_NOTIFY_OTHER_PARTY_DISCONNECTED] = "other party disconnected", - [OSMO_CC_NOTIFY_CONFERENCE_FLOATING] = "confernce floating", - [OSMO_CC_NOTIFY_CONFERENCE_DISC_PREEMPT] = "confernce disconnect preemption", - [OSMO_CC_NOTIFY_CONFERENCE_FLOATING_SUP] = "conference floating sup", - [OSMO_CC_NOTIFY_CALL_IS_A_WAITING_CALL] = "call is a waiting call", - [OSMO_CC_NOTIFY_DIVERSION_ACTIVATED] = "diversion activated", - [OSMO_CC_NOTIFY_RESERVED_CT_1] = "reserved CT 1", - [OSMO_CC_NOTIFY_RESERVED_CT_2] = "reserved CT 2", - [OSMO_CC_NOTIFY_REVERSE_CHARGING] = "reverse charging", - [OSMO_CC_NOTIFY_REMOTE_HOLD] = "remote hold", - [OSMO_CC_NOTIFY_REMOTE_RETRIEVAL] = "remote retrieval", - [OSMO_CC_NOTIFY_CALL_IS_DIVERTING] = "call is diverting", -}; - -const char *osmo_cc_notify_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_notify_name) -int osmo_cc_notify_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_notify_name) - -static const char *osmo_cc_coding_name[OSMO_CC_CODING_NUM] = { - [OSMO_CC_CODING_ITU_T] = "ITU-T", - [OSMO_CC_CODING_ISO_IEC] = "ISO/IEC", - [OSMO_CC_CODING_NATIONAL] = "national", - [OSMO_CC_CODING_STANDARD_SPECIFIC] = "standard specific", -}; - -const char *osmo_cc_coding_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_coding_name) -int osmo_cc_coding_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_coding_name) - -static const char *osmo_cc_isdn_cause_name[OSMO_CC_ISDN_CAUSE_NUM] = { - [0] = "unset", - [OSMO_CC_ISDN_CAUSE_UNASSIGNED_NR] = "unsassigned number", - [OSMO_CC_ISDN_CAUSE_NO_ROUTE_TRANSIT] = "no route to transit network", - [OSMO_CC_ISDN_CAUSE_NO_ROUTE] = "no route", - [OSMO_CC_ISDN_CAUSE_CHAN_UNACCEPT] = "channel unacceptable", - [OSMO_CC_ISDN_CAUSE_OP_DET_BARRING] = "detected barring", - [OSMO_CC_ISDN_CAUSE_NORM_CALL_CLEAR] = "normal call clearing", - [OSMO_CC_ISDN_CAUSE_USER_BUSY] = "user busy", - [OSMO_CC_ISDN_CAUSE_USER_NOTRESPOND] = "user not responding", - [OSMO_CC_ISDN_CAUSE_USER_ALERTING_NA] = "user does not answer", - [OSMO_CC_ISDN_CAUSE_CALL_REJECTED] = "call rejected", - [OSMO_CC_ISDN_CAUSE_NUMBER_CHANGED] = "number changed", - [OSMO_CC_ISDN_CAUSE_PRE_EMPTION] = "pre-emption", - [OSMO_CC_ISDN_CAUSE_NONSE_USER_CLR] = "non-selected user clearing", - [OSMO_CC_ISDN_CAUSE_DEST_OOO] = "destination out-of-order", - [OSMO_CC_ISDN_CAUSE_INV_NR_FORMAT] = "invalid number format", - [OSMO_CC_ISDN_CAUSE_FACILITY_REJ] = "facility rejected", - [OSMO_CC_ISDN_CAUSE_RESP_STATUS_INQ] = "response to status enquiery", - [OSMO_CC_ISDN_CAUSE_NORMAL_UNSPEC] = "normal, uspecified", - [OSMO_CC_ISDN_CAUSE_NO_CIRCUIT_CHAN] = "no circuit/channel available", - [OSMO_CC_ISDN_CAUSE_NETWORK_OOO] = "network out of order", - [OSMO_CC_ISDN_CAUSE_TEMP_FAILURE] = "temporary failure", - [OSMO_CC_ISDN_CAUSE_SWITCH_CONG] = "switching equipment congested", - [OSMO_CC_ISDN_CAUSE_ACC_INF_DISCARD] = "access information discarded", - [OSMO_CC_ISDN_CAUSE_REQ_CHAN_UNAVAIL] = "requested circuit/channel unavailable", - [OSMO_CC_ISDN_CAUSE_RESOURCE_UNAVAIL] = "resource unavailable", - [OSMO_CC_ISDN_CAUSE_QOS_UNAVAIL] = "quality of service unavailable", - [OSMO_CC_ISDN_CAUSE_REQ_FAC_NOT_SUBSC] = "requested facility not subscribed", - [OSMO_CC_ISDN_CAUSE_INC_BARRED_CUG] = "inc barred in closed user group", - [OSMO_CC_ISDN_CAUSE_BEARER_CAP_UNAUTH] = "bearer capability unauthorized", - [OSMO_CC_ISDN_CAUSE_BEARER_CA_UNAVAIL] = "bearer capability not available", - [OSMO_CC_ISDN_CAUSE_SERV_OPT_UNAVAIL] = "service or option not available", - [OSMO_CC_ISDN_CAUSE_BEARERSERV_UNIMPL] = "bearer service unimplemented", - [OSMO_CC_ISDN_CAUSE_ACM_GE_ACM_MAX] = "acm ge ach max", - [OSMO_CC_ISDN_CAUSE_REQ_FAC_NOTIMPL] = "requrested facility not implemented", - [OSMO_CC_ISDN_CAUSE_RESTR_BCAP_AVAIL] = "restricted bearer capabilitey available", - [OSMO_CC_ISDN_CAUSE_SERV_OPT_UNIMPL] = "service or option unimplemented", - [OSMO_CC_ISDN_CAUSE_INVAL_CALLREF] = "invalid call reference", - [OSMO_CC_ISDN_CAUSE_USER_NOT_IN_CUG] = "user not in closed user group", - [OSMO_CC_ISDN_CAUSE_INCOMPAT_DEST] = "incompatible destination", - [OSMO_CC_ISDN_CAUSE_INVAL_TRANS_NET] = "invalid transit network", - [OSMO_CC_ISDN_CAUSE_SEMANTIC_INCORR] = "semantically incorrect", - [OSMO_CC_ISDN_CAUSE_INVAL_MAND_INF] = "invalid mandatory information", - [OSMO_CC_ISDN_CAUSE_MSGTYPE_NOTEXIST] = "message type does not exist", - [OSMO_CC_ISDN_CAUSE_MSGTYPE_INCOMPAT] = "message type incompatible", - [OSMO_CC_ISDN_CAUSE_IE_NOTEXIST] = "informaton element does not exits", - [OSMO_CC_ISDN_CAUSE_COND_IE_ERR] = "conditional information element error", - [OSMO_CC_ISDN_CAUSE_MSG_INCOMP_STATE] = "message at incompatlible state", - [OSMO_CC_ISDN_CAUSE_RECOVERY_TIMER] = "recovery on time expiery", - [OSMO_CC_ISDN_CAUSE_PROTO_ERR] = "protocol error", - [OSMO_CC_ISDN_CAUSE_INTERWORKING] = "interworking, unspecified", -}; - -const char *osmo_cc_isdn_cause_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_isdn_cause_name) -int osmo_cc_isdn_cause_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_isdn_cause_name) - -static const char *osmo_cc_location_name[OSMO_CC_LOCATION_NUM] = { - [OSMO_CC_LOCATION_USER] = "user", - [OSMO_CC_LOCATION_PRIV_SERV_LOC_USER] = "private network serving local user", - [OSMO_CC_LOCATION_PUB_SERV_LOC_USER] = "public network serving local user", - [OSMO_CC_LOCATION_TRANSIT] = "transit network", - [OSMO_CC_LOCATION_PUB_SERV_REM_USER] = "public network serving remote user", - [OSMO_CC_LOCATION_PRIV_SERV_REM_USER] = "private network serving remote user", - [OSMO_CC_LOCATION_BEYOND_INTERWORKING] = "beyond interworking", -}; - -const char *osmo_cc_location_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_location_name) -int osmo_cc_location_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_location_name) - -static const char *osmo_cc_progress_name[OSMO_CC_PROGRESS_NUM] = { - [OSMO_CC_PROGRESS_NOT_END_TO_END_ISDN] = "not end-to-end ISDN", - [OSMO_CC_PROGRESS_DEST_NOT_ISDN] = "destination not ISDN", - [OSMO_CC_PROGRESS_ORIG_NOT_ISDN] = "originator not ISDN", - [OSMO_CC_PROGRESS_RETURN_TO_ISDN] = "return to ISDN", - [OSMO_CC_PROGRESS_INTERWORKING] = "interworking", - [OSMO_CC_PROGRESS_INBAND_INFO_AVAILABLE] = "inmand information available (audio)", -}; - -const char *osmo_cc_progress_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_progress_name) -int osmo_cc_progress_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_progress_name) - -static const char *osmo_cc_capability_name[OSMO_CC_CAPABILITY_NUM] = { - [OSMO_CC_CAPABILITY_SPEECH] = "speech", - [OSMO_CC_CAPABILITY_DATA] = "data", - [OSMO_CC_CAPABILITY_DATA_RESTRICTED] = "data restricted", - [OSMO_CC_CAPABILITY_AUDIO] = "audio", - [OSMO_CC_CAPABILITY_DATA_WITH_TONES] = "data with tones", - [OSMO_CC_CAPABILITY_VIDEO] = "video", -}; - -const char *osmo_cc_capability_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_capability_name) -int osmo_cc_capability_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_capability_name) - -static const char *osmo_cc_mode_name[OSMO_CC_MODE_NUM] = { - [OSMO_CC_MODE_CIRCUIT] = "circuit", - [OSMO_CC_MODE_PACKET] = "packet", -}; - -const char *osmo_cc_mode_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_mode_name) -int osmo_cc_mode_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_mode_name) - -static const char *osmo_cc_dtmf_mode_name[OSMO_CC_DTMF_MODE_NUM] = { - [OSMO_CC_DTMF_MODE_OFF] = "off", - [OSMO_CC_DTMF_MODE_ON] = "on", - [OSMO_CC_DTMF_MODE_DIGITS] = "digit", -}; - -const char *osmo_cc_dtmf_mode_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_dtmf_mode_name) -int osmo_cc_dtmf_mode_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_dtmf_mode_name) - -static const char *osmo_cc_socket_cause_name[OSMO_CC_SOCKET_CAUSE_NUM] = { - [0] = "unset", - [OSMO_CC_SOCKET_CAUSE_VERSION_MISMATCH] = "version mismatch", - [OSMO_CC_SOCKET_CAUSE_FAILED] = "socket failed", - [OSMO_CC_SOCKET_CAUSE_BROKEN_PIPE] = "broken pipe", - [OSMO_CC_SOCKET_CAUSE_TIMEOUT] = "keepalive timeout", -}; - -const char *osmo_cc_socket_cause_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_socket_cause_name) -int osmo_cc_socket_cause_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_socket_cause_name) - -static const char *osmo_cc_network_name[OSMO_CC_NETWORK_NUM] = { - [OSMO_CC_NETWORK_UNDEFINED] = "undefined", - [OSMO_CC_NETWORK_ALSA_NONE] = "alsa", - [OSMO_CC_NETWORK_POTS_NONE] = "pots", - [OSMO_CC_NETWORK_ISDN_NONE] = "isdn", - [OSMO_CC_NETWORK_SIP_NONE] = "sip", - [OSMO_CC_NETWORK_GSM_IMSI] = "gsm-imsi", - [OSMO_CC_NETWORK_GSM_IMEI] = "gsm-imei", - [OSMO_CC_NETWORK_WEB_NONE] = "web", - [OSMO_CC_NETWORK_DECT_NONE] = "decs", - [OSMO_CC_NETWORK_BLUETOOTH_NONE] = "bluetooth", - [OSMO_CC_NETWORK_SS5_NONE] = "ss5", - [OSMO_CC_NETWORK_ANETZ_NONE] = "anetz", - [OSMO_CC_NETWORK_BNETZ_MUENZ] = "bnetz", - [OSMO_CC_NETWORK_CNETZ_NONE] = "cnetz", - [OSMO_CC_NETWORK_NMT_NONE] = "nmt", - [OSMO_CC_NETWORK_R2000_NONE] = "radiocom2000", - [OSMO_CC_NETWORK_AMPS_ESN] = "amps", - [OSMO_CC_NETWORK_MTS_NONE] = "mts", - [OSMO_CC_NETWORK_IMTS_NONE] = "imts", - [OSMO_CC_NETWORK_EUROSIGNAL_NONE] = "eurosignal", - [OSMO_CC_NETWORK_JOLLYCOM_NONE] = "jollycom", - [OSMO_CC_NETWORK_MPT1327_PSTN] = "mpt1327-pstn", - [OSMO_CC_NETWORK_MPT1327_PBX] = "mpt1327-pbx", -}; - -const char *osmo_cc_network_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_network_name) -int osmo_cc_network_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_network_name) - -/* - * - */ - -static uint32_t new_callref = 0; - -uint32_t osmo_cc_new_callref(void) -{ - return (++new_callref); -} - -/* create message with maximum size */ -osmo_cc_msg_t *osmo_cc_new_msg(uint8_t msg_type) -{ - osmo_cc_msg_t *msg; - - /* allocate message */ - msg = calloc(1, sizeof(*msg) + 65535); - if (!msg) { - PDEBUG(DCC, DEBUG_ERROR, "No memory\n"); - abort(); - } - /* set message type and zero length */ - msg->type = msg_type; - msg->length_networkorder = htons(0); - - return msg; -} - -/* clone message */ -osmo_cc_msg_t *osmo_cc_clone_msg(osmo_cc_msg_t *msg) -{ - osmo_cc_msg_t *new_msg; - - new_msg = osmo_cc_new_msg(msg->type); - new_msg->length_networkorder = msg->length_networkorder; - memcpy(new_msg->data, msg->data, ntohs(msg->length_networkorder)); - - return new_msg; -} - -osmo_cc_msg_t *osmo_cc_msg_list_dequeue(osmo_cc_msg_list_t **mlp, uint32_t *callref_p) -{ - osmo_cc_msg_list_t *ml; - osmo_cc_msg_t *msg; - - ml = *mlp; - msg = ml->msg; - if (callref_p) - *callref_p = ml->callref; - *mlp = ml->next; - free(ml); - - return msg; -} - -osmo_cc_msg_list_t *osmo_cc_msg_list_enqueue(osmo_cc_msg_list_t **mlp, osmo_cc_msg_t *msg, uint32_t callref) -{ - osmo_cc_msg_list_t *ml; - - ml = calloc(1, sizeof(*ml)); - ml->msg = msg; - ml->callref = callref; - while (*mlp) - mlp = &((*mlp)->next); - *mlp = ml; - - return ml; -} - -/* destroy message */ -void osmo_cc_free_msg(osmo_cc_msg_t *msg) -{ - free(msg); -} - -void osmo_cc_debug_ie(osmo_cc_msg_t *msg, int level) -{ - uint16_t msg_len, len; - uint8_t *p; - osmo_cc_ie_t *ie; - int rc; - int ie_repeat[256]; - uint8_t type, plan, present, screen, coding, capability, mode, progress, reason, duration_ms, pause_ms, dtmf_mode, location, notify, isdn_cause, socket_cause; - uint16_t sip_cause; - uint32_t unique; - char string[65536]; - int i; - - memset(ie_repeat, 0, sizeof(ie_repeat)); - - msg_len = ntohs(msg->length_networkorder); - p = msg->data; - - while (msg_len) { - ie = (osmo_cc_ie_t *)p; - /* check for minimum IE length */ - if (msg_len < sizeof(*ie)) { - PDEBUG(DCC, level, "****** Rest of message is too short for an IE: value=%s\n", debug_hex(p, msg_len)); - return; - } - /* get actual IE length */ - len = ntohs(ie->length_networkorder); - /* check if IE length does not exceed message */ - if (msg_len < sizeof(*ie) + len) { - PDEBUG(DCC, level, "****** IE: type=0x%02x length=%d would exceed the rest length of message (%d bytes left)\n", ie->type, len, msg_len - (int)sizeof(*ie)); - return; - } - switch (ie->type) { - case OSMO_CC_IE_CALLED: - rc = osmo_cc_get_ie_called(msg, ie_repeat[ie->type], &type, &plan, string, sizeof(string)); - if (rc < 0) - break; - PDEBUG(DCC, level, " %s type=%d(%s) plan=%d(%s) number='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_type_value2name(type), plan, osmo_cc_plan_value2name(plan), string); - break; - case OSMO_CC_IE_CALLED_SUB: - rc = osmo_cc_get_ie_called_sub(msg, ie_repeat[ie->type], &type, string, sizeof(string)); - if (rc < 0) - break; - PDEBUG(DCC, level, " %s type=%d(%s) number='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_type_value2name(type), string); - break; - case OSMO_CC_IE_CALLED_NAME: - rc = osmo_cc_get_ie_called_name(msg, ie_repeat[ie->type], string, sizeof(string)); - if (rc < 0) - break; - PDEBUG(DCC, level, " %s name='%s'\n", osmo_cc_ie_value2name(ie->type), string); - break; - case OSMO_CC_IE_CALLED_INTERFACE: - rc = osmo_cc_get_ie_called_interface(msg, ie_repeat[ie->type], string, sizeof(string)); - if (rc < 0) - break; - PDEBUG(DCC, level, " %s name='%s'\n", osmo_cc_ie_value2name(ie->type), string); - break; - case OSMO_CC_IE_COMPLETE: - rc = osmo_cc_get_ie_complete(msg, ie_repeat[ie->type]); - if (rc < 0) - break; - PDEBUG(DCC, level, " %s\n", osmo_cc_ie_value2name(ie->type)); - break; - case OSMO_CC_IE_CALLING: - rc = osmo_cc_get_ie_calling(msg, ie_repeat[ie->type], &type, &plan, &present, &screen, string, sizeof(string)); - if (rc < 0) - break; - PDEBUG(DCC, level, " %s type=%d(%s) plan=%d(%s), presentation=%d(%s), screening=%d(%s), number='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_type_value2name(type), plan, osmo_cc_plan_value2name(plan), present, osmo_cc_present_value2name(present), screen, osmo_cc_screen_value2name(screen), string); - break; - case OSMO_CC_IE_CALLING_SUB: - rc = osmo_cc_get_ie_calling_sub(msg, ie_repeat[ie->type], &type, string, sizeof(string)); - if (rc < 0) - break; - PDEBUG(DCC, level, " %s type=%d(%s) number='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_type_value2name(type), string); - break; - case OSMO_CC_IE_CALLING_NAME: - rc = osmo_cc_get_ie_calling_name(msg, ie_repeat[ie->type], string, sizeof(string)); - if (rc < 0) - break; - PDEBUG(DCC, level, " %s name='%s'\n", osmo_cc_ie_value2name(ie->type), string); - break; - case OSMO_CC_IE_CALLING_INTERFACE: - rc = osmo_cc_get_ie_calling_interface(msg, ie_repeat[ie->type], string, sizeof(string)); - if (rc < 0) - break; - PDEBUG(DCC, level, " %s name='%s'\n", osmo_cc_ie_value2name(ie->type), string); - break; - case OSMO_CC_IE_CALLING_NETWORK: - rc = osmo_cc_get_ie_calling_network(msg, ie_repeat[ie->type], &type, string, sizeof(string)); - if (rc < 0) - break; - PDEBUG(DCC, level, " %s type=%d(%s) id='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_network_value2name(type), string); - break; - case OSMO_CC_IE_BEARER: - rc = osmo_cc_get_ie_bearer(msg, ie_repeat[ie->type], &coding, &capability, &mode); - if (rc < 0) - break; - PDEBUG(DCC, level, " %s coding=%d(%s) capability=%d(%s) mode=%d(%s)\n", osmo_cc_ie_value2name(ie->type), coding, osmo_cc_coding_value2name(coding), capability, osmo_cc_capability_value2name(capability), mode, osmo_cc_mode_value2name(mode)); - break; - case OSMO_CC_IE_REDIR: - rc = osmo_cc_get_ie_redir(msg, ie_repeat[ie->type], &type, &plan, &present, &screen, &reason, string, sizeof(string)); - if (rc < 0) - break; - PDEBUG(DCC, level, " %s type=%d(%s) plan=%d(%s) presentation=%d(%s) screening=%d(%s) reason=%d(%s) number='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_type_value2name(type), plan, osmo_cc_plan_value2name(plan), present, osmo_cc_present_value2name(present), screen, osmo_cc_screen_value2name(screen), reason, osmo_cc_redir_reason_value2name(reason), string); - break; - case OSMO_CC_IE_DTMF: - rc = osmo_cc_get_ie_dtmf(msg, ie_repeat[ie->type], &duration_ms, &pause_ms, &dtmf_mode, string, sizeof(string)); - if (rc < 0) - break; - PDEBUG(DCC, level, " %s duration=%dms pause=%dms mode=%d(%s)\n", osmo_cc_ie_value2name(ie->type), duration_ms, pause_ms, dtmf_mode, osmo_cc_dtmf_mode_value2name(dtmf_mode)); - break; - case OSMO_CC_IE_KEYPAD: - rc = osmo_cc_get_ie_keypad(msg, ie_repeat[ie->type], string, sizeof(string)); - if (rc < 0) - break; - PDEBUG(DCC, level, " %s digits='%s'\n", osmo_cc_ie_value2name(ie->type), string); - break; - case OSMO_CC_IE_PROGRESS: - rc = osmo_cc_get_ie_progress(msg, ie_repeat[ie->type], &coding, &location, &progress); - if (rc < 0) - break; - PDEBUG(DCC, level, " %s coding=%d(%s) location=%d(%s) progress=%d(%s)\n", osmo_cc_ie_value2name(ie->type), coding, osmo_cc_coding_value2name(coding), location, osmo_cc_location_value2name(location), progress, osmo_cc_progress_value2name(progress)); - break; - case OSMO_CC_IE_NOTIFY: - rc = osmo_cc_get_ie_notify(msg, ie_repeat[ie->type], ¬ify); - if (rc < 0) - break; - PDEBUG(DCC, level, " %s indicator=%d(%s)\n", osmo_cc_ie_value2name(ie->type), notify, osmo_cc_notify_value2name(notify)); - break; - case OSMO_CC_IE_CAUSE: - rc = osmo_cc_get_ie_cause(msg, ie_repeat[ie->type], &location, &isdn_cause, &sip_cause, &socket_cause); - if (rc < 0) - break; - PDEBUG(DCC, level, " %s location=%d(%s) isdn_cause=%d(%s) sip_cause=%d socket_cause=%d(%s)\n", osmo_cc_ie_value2name(ie->type), location, osmo_cc_location_value2name(location), isdn_cause, osmo_cc_isdn_cause_value2name(isdn_cause), sip_cause, socket_cause, osmo_cc_socket_cause_value2name(socket_cause)); - break; - case OSMO_CC_IE_DISPLAY: - rc = osmo_cc_get_ie_display(msg, ie_repeat[ie->type], string, sizeof(string)); - if (rc < 0) - break; - PDEBUG(DCC, level, " %s info='%s'\n", osmo_cc_ie_value2name(ie->type), string); - break; - case OSMO_CC_IE_SDP: - rc = osmo_cc_get_ie_sdp(msg, ie_repeat[ie->type], string, sizeof(string)); - if (rc < 0) - break; - for (i = 0; string[i]; i++) { - if (string[i] == '\r') - string[i] = '\\'; - if (string[i] == '\n') - string[i] = 'n'; - } - PDEBUG(DCC, level, " %s payload=%s\n", osmo_cc_ie_value2name(ie->type), string); - break; - case OSMO_CC_IE_SOCKET_ADDRESS: - rc = osmo_cc_get_ie_socket_address(msg, ie_repeat[ie->type], string, sizeof(string)); - if (rc < 0) - break; - PDEBUG(DCC, level, " %s address='%s'\n", osmo_cc_ie_value2name(ie->type), string); - break; - case OSMO_CC_IE_PRIVATE: - rc = osmo_cc_get_ie_private(msg, ie_repeat[ie->type], &unique, (uint8_t *)string, sizeof(string)); - if (rc < 0) - break; - PDEBUG(DCC, level, " %s unique=%u=0x%08x private=%s\n", osmo_cc_ie_value2name(ie->type), unique, unique, debug_hex((uint8_t *)string, rc)); - break; - default: - PDEBUG(DCC, level, " %s type=0x%02x length=%d value=%s\n", osmo_cc_ie_value2name(ie->type), ie->type, len, debug_hex(ie->data, len)); - } - ie_repeat[ie->type]++; - p += sizeof(*ie) + len; - msg_len -= sizeof(*ie) + len; - } -} - -/* search and return information element - * we give the IE type we are searching for - * we also give the repetition, to find IE that is repeated - * the result is stored in *ie_data - * the return length is the length that exceeds the given ie_len - * if there is an error, a value < 0 is returned - */ -int osmo_cc_get_ie_struct(osmo_cc_msg_t *msg, uint8_t ie_type, int ie_repeat, int ie_len, const osmo_cc_ie_t **ie_struct) -{ - uint16_t msg_len, len; - uint8_t *p; - osmo_cc_ie_t *ie; - - msg_len = ntohs(msg->length_networkorder); - p = msg->data; - - while (msg_len) { - ie = (osmo_cc_ie_t *)p; - /* check for minimum IE length */ - if (msg_len < sizeof(*ie)) { - PDEBUG(DCC, DEBUG_ERROR, "MSG short read\n"); - osmo_cc_debug_ie(msg, DEBUG_ERROR); - return -EINVAL; - } - /* get actual IE length */ - len = ntohs(ie->length_networkorder); - /* check if IE length does not exceed message */ - if (msg_len < sizeof(*ie) + len) { - PDEBUG(DCC, DEBUG_ERROR, "MSG short read\n"); - osmo_cc_debug_ie(msg, DEBUG_ERROR); - return -EINVAL; - } - /* check if IE matches the one that is searched for */ - if (ie->type != ie_type) { - p += sizeof(*ie) + len; - msg_len -= sizeof(*ie) + len; - continue; - } - /* check if IE repetition exists */ - if (ie_repeat) { - --ie_repeat; - p += sizeof(*ie) + len; - msg_len -= sizeof(*ie) + len; - continue; - } - /* return IE and indicate how many bytes we have more than the given length*/ - if (ntohs(ie->length_networkorder) < ie_len) { - PDEBUG(DCC, DEBUG_ERROR, "IE 0x%02d has length of %d, but we expect it to have at least %d!\n", ie_type, ntohs(ie->length_networkorder), ie_len); - return -EINVAL; - } - *ie_struct = ie; - return ntohs(ie->length_networkorder) - ie_len; - } - - /* IE not found */ - return -EINVAL; -} - -/* as above, but return data of IE only */ -int osmo_cc_get_ie_data(osmo_cc_msg_t *msg, uint8_t ie_type, int ie_repeat, int ie_len, const void **ie_data) -{ - const osmo_cc_ie_t *ie; - int rc; - - rc = osmo_cc_get_ie_struct(msg, ie_type, ie_repeat, ie_len, &ie); - if (rc >= 0) - *ie_data = ie->data; - - return rc; -} - -/* as above, but return 1 if IE exists */ -int osmo_cc_has_ie(osmo_cc_msg_t *msg, uint8_t ie_type, int ie_repeat) -{ - const osmo_cc_ie_t *ie; - int rc; - - rc = osmo_cc_get_ie_struct(msg, ie_type, ie_repeat, 0, &ie); - if (rc >= 0) - return 1; - - return 0; -} - -/* remove IE from message */ -int osmo_cc_remove_ie(osmo_cc_msg_t *msg, uint8_t ie_type, int ie_repeat) -{ - const osmo_cc_ie_t *ie; - int rc; - int msg_len, before_ie, ie_size, after_ie; - - rc = osmo_cc_get_ie_struct(msg, ie_type, ie_repeat, 0, &ie); - if (rc < 0) - return rc; - - msg_len = ntohs(msg->length_networkorder); - before_ie = (void *)ie - (void *)msg->data; - ie_size = sizeof(*ie) + ntohs(ie->length_networkorder); - after_ie = msg_len - ie_size - before_ie; - if (after_ie) - memcpy(msg->data + before_ie, msg->data + before_ie + ie_size, after_ie); - msg->length_networkorder = htons(msg_len - ie_size); - - return 0; -} - -/* add information element - * the type is given by ie_type and length is given by ie_len - * the return value is a pointer to the data of the IE - */ -void *osmo_cc_add_ie(osmo_cc_msg_t *msg, uint8_t ie_type, int ie_len) -{ - uint16_t msg_len; - int new_msg_len; - uint8_t *p; - osmo_cc_ie_t *ie; - - /* get pointer to first IE, if any */ - p = msg->data; - /* expand messasge */ - msg_len = ntohs(msg->length_networkorder); - new_msg_len = msg_len + sizeof(*ie) + ie_len; - if (new_msg_len > 65535) { - PDEBUG(DCC, DEBUG_ERROR, "MSG overflow\n"); - return NULL; - } - msg->length_networkorder = htons(new_msg_len); - /* go to end of (unexpanded) message */ - ie = (osmo_cc_ie_t *)(p + msg_len); - /* add ie */ - ie->type = ie_type; - ie->length_networkorder = htons(ie_len); - memset(ie->data, 0, ie_len); /* just in case there is something, but it shouldn't */ - - return ie->data; -} - -/* gets the information element's data that *iep points to and returns that ie. - * if *iep points to msg->data, the first IE's data is returned. (must be set before first call.) - * if *iep points to the end of the message, NULL is returned. - * if there is no next IE, *iep is set to point to the end of message. - */ -void *osmo_cc_msg_sep_ie(osmo_cc_msg_t *msg, void **iep, uint8_t *ie_type, uint16_t *ie_length) -{ - uint16_t msg_len; - osmo_cc_ie_t *ie; - - /* in case that *iep points to start of message, make it point to first IE */ - if (*iep == msg) - *iep = msg->data; - /* case IE */ - ie = *iep; - /* check if it is NULL */ - if (ie == NULL) - return NULL; - /* check if it points to the end of message or there is not at least an IE header */ - msg_len = ntohs(msg->length_networkorder); - if ((int)((uint8_t *)ie - msg->data) > (int)(msg_len - sizeof(*ie))) - return NULL; - /* increment iep and return IE */ - *ie_type = ie->type; - *ie_length = ntohs(ie->length_networkorder); - *iep = (uint8_t *)ie + sizeof(*ie) + *ie_length; - return ie->data; -} - -/* copy given block to given string with given size */ -static void _ie2string(char *string, size_t string_size, const char *ie_string, int ie_size) -{ - int copy_size; - - copy_size = string_size - 1; - if (ie_size < copy_size) - copy_size = ie_size; - memcpy(string, ie_string, copy_size); - string[copy_size] = '\0'; -} - -/* helper to encode called party number (dialing) */ -void osmo_cc_add_ie_called(osmo_cc_msg_t *msg, uint8_t type, uint8_t plan, const char *dialing) -{ - struct osmo_cc_ie_called *ie_called; - - ie_called = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLED, sizeof(*ie_called) + strlen(dialing)); - ie_called->type = type; - ie_called->plan = plan; - memcpy(ie_called->digits, dialing, strlen(dialing)); -} - -/* helper to decode called party number (dialing) */ -int osmo_cc_get_ie_called(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, uint8_t *plan, char *dialing, size_t dialing_size) -{ - struct osmo_cc_ie_called *ie_called; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLED, ie_repeat, sizeof(*ie_called), (const void **)&ie_called); - if (rc < 0) - return rc; - *type = ie_called->type; - *plan = ie_called->plan; - _ie2string(dialing, dialing_size, ie_called->digits, rc); - return rc; -} - -/* helper to encode called party sub address (dialing) */ -void osmo_cc_add_ie_called_sub(osmo_cc_msg_t *msg, uint8_t type, const char *dialing) -{ - struct osmo_cc_ie_called_sub *ie_called_sub; - - ie_called_sub = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLED_SUB, sizeof(*ie_called_sub) + strlen(dialing)); - ie_called_sub->type = type; - memcpy(ie_called_sub->digits, dialing, strlen(dialing)); -} - -/* helper to decode called party sub address (dialing) */ -int osmo_cc_get_ie_called_sub(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, char *dialing, size_t dialing_size) -{ - struct osmo_cc_ie_called_sub *ie_called_sub; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLED_SUB, ie_repeat, sizeof(*ie_called_sub), (const void **)&ie_called_sub); - if (rc < 0) - return rc; - *type = ie_called_sub->type; - _ie2string(dialing, dialing_size, ie_called_sub->digits, rc); - return rc; -} - -/* helper to encode called party name (dialing) */ -void osmo_cc_add_ie_called_name(osmo_cc_msg_t *msg, const char *name) -{ - struct osmo_cc_ie_called_name *ie_called_name; - - ie_called_name = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLED_NAME, sizeof(*ie_called_name) + strlen(name)); - memcpy(ie_called_name->name, name, strlen(name)); -} - -/* helper to decode called party name (dialing) */ -int osmo_cc_get_ie_called_name(osmo_cc_msg_t *msg, int ie_repeat, char *name, size_t name_size) -{ - struct osmo_cc_ie_called_name *ie_called_name; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLED_NAME, ie_repeat, sizeof(*ie_called_name), (const void **)&ie_called_name); - if (rc < 0) - return rc; - _ie2string(name, name_size, ie_called_name->name, rc); - return rc; -} - -/* helper to encode called interface name */ -void osmo_cc_add_ie_called_interface(osmo_cc_msg_t *msg, const char *interface) -{ - struct osmo_cc_ie_called_interface *ie_interface; - - ie_interface = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLED_INTERFACE, sizeof(*ie_interface) + strlen(interface)); - memcpy(ie_interface->name, interface, strlen(interface)); -} - -/* helper to decode called interface name */ -int osmo_cc_get_ie_called_interface(osmo_cc_msg_t *msg, int ie_repeat, char *interface, size_t interface_size) -{ - struct osmo_cc_ie_called_interface *ie_interface; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLED_INTERFACE, ie_repeat, sizeof(*ie_interface), (const void **)&ie_interface); - if (rc < 0) - return rc; - _ie2string(interface, interface_size, ie_interface->name, rc); - return rc; -} - -/* helper to encode complete IE */ -void osmo_cc_add_ie_complete(osmo_cc_msg_t *msg) -{ - osmo_cc_add_ie(msg, OSMO_CC_IE_COMPLETE, 0); -} - -/* helper to decode complete IE */ -int osmo_cc_get_ie_complete(osmo_cc_msg_t *msg, int ie_repeat) -{ - int rc; - void *ie_complete; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_COMPLETE, ie_repeat, 0, (const void **)&ie_complete); - return rc; -} - -/* helper to encode calling/connected party number (caller ID or connected ID) */ -void osmo_cc_add_ie_calling(osmo_cc_msg_t *msg, uint8_t type, uint8_t plan, uint8_t present, uint8_t screen, const char *callerid) -{ - struct osmo_cc_ie_calling *ie_calling; - - ie_calling = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLING, sizeof(*ie_calling) + strlen(callerid)); - ie_calling->type = type; - ie_calling->plan = plan; - ie_calling->present = present; - ie_calling->screen = screen; - memcpy(ie_calling->digits, callerid, strlen(callerid)); -} - -/* helper to decode calling/connected party number (caller ID or connected ID) */ -int osmo_cc_get_ie_calling(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, uint8_t *plan, uint8_t *present, uint8_t *screen, char *callerid, size_t callerid_size) -{ - struct osmo_cc_ie_calling *ie_calling; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLING, ie_repeat, sizeof(*ie_calling), (const void **)&ie_calling); - if (rc < 0) - return rc; - *type = ie_calling->type; - *plan = ie_calling->plan; - *present = ie_calling->present; - *screen = ie_calling->screen; - _ie2string(callerid, callerid_size, ie_calling->digits, rc); - return rc; -} - -/* helper to encode calling/connected sub address (caller ID or connected ID) */ -void osmo_cc_add_ie_calling_sub(osmo_cc_msg_t *msg, uint8_t type, const char *callerid) -{ - struct osmo_cc_ie_calling_sub *ie_calling_sub; - - ie_calling_sub = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLING_SUB, sizeof(*ie_calling_sub) + strlen(callerid)); - ie_calling_sub->type = type; - memcpy(ie_calling_sub->digits, callerid, strlen(callerid)); -} - -/* helper to decode calling/connected sub address (caller ID or connected ID) */ -int osmo_cc_get_ie_calling_sub(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, char *callerid, size_t callerid_size) -{ - struct osmo_cc_ie_calling_sub *ie_calling_sub; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLING_SUB, ie_repeat, sizeof(*ie_calling_sub), (const void **)&ie_calling_sub); - if (rc < 0) - return rc; - *type = ie_calling_sub->type; - _ie2string(callerid, callerid_size, ie_calling_sub->digits, rc); - return rc; -} - -/* helper to encode calling/connected name (caller ID or connected ID) */ -void osmo_cc_add_ie_calling_name(osmo_cc_msg_t *msg, const char *name) -{ - struct osmo_cc_ie_calling_name *ie_calling_name; - - ie_calling_name = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLING_NAME, sizeof(*ie_calling_name) + strlen(name)); - memcpy(ie_calling_name->name, name, strlen(name)); -} - -/* helper to decode calling/connected name address (caller ID or connected ID) */ -int osmo_cc_get_ie_calling_name(osmo_cc_msg_t *msg, int ie_repeat, char *name, size_t name_size) -{ - struct osmo_cc_ie_calling_name *ie_calling_name; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLING_NAME, ie_repeat, sizeof(*ie_calling_name), (const void **)&ie_calling_name); - if (rc < 0) - return rc; - _ie2string(name, name_size, ie_calling_name->name, rc); - return rc; -} - -/* helper to encode calling interface name */ -void osmo_cc_add_ie_calling_interface(osmo_cc_msg_t *msg, const char *interface) -{ - struct osmo_cc_ie_calling_interface *ie_interface; - - ie_interface = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLING_INTERFACE, sizeof(*ie_interface) + strlen(interface)); - memcpy(ie_interface->name, interface, strlen(interface)); -} - -/* helper to decode calling interface name */ -int osmo_cc_get_ie_calling_interface(osmo_cc_msg_t *msg, int ie_repeat, char *interface, size_t interface_size) -{ - struct osmo_cc_ie_calling_interface *ie_interface; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLING_INTERFACE, ie_repeat, sizeof(*ie_interface), (const void **)&ie_interface); - if (rc < 0) - return rc; - _ie2string(interface, interface_size, ie_interface->name, rc); - return rc; -} - -/* helper to encode network specific caller/connected ID */ -void osmo_cc_add_ie_calling_network(osmo_cc_msg_t *msg, uint8_t type, const char *networkid) -{ - struct osmo_cc_ie_network *ie_network; - - ie_network = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLING_NETWORK, sizeof(*ie_network) + strlen(networkid)); - ie_network->type = type; - memcpy(ie_network->id, networkid, strlen(networkid)); -} - -/* helper to encode network specific caller/connected ID */ -int osmo_cc_get_ie_calling_network(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, char *networkid, size_t networkid_size) -{ - struct osmo_cc_ie_network *ie_network; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLING_NETWORK, ie_repeat, sizeof(*ie_network), (const void **)&ie_network); - if (rc < 0) - return rc; - *type = ie_network->type; - _ie2string(networkid, networkid_size, ie_network->id, rc); - return rc; -} - -/* helper to encode bearer capability */ -void osmo_cc_add_ie_bearer(osmo_cc_msg_t *msg, uint8_t coding, uint8_t capability, uint8_t mode) -{ - struct osmo_cc_ie_bearer *ie_bearer; - - ie_bearer = osmo_cc_add_ie(msg, OSMO_CC_IE_BEARER, sizeof(*ie_bearer)); - ie_bearer->coding = coding; - ie_bearer->capability = capability; - ie_bearer->mode = mode; -} - -/* helper to decode bearer capability */ -int osmo_cc_get_ie_bearer(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *coding, uint8_t *capability, uint8_t *mode) -{ - struct osmo_cc_ie_bearer *ie_bearer; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_BEARER, ie_repeat, sizeof(*ie_bearer), (const void **)&ie_bearer); - if (rc < 0) - return rc; - *coding = ie_bearer->coding; - *capability = ie_bearer->capability; - *mode = ie_bearer->mode; - return rc; -} - -/* helper to encode redirection and redirecting number */ -void osmo_cc_add_ie_redir(osmo_cc_msg_t *msg, uint8_t type, uint8_t plan, uint8_t present, uint8_t screen, uint8_t redir_reason, const char *callerid) -{ - struct osmo_cc_ie_redir *ie_redir; - - ie_redir = osmo_cc_add_ie(msg, OSMO_CC_IE_REDIR, sizeof(*ie_redir) + strlen(callerid)); - ie_redir->type = type; - ie_redir->plan = plan; - ie_redir->present = present; - ie_redir->screen = screen; - ie_redir->redir_reason = redir_reason; - memcpy(ie_redir->digits, callerid, strlen(callerid)); -} - -/* helper to decode redirection and redirecting number */ -int osmo_cc_get_ie_redir(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, uint8_t *plan, uint8_t *present, uint8_t *screen, uint8_t *reason, char *callerid, size_t callerid_size) -{ - struct osmo_cc_ie_redir *ie_redir; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_REDIR, ie_repeat, sizeof(*ie_redir), (const void **)&ie_redir); - if (rc < 0) - return rc; - *type = ie_redir->type; - *plan = ie_redir->plan; - *present = ie_redir->present; - *screen = ie_redir->screen; - *reason = ie_redir->redir_reason; - _ie2string(callerid, callerid_size, ie_redir->digits, rc); - return rc; -} - -/* helper to encode DTMF tones */ -void osmo_cc_add_ie_dtmf(osmo_cc_msg_t *msg, uint8_t duration_ms, uint8_t pause_ms, uint8_t dtmf_mode, const char *digits) -{ - struct osmo_cc_ie_dtmf *ie_dtmf; - - ie_dtmf = osmo_cc_add_ie(msg, OSMO_CC_IE_DTMF, sizeof(*ie_dtmf) + strlen(digits)); - ie_dtmf->duration_ms = duration_ms; - ie_dtmf->pause_ms = pause_ms; - ie_dtmf->dtmf_mode = dtmf_mode; - memcpy(ie_dtmf->digits, digits, strlen(digits)); -} - -/* helper to decode DTMF tones */ -int osmo_cc_get_ie_dtmf(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *duration_ms, uint8_t *pause_ms, uint8_t *dtmf_mode, char *digits, size_t digits_size) -{ - struct osmo_cc_ie_dtmf *ie_dtmf; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_DTMF, ie_repeat, sizeof(*ie_dtmf), (const void **)&ie_dtmf); - if (rc < 0) - return rc; - *duration_ms = ie_dtmf->duration_ms; - *pause_ms = ie_dtmf->pause_ms; - *dtmf_mode = ie_dtmf->dtmf_mode; - _ie2string(digits, digits_size, ie_dtmf->digits, rc); - return rc; -} - -/* helper to encode keypad press */ -void osmo_cc_add_ie_keypad(osmo_cc_msg_t *msg, const char *digits) -{ - struct osmo_cc_ie_keypad *ie_keypad; - - ie_keypad = osmo_cc_add_ie(msg, OSMO_CC_IE_KEYPAD, sizeof(*ie_keypad) + strlen(digits)); - memcpy(ie_keypad->digits, digits, strlen(digits)); -} - -/* helper to decode keypad press */ -int osmo_cc_get_ie_keypad(osmo_cc_msg_t *msg, int ie_repeat, char *digits, size_t digits_size) -{ - struct osmo_cc_ie_keypad *ie_keypad; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_KEYPAD, ie_repeat, sizeof(*ie_keypad), (const void **)&ie_keypad); - if (rc < 0) - return rc; - _ie2string(digits, digits_size, ie_keypad->digits, rc); - return rc; -} - -/* helper to encode call progress information */ -void osmo_cc_add_ie_progress(osmo_cc_msg_t *msg, uint8_t coding, uint8_t location, uint8_t progress) -{ - struct osmo_cc_ie_progress *ie_progress; - - ie_progress = osmo_cc_add_ie(msg, OSMO_CC_IE_PROGRESS, sizeof(*ie_progress)); - ie_progress->coding = coding; - ie_progress->location = location; - ie_progress->progress = progress; -} - -/* helper to decode call progress information */ -int osmo_cc_get_ie_progress(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *coding, uint8_t *location, uint8_t *progress) -{ - struct osmo_cc_ie_progress *ie_progress; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_PROGRESS, ie_repeat, sizeof(*ie_progress), (const void **)&ie_progress); - if (rc < 0) - return rc; - *coding = ie_progress->coding; - *location = ie_progress->location; - *progress = ie_progress->progress; - return rc; -} - -/* helper to encode notification */ -void osmo_cc_add_ie_notify(osmo_cc_msg_t *msg, uint8_t notify) -{ - struct osmo_cc_ie_notify *ie_notify; - - ie_notify = osmo_cc_add_ie(msg, OSMO_CC_IE_NOTIFY, sizeof(*ie_notify)); - ie_notify->notify = notify; -} - -/* helper to decode notification */ -int osmo_cc_get_ie_notify(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *notify) -{ - struct osmo_cc_ie_notify *ie_notify; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_NOTIFY, ie_repeat, sizeof(*ie_notify), (const void **)&ie_notify); - if (rc < 0) - return rc; - *notify = ie_notify->notify; - return rc; -} - -/* helper to encode cause */ -void osmo_cc_add_ie_cause(osmo_cc_msg_t *msg, uint8_t location, uint8_t isdn_cause, uint16_t sip_cause, uint8_t socket_cause) -{ - struct osmo_cc_ie_cause *ie_cause; - - ie_cause = osmo_cc_add_ie(msg, OSMO_CC_IE_CAUSE, sizeof(*ie_cause)); - ie_cause->location = location; - ie_cause->isdn_cause = isdn_cause; - ie_cause->sip_cause_networkorder = htons(sip_cause); - ie_cause->socket_cause = socket_cause; -} - -/* helper to deccode cause */ -int osmo_cc_get_ie_cause(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *location, uint8_t *isdn_cause, uint16_t *sip_cause, uint8_t *socket_cause) -{ - struct osmo_cc_ie_cause *ie_cause; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CAUSE, ie_repeat, sizeof(*ie_cause), (const void **)&ie_cause); - if (rc < 0) - return rc; - *location = ie_cause->location; - *isdn_cause = ie_cause->isdn_cause; - *sip_cause = ntohs(ie_cause->sip_cause_networkorder); - *socket_cause = ie_cause->socket_cause; - return rc; -} - -/* helper to encode DISPLAY information */ -void osmo_cc_add_ie_display(osmo_cc_msg_t *msg, const char *text) -{ - struct osmo_cc_ie_display *ie_display; - - ie_display = osmo_cc_add_ie(msg, OSMO_CC_IE_DISPLAY, sizeof(*ie_display) + strlen(text)); - memcpy(ie_display->text, text, strlen(text)); -} - -/* helper to decode DISPLAY information */ -int osmo_cc_get_ie_display(osmo_cc_msg_t *msg, int ie_repeat, char *text, size_t text_size) -{ - struct osmo_cc_ie_display *ie_display; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_DISPLAY, ie_repeat, sizeof(*ie_display), (const void **)&ie_display); - if (rc < 0) - return rc; - _ie2string(text, text_size, ie_display->text, rc); - return rc; -} - -/* helper to encode SDP */ -void osmo_cc_add_ie_sdp(osmo_cc_msg_t *msg, const char *sdp) -{ - struct osmo_cc_ie_sdp *ie_sdp; - - ie_sdp = osmo_cc_add_ie(msg, OSMO_CC_IE_SDP, sizeof(*ie_sdp) + strlen(sdp)); - memcpy(ie_sdp->sdp, sdp, strlen(sdp)); -} - -/* helper to decode SDP */ -int osmo_cc_get_ie_sdp(osmo_cc_msg_t *msg, int ie_repeat, char *sdp, size_t sdp_size) -{ - struct osmo_cc_ie_sdp *ie_sdp; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_SDP, ie_repeat, sizeof(*ie_sdp), (const void **)&ie_sdp); - if (rc < 0) - return rc; - _ie2string(sdp, sdp_size, ie_sdp->sdp, rc); - return rc; -} - -/* helper to encode socket address */ -void osmo_cc_add_ie_socket_address(osmo_cc_msg_t *msg, const char *address) -{ - struct osmo_cc_ie_socket_address *ie_socket_address; - - ie_socket_address = osmo_cc_add_ie(msg, OSMO_CC_IE_SOCKET_ADDRESS, sizeof(*ie_socket_address) + strlen(address)); - memcpy(ie_socket_address->address, address, strlen(address)); -} - -/* helper to decode socket address */ -int osmo_cc_get_ie_socket_address(osmo_cc_msg_t *msg, int ie_repeat, char *address, size_t address_size) -{ - struct osmo_cc_ie_socket_address *ie_socket_address; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_SOCKET_ADDRESS, ie_repeat, sizeof(*ie_socket_address), (const void **)&ie_socket_address); - if (rc < 0) - return rc; - _ie2string(address, address_size, ie_socket_address->address, rc); - return rc; -} - -/* helper to encode private information element */ -void osmo_cc_add_ie_private(osmo_cc_msg_t *msg, uint32_t unique, const uint8_t *data, size_t data_size) -{ - struct osmo_cc_ie_private *ie_private; - - ie_private = osmo_cc_add_ie(msg, OSMO_CC_IE_PRIVATE, sizeof(*ie_private) + data_size); - ie_private->unique_networkorder = htonl(unique); - memcpy(ie_private->data, data, data_size); -} - -/* helper to decode private information element */ -int osmo_cc_get_ie_private(osmo_cc_msg_t *msg, int ie_repeat, uint32_t *unique, uint8_t *data, size_t data_size) -{ - struct osmo_cc_ie_private *ie_private; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_PRIVATE, ie_repeat, sizeof(*ie_private), (const void **)&ie_private); - if (rc < 0) - return rc; - *unique = ntohl(ie_private->unique_networkorder); - if (rc > (int)data_size) - rc = data_size; - memcpy(data, ie_private->data, rc); - return rc; -} - diff --git a/src/libosmocc/message.h b/src/libosmocc/message.h deleted file mode 100644 index 8f4d487..0000000 --- a/src/libosmocc/message.h +++ /dev/null @@ -1,510 +0,0 @@ -#ifndef OSMO_CC_MSG_H -#define OSMO_CC_MSG_H - -#define OSMO_CC_VERSION "OSMOCCv1" - -/* call control messages types */ -enum osmo_cc_msg_type { - OSMO_CC_MSG_SETUP_REQ = 0x00, - OSMO_CC_MSG_SETUP_IND = 0x01, - OSMO_CC_MSG_REJ_REQ = 0x10, - OSMO_CC_MSG_REJ_IND = 0x11, - OSMO_CC_MSG_SETUP_ACK_REQ = 0x20, - OSMO_CC_MSG_SETUP_ACK_IND = 0x21, - OSMO_CC_MSG_PROC_REQ = 0x30, - OSMO_CC_MSG_PROC_IND = 0x31, - OSMO_CC_MSG_ALERT_REQ = 0x40, - OSMO_CC_MSG_ALERT_IND = 0x41, - OSMO_CC_MSG_SETUP_RSP = 0x02, - OSMO_CC_MSG_SETUP_CNF = 0x03, - OSMO_CC_MSG_SETUP_COMP_REQ = 0x50, - OSMO_CC_MSG_SETUP_COMP_IND = 0x51, - OSMO_CC_MSG_DISC_REQ = 0x60, - OSMO_CC_MSG_DISC_IND = 0x61, - OSMO_CC_MSG_REL_REQ = 0x70, - OSMO_CC_MSG_REL_CNF = 0x73, - OSMO_CC_MSG_REL_IND = 0x71, - OSMO_CC_MSG_PROGRESS_REQ = 0x80, - OSMO_CC_MSG_PROGRESS_IND = 0x81, - OSMO_CC_MSG_NOTIFY_REQ = 0x84, - OSMO_CC_MSG_NOTIFY_IND = 0x85, - OSMO_CC_MSG_INFO_REQ = 0x88, - OSMO_CC_MSG_INFO_IND = 0x89, - OSMO_CC_MSG_UPDATE_REQ = 0x91, - OSMO_CC_MSG_UPDATE_CNF = 0x93, - OSMO_CC_MSG_ATTACH_REQ = 0xf8, - OSMO_CC_MSG_ATTACH_IND = 0xf9, - OSMO_CC_MSG_ATTACH_RSP = 0xfa, - OSMO_CC_MSG_ATTACH_CNF = 0xfb, - OSMO_CC_MSG_DUMMY_REQ = 0xfc, -}; -#define OSMO_CC_MSG_NUM 0x100 - -#define OSMO_CC_MSG_MASK 0x03, -#define OSMO_CC_MSG_REQ 0x00, -#define OSMO_CC_MSG_IND 0x01, -#define OSMO_CC_MSG_RSP 0x02, -#define OSMO_CC_MSG_CNF 0x03, - -const char *osmo_cc_msg_value2name(int value); -int osmo_cc_msg_name2value(const char *name); - -/* information elements */ -enum osmo_cc_ie_type { - OSMO_CC_IE_CALLED = 0x11, - OSMO_CC_IE_CALLED_SUB = 0x12, - OSMO_CC_IE_CALLED_NAME = 0x13, - OSMO_CC_IE_CALLED_INTERFACE = 0x14, - OSMO_CC_IE_DTMF = 0x1d, - OSMO_CC_IE_KEYPAD = 0x1e, - OSMO_CC_IE_COMPLETE = 0x1f, - OSMO_CC_IE_CALLING = 0x21, - OSMO_CC_IE_CALLING_SUB = 0x22, - OSMO_CC_IE_CALLING_NAME = 0x23, - OSMO_CC_IE_CALLING_INTERFACE = 0x24, - OSMO_CC_IE_CALLING_NETWORK = 0x2f, - OSMO_CC_IE_REDIR = 0x31, - OSMO_CC_IE_PROGRESS = 0x32, - OSMO_CC_IE_NOTIFY = 0x33, - OSMO_CC_IE_DISPLAY = 0x34, - OSMO_CC_IE_CAUSE = 0x41, - OSMO_CC_IE_BEARER = 0x51, - OSMO_CC_IE_SDP = 0x52, - OSMO_CC_IE_SOCKET_ADDRESS = 0x5e, - OSMO_CC_IE_PRIVATE = 0x5f, -}; -#define OSMO_CC_IE_NUM 0x100 - -const char *osmo_cc_ie_value2name(int value); -int osmo_cc_ie_name2value(const char *name); - -/* type of number, see ITU-T Rec. Q.931 */ -#define OSMO_CC_TYPE_UNKNOWN 0 -#define OSMO_CC_TYPE_INTERNATIONAL 1 -#define OSMO_CC_TYPE_NATIONAL 2 -#define OSMO_CC_TYPE_NETWORK 3 -#define OSMO_CC_TYPE_SUBSCRIBER 4 -#define OSMO_CC_TYPE_ABBREVIATED 5 -#define OSMO_CC_TYPE_RESERVED 7 -#define OSMO_CC_TYPE_NUM 8 - -const char *osmo_cc_type_value2name(int value); -int osmo_cc_type_name2value(const char *name); - -/* numbering plan, see ITU-T Rec. Q.931 */ -#define OSMO_CC_PLAN_UNKNOWN 0 -#define OSMO_CC_PLAN_TELEPHONY 1 -#define OSMO_CC_PLAN_DATA 3 -#define OSMO_CC_PLAN_TTY 4 -#define OSMO_CC_PLAN_NATIONAL_STANDARD 8 -#define OSMO_CC_PLAN_PRIVATE 9 -#define OSMO_CC_PLAN_RESERVED 15 -#define OSMO_CC_PLAN_NUM 16 - -const char *osmo_cc_plan_value2name(int value); -int osmo_cc_plan_name2value(const char *name); - -/* presentation indicator, see ITU-T Rec. Q.931 */ -#define OSMO_CC_PRESENT_ALLOWED 0 -#define OSMO_CC_PRESENT_RESTRICTED 1 -#define OSMO_CC_PRESENT_NOT_AVAIL 2 -#define OSMO_CC_PRESENT_RESERVED 3 -#define OSMO_CC_PRESENT_NUM 4 - -const char *osmo_cc_present_value2name(int value); -int osmo_cc_present_name2value(const char *name); - -/* screening indicator, see ITU-T Rec. Q.931 */ -#define OSMO_CC_SCREEN_USER_UNSCREENED 0 -#define OSMO_CC_SCREEN_USER_VERIFIED_PASSED 1 -#define OSMO_CC_SCREEN_USER_VERIFIED_FAILED 2 -#define OSMO_CC_SCREEN_NETWORK 3 -#define OSMO_CC_SCREEN_NUM 4 - -const char *osmo_cc_screen_value2name(int value); -int osmo_cc_screen_name2value(const char *name); - -/* screening indicator, see ITU-T Rec. Q.931 */ -#define OSMO_CC_REDIR_REASON_UNKNOWN 0 -#define OSMO_CC_REDIR_REASON_CFB 1 -#define OSMO_CC_REDIR_REASON_CFNR 2 -#define OSMO_CC_REDIR_REASON_CD 4 -#define OSMO_CC_REDIR_REASON_CF_OUTOFORDER 9 -#define OSMO_CC_REDIR_REASON_CF_BY_DTE 10 -#define OSMO_CC_REDIR_REASON_CFU 15 -#define OSMO_CC_REDIR_REASON_NUM 16 - -const char *osmo_cc_redir_reason_value2name(int value); -int osmo_cc_redir_reason_name2value(const char *name); - -/* notification indicator, see ITU-T Rec. Q.931 ff. */ -#define OSMO_CC_NOTIFY_USER_SUSPENDED 0x00 -#define OSMO_CC_NOTIFY_USER_RESUMED 0x01 -#define OSMO_CC_NOTIFY_BEARER_SERVICE_CHANGE 0x02 -#define OSMO_CC_NOTIFY_CALL_COMPLETION_DELAY 0x03 -#define OSMO_CC_NOTIFY_CONFERENCE_ESTABLISHED 0x42 -#define OSMO_CC_NOTIFY_CONFERENCE_DISCONNECTED 0x43 -#define OSMO_CC_NOTIFY_OTHER_PARTY_ADDED 0x44 -#define OSMO_CC_NOTIFY_ISOLATED 0x45 -#define OSMO_CC_NOTIFY_REATTACHED 0x46 -#define OSMO_CC_NOTIFY_OTHER_PARTY_ISOLATED 0x47 -#define OSMO_CC_NOTIFY_OTHER_PARTY_REATTACHED 0x48 -#define OSMO_CC_NOTIFY_OTHER_PARTY_SPLIT 0x49 -#define OSMO_CC_NOTIFY_OTHER_PARTY_DISCONNECTED 0x4a -#define OSMO_CC_NOTIFY_CONFERENCE_FLOATING 0x4b -#define OSMO_CC_NOTIFY_CONFERENCE_DISC_PREEMPT 0x4c /* disconnect preemted */ -#define OSMO_CC_NOTIFY_CONFERENCE_FLOATING_SUP 0x4f /* served user preemted */ -#define OSMO_CC_NOTIFY_CALL_IS_A_WAITING_CALL 0x60 -#define OSMO_CC_NOTIFY_DIVERSION_ACTIVATED 0x68 -#define OSMO_CC_NOTIFY_RESERVED_CT_1 0x69 -#define OSMO_CC_NOTIFY_RESERVED_CT_2 0x6a -#define OSMO_CC_NOTIFY_REVERSE_CHARGING 0x6e -#define OSMO_CC_NOTIFY_REMOTE_HOLD 0x79 -#define OSMO_CC_NOTIFY_REMOTE_RETRIEVAL 0x7a -#define OSMO_CC_NOTIFY_CALL_IS_DIVERTING 0x7b -#define OSMO_CC_NOTIFY_NUM 0x100 - -const char *osmo_cc_notify_value2name(int value); -int osmo_cc_notify_name2value(const char *name); - -/* coding standard, see ITU-T Rec. Q.931 */ -#define OSMO_CC_CODING_ITU_T 0 -#define OSMO_CC_CODING_ISO_IEC 1 -#define OSMO_CC_CODING_NATIONAL 2 -#define OSMO_CC_CODING_STANDARD_SPECIFIC 3 -#define OSMO_CC_CODING_NUM 4 - -const char *osmo_cc_coding_value2name(int value); -int osmo_cc_coding_name2value(const char *name); - -/* cause, see ITU-T Rec. Q.850 */ -#define OSMO_CC_ISDN_CAUSE_UNASSIGNED_NR 1 -#define OSMO_CC_ISDN_CAUSE_NO_ROUTE_TRANSIT 2 -#define OSMO_CC_ISDN_CAUSE_NO_ROUTE 3 -#define OSMO_CC_ISDN_CAUSE_CHAN_UNACCEPT 6 -#define OSMO_CC_ISDN_CAUSE_OP_DET_BARRING 8 -#define OSMO_CC_ISDN_CAUSE_NORM_CALL_CLEAR 16 -#define OSMO_CC_ISDN_CAUSE_USER_BUSY 17 -#define OSMO_CC_ISDN_CAUSE_USER_NOTRESPOND 18 -#define OSMO_CC_ISDN_CAUSE_USER_ALERTING_NA 19 -#define OSMO_CC_ISDN_CAUSE_CALL_REJECTED 21 -#define OSMO_CC_ISDN_CAUSE_NUMBER_CHANGED 22 -#define OSMO_CC_ISDN_CAUSE_PRE_EMPTION 25 -#define OSMO_CC_ISDN_CAUSE_NONSE_USER_CLR 26 -#define OSMO_CC_ISDN_CAUSE_DEST_OOO 27 -#define OSMO_CC_ISDN_CAUSE_INV_NR_FORMAT 28 -#define OSMO_CC_ISDN_CAUSE_FACILITY_REJ 29 -#define OSMO_CC_ISDN_CAUSE_RESP_STATUS_INQ 30 -#define OSMO_CC_ISDN_CAUSE_NORMAL_UNSPEC 31 -#define OSMO_CC_ISDN_CAUSE_NO_CIRCUIT_CHAN 34 -#define OSMO_CC_ISDN_CAUSE_NETWORK_OOO 38 -#define OSMO_CC_ISDN_CAUSE_TEMP_FAILURE 41 -#define OSMO_CC_ISDN_CAUSE_SWITCH_CONG 42 -#define OSMO_CC_ISDN_CAUSE_ACC_INF_DISCARD 43 -#define OSMO_CC_ISDN_CAUSE_REQ_CHAN_UNAVAIL 44 -#define OSMO_CC_ISDN_CAUSE_RESOURCE_UNAVAIL 47 -#define OSMO_CC_ISDN_CAUSE_QOS_UNAVAIL 49 -#define OSMO_CC_ISDN_CAUSE_REQ_FAC_NOT_SUBSC 50 -#define OSMO_CC_ISDN_CAUSE_INC_BARRED_CUG 55 -#define OSMO_CC_ISDN_CAUSE_BEARER_CAP_UNAUTH 57 -#define OSMO_CC_ISDN_CAUSE_BEARER_CA_UNAVAIL 58 -#define OSMO_CC_ISDN_CAUSE_SERV_OPT_UNAVAIL 63 -#define OSMO_CC_ISDN_CAUSE_BEARERSERV_UNIMPL 65 -#define OSMO_CC_ISDN_CAUSE_ACM_GE_ACM_MAX 68 -#define OSMO_CC_ISDN_CAUSE_REQ_FAC_NOTIMPL 69 -#define OSMO_CC_ISDN_CAUSE_RESTR_BCAP_AVAIL 70 -#define OSMO_CC_ISDN_CAUSE_SERV_OPT_UNIMPL 79 -#define OSMO_CC_ISDN_CAUSE_INVAL_CALLREF 81 -#define OSMO_CC_ISDN_CAUSE_USER_NOT_IN_CUG 87 -#define OSMO_CC_ISDN_CAUSE_INCOMPAT_DEST 88 -#define OSMO_CC_ISDN_CAUSE_INVAL_TRANS_NET 91 -#define OSMO_CC_ISDN_CAUSE_SEMANTIC_INCORR 95 -#define OSMO_CC_ISDN_CAUSE_INVAL_MAND_INF 96 -#define OSMO_CC_ISDN_CAUSE_MSGTYPE_NOTEXIST 97 -#define OSMO_CC_ISDN_CAUSE_MSGTYPE_INCOMPAT 98 -#define OSMO_CC_ISDN_CAUSE_IE_NOTEXIST 99 -#define OSMO_CC_ISDN_CAUSE_COND_IE_ERR 100 -#define OSMO_CC_ISDN_CAUSE_MSG_INCOMP_STATE 101 -#define OSMO_CC_ISDN_CAUSE_RECOVERY_TIMER 102 -#define OSMO_CC_ISDN_CAUSE_PROTO_ERR 111 -#define OSMO_CC_ISDN_CAUSE_INTERWORKING 127 -#define OSMO_CC_ISDN_CAUSE_NUM 128 - -const char *osmo_cc_isdn_cause_value2name(int value); -int osmo_cc_isdn_cause_name2value(const char *name); - -/* location, see ITU-T Rec. Q.931 */ -#define OSMO_CC_LOCATION_USER 0 -#define OSMO_CC_LOCATION_PRIV_SERV_LOC_USER 1 -#define OSMO_CC_LOCATION_PUB_SERV_LOC_USER 2 -#define OSMO_CC_LOCATION_TRANSIT 3 -#define OSMO_CC_LOCATION_PUB_SERV_REM_USER 4 -#define OSMO_CC_LOCATION_PRIV_SERV_REM_USER 5 -#define OSMO_CC_LOCATION_BEYOND_INTERWORKING 10 -#define OSMO_CC_LOCATION_NUM 16 - -const char *osmo_cc_location_value2name(int value); -int osmo_cc_location_name2value(const char *name); - -/* progress description, see ITU-T Rec. Q.931 */ -#define OSMO_CC_PROGRESS_NOT_END_TO_END_ISDN 1 -#define OSMO_CC_PROGRESS_DEST_NOT_ISDN 2 -#define OSMO_CC_PROGRESS_ORIG_NOT_ISDN 3 -#define OSMO_CC_PROGRESS_RETURN_TO_ISDN 4 -#define OSMO_CC_PROGRESS_INTERWORKING 5 -#define OSMO_CC_PROGRESS_INBAND_INFO_AVAILABLE 8 -#define OSMO_CC_PROGRESS_NUM 16 - -const char *osmo_cc_progress_value2name(int value); -int osmo_cc_progress_name2value(const char *name); - -/* information transfer capability, see ITU-T Rec. Q.931 */ -#define OSMO_CC_CAPABILITY_SPEECH 0 -#define OSMO_CC_CAPABILITY_DATA 8 -#define OSMO_CC_CAPABILITY_DATA_RESTRICTED 9 -#define OSMO_CC_CAPABILITY_AUDIO 16 -#define OSMO_CC_CAPABILITY_DATA_WITH_TONES 17 -#define OSMO_CC_CAPABILITY_VIDEO 24 -#define OSMO_CC_CAPABILITY_NUM 32 - -const char *osmo_cc_capability_value2name(int value); -int osmo_cc_capability_name2value(const char *name); - -/* transfer mode, see ITU-T Rec. Q.931 */ -#define OSMO_CC_MODE_CIRCUIT 0 -#define OSMO_CC_MODE_PACKET 2 -#define OSMO_CC_MODE_NUM 4 - -const char *osmo_cc_mode_value2name(int value); -int osmo_cc_mode_name2value(const char *name); - -#define OSMO_CC_DTMF_MODE_OFF 0 /* stop tone */ -#define OSMO_CC_DTMF_MODE_ON 1 /* start tone */ -#define OSMO_CC_DTMF_MODE_DIGITS 2 /* play tone(s) with duration and pauses */ -#define OSMO_CC_DTMF_MODE_NUM 3 - -const char *osmo_cc_dtmf_mode_value2name(int value); -int osmo_cc_dtmf_mode_name2value(const char *name); - -#define OSMO_CC_SOCKET_CAUSE_VERSION_MISMATCH 1 /* version mismatch */ -#define OSMO_CC_SOCKET_CAUSE_FAILED 2 /* connection failed */ -#define OSMO_CC_SOCKET_CAUSE_BROKEN_PIPE 3 /* connected socket failed */ -#define OSMO_CC_SOCKET_CAUSE_TIMEOUT 4 /* keepalive packets timeout */ -// if you add causes here, add them in process_cause.c also! -#define OSMO_CC_SOCKET_CAUSE_NUM 5 - -const char *osmo_cc_socket_cause_value2name(int value); -int osmo_cc_socket_cause_name2value(const char *name); - -/* network type (network IE) and meaning of 'id' */ -#define OSMO_CC_NETWORK_UNDEFINED 0x00 -#define OSMO_CC_NETWORK_ALSA_NONE 0x01 -#define OSMO_CC_NETWORK_POTS_NONE 0x02 -#define OSMO_CC_NETWORK_ISDN_NONE 0x03 -#define OSMO_CC_NETWORK_SIP_NONE 0x04 -#define OSMO_CC_NETWORK_GSM_IMSI 0x05 /* id has decimal IMSI */ -#define OSMO_CC_NETWORK_GSM_IMEI 0x06 /* id has decimal IMEI */ -#define OSMO_CC_NETWORK_WEB_NONE 0x07 -#define OSMO_CC_NETWORK_DECT_NONE 0x08 -#define OSMO_CC_NETWORK_BLUETOOTH_NONE 0x09 -#define OSMO_CC_NETWORK_SS5_NONE 0x0a -#define OSMO_CC_NETWORK_ANETZ_NONE 0x80 -#define OSMO_CC_NETWORK_BNETZ_MUENZ 0x81 /* id starts with 'M' */ -#define OSMO_CC_NETWORK_CNETZ_NONE 0x82 -#define OSMO_CC_NETWORK_NMT_NONE 0x83 /* id has decimal password */ -#define OSMO_CC_NETWORK_R2000_NONE 0x84 -#define OSMO_CC_NETWORK_AMPS_ESN 0x85 /* if has decimal ESN (TACS also) */ -#define OSMO_CC_NETWORK_MTS_NONE 0x86 -#define OSMO_CC_NETWORK_IMTS_NONE 0x87 -#define OSMO_CC_NETWORK_EUROSIGNAL_NONE 0x88 -#define OSMO_CC_NETWORK_JOLLYCOM_NONE 0x89 /* call from JollyCom... */ -#define OSMO_CC_NETWORK_MPT1327_PSTN 0x8a /* call from MPT1327 */ -#define OSMO_CC_NETWORK_MPT1327_PBX 0x8b /* id is selected PBX number */ -#define OSMO_CC_NETWORK_NUM 0x100 - -const char *osmo_cc_network_value2name(int value); -int osmo_cc_network_name2value(const char *name); - -typedef struct osmo_cc_msg { - uint8_t type; - uint16_t length_networkorder; - uint8_t data[0]; -} __attribute__((packed)) osmo_cc_msg_t; - -typedef struct osmo_cc_msg_list { - struct osmo_cc_msg_list *next; - struct osmo_cc_msg *msg; - uint32_t callref; - char host[128]; - uint16_t port; -} osmo_cc_msg_list_t; - -typedef struct osmo_cc_ie { - uint8_t type; - uint16_t length_networkorder; - uint8_t data[0]; -} __attribute__((packed)) osmo_cc_ie_t; - -struct osmo_cc_ie_called { - uint8_t type; - uint8_t plan; - char digits[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_called_sub { - uint8_t type; - char digits[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_called_name { - char name[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_called_interface { - char name[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_calling { - uint8_t type; - uint8_t plan; - uint8_t present; - uint8_t screen; - char digits[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_calling_sub { - uint8_t type; - char digits[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_calling_name { - char name[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_calling_interface { - char name[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_network { - uint8_t type; - char id[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_bearer { - uint8_t coding; - uint8_t capability; - uint8_t mode; -} __attribute__((packed)); - -struct osmo_cc_ie_redir { - uint8_t type; - uint8_t plan; - uint8_t present; - uint8_t screen; - uint8_t redir_reason; - char digits[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_dtmf { - uint8_t duration_ms; - uint8_t pause_ms; - uint8_t dtmf_mode; - char digits[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_keypad { - char digits[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_progress { - uint8_t coding; - uint8_t location; - uint8_t progress; -} __attribute__((packed)); - -struct osmo_cc_ie_notify { - uint8_t notify; -} __attribute__((packed)); - -struct osmo_cc_ie_cause { - uint8_t location; - uint8_t isdn_cause; - uint16_t sip_cause_networkorder; - uint8_t socket_cause; -} __attribute__((packed)); - -struct osmo_cc_ie_display { - char text[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_sdp { - char sdp[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_socket_address { - char address[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_private { - uint32_t unique_networkorder; - uint8_t data[0]; -} __attribute__((packed)); - -uint32_t osmo_cc_new_callref(void); -osmo_cc_msg_t *osmo_cc_new_msg(uint8_t msg_type); -osmo_cc_msg_t *osmo_cc_clone_msg(osmo_cc_msg_t *msg); -osmo_cc_msg_t *osmo_cc_msg_list_dequeue(osmo_cc_msg_list_t **mlp, uint32_t *callref_p); -osmo_cc_msg_list_t *osmo_cc_msg_list_enqueue(osmo_cc_msg_list_t **mlp, osmo_cc_msg_t *msg, uint32_t callref); -void osmo_cc_free_msg(osmo_cc_msg_t *msg); -void osmo_cc_debug_ie(osmo_cc_msg_t *msg, int level); -int osmo_cc_get_ie_struct(osmo_cc_msg_t *msg, uint8_t ie_type, int ie_repeat, int ie_len, const osmo_cc_ie_t **ie_struct); -int osmo_cc_get_ie_data(osmo_cc_msg_t *msg, uint8_t ie_type, int ie_repeat, int ie_len, const void **ie_data); -int osmo_cc_has_ie(osmo_cc_msg_t *msg, uint8_t ie_type, int ie_repeat); -int osmo_cc_remove_ie(osmo_cc_msg_t *msg, uint8_t ie_type, int ie_repeat); -void *osmo_cc_add_ie(osmo_cc_msg_t *msg, uint8_t ie_type, int ie_len); -void *osmo_cc_msg_sep_ie(osmo_cc_msg_t *msg, void **iep, uint8_t *ie_type, uint16_t *ie_length); - -void osmo_cc_add_ie_called(osmo_cc_msg_t *msg, uint8_t type, uint8_t plan, const char *dialing); -int osmo_cc_get_ie_called(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, uint8_t *plan, char *dialing, size_t dialing_size); -void osmo_cc_add_ie_called_sub(osmo_cc_msg_t *msg, uint8_t type, const char *dialing); -int osmo_cc_get_ie_called_sub(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, char *dialing, size_t dialing_size); -void osmo_cc_add_ie_called_name(osmo_cc_msg_t *msg, const char *name); -int osmo_cc_get_ie_called_name(osmo_cc_msg_t *msg, int ie_repeat, char *name, size_t name_size); -void osmo_cc_add_ie_called_interface(osmo_cc_msg_t *msg, const char *interface); -int osmo_cc_get_ie_called_interface(osmo_cc_msg_t *msg, int ie_repeat, char *interface, size_t interface_size); -void osmo_cc_add_ie_complete(osmo_cc_msg_t *msg); -int osmo_cc_get_ie_complete(osmo_cc_msg_t *msg, int ie_repeat); -void osmo_cc_add_ie_calling(osmo_cc_msg_t *msg, uint8_t type, uint8_t plan, uint8_t present, uint8_t screen, const char *callerid); -int osmo_cc_get_ie_calling(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, uint8_t *plan, uint8_t *present, uint8_t *screen, char *callerid, size_t callerid_size); -void osmo_cc_add_ie_calling_sub(osmo_cc_msg_t *msg, uint8_t type, const char *callerid); -int osmo_cc_get_ie_calling_sub(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, char *callerid, size_t callerid_size); -void osmo_cc_add_ie_calling_name(osmo_cc_msg_t *msg, const char *name); -int osmo_cc_get_ie_calling_name(osmo_cc_msg_t *msg, int ie_repeat, char *name, size_t name_size); -void osmo_cc_add_ie_calling_interface(osmo_cc_msg_t *msg, const char *interface); -int osmo_cc_get_ie_calling_interface(osmo_cc_msg_t *msg, int ie_repeat, char *interface, size_t interface_size); -void osmo_cc_add_ie_calling_network(osmo_cc_msg_t *msg, uint8_t type, const char *networkid); -int osmo_cc_get_ie_calling_network(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, char *networkid, size_t networkid_size); -void osmo_cc_add_ie_bearer(osmo_cc_msg_t *msg, uint8_t coding, uint8_t capability, uint8_t mode); -int osmo_cc_get_ie_bearer(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *coding, uint8_t *capability, uint8_t *mode); -void osmo_cc_add_ie_redir(osmo_cc_msg_t *msg, uint8_t type, uint8_t plan, uint8_t present, uint8_t screen, uint8_t redir_reason, const char *callerid); -int osmo_cc_get_ie_redir(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, uint8_t *plan, uint8_t *present, uint8_t *screen, uint8_t *reason, char *callerid, size_t callerid_size); -void osmo_cc_add_ie_dtmf(osmo_cc_msg_t *msg, uint8_t duration_ms, uint8_t pause_ms, uint8_t dtmf_mode, const char *digits); -int osmo_cc_get_ie_dtmf(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *duration_ms, uint8_t *pause_ms, uint8_t *dtmf_mode, char *digits, size_t digits_size); -void osmo_cc_add_ie_keypad(osmo_cc_msg_t *msg, const char *digits); -int osmo_cc_get_ie_keypad(osmo_cc_msg_t *msg, int ie_repeat, char *digits, size_t digits_size); -void osmo_cc_add_ie_progress(osmo_cc_msg_t *msg, uint8_t coding, uint8_t location, uint8_t progress); -int osmo_cc_get_ie_progress(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *coding, uint8_t *location, uint8_t *progress); -void osmo_cc_add_ie_notify(osmo_cc_msg_t *msg, uint8_t notify); -int osmo_cc_get_ie_notify(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *notify); -void osmo_cc_add_ie_cause(osmo_cc_msg_t *msg, uint8_t location, uint8_t isdn_cause, uint16_t sip_cause, uint8_t socket_cause); -int osmo_cc_get_ie_cause(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *location, uint8_t *isdn_cause, uint16_t *sip_cause, uint8_t *socket_cause); -void osmo_cc_add_ie_display(osmo_cc_msg_t *msg, const char *text); -int osmo_cc_get_ie_display(osmo_cc_msg_t *msg, int ie_repeat, char *text, size_t text_size); -void osmo_cc_add_ie_sdp(osmo_cc_msg_t *msg, const char *sdp); -int osmo_cc_get_ie_sdp(osmo_cc_msg_t *msg, int ie_repeat, char *sdp, size_t sdp_size); -void osmo_cc_add_ie_socket_address(osmo_cc_msg_t *msg, const char *address); -int osmo_cc_get_ie_socket_address(osmo_cc_msg_t *msg, int ie_repeat, char *address, size_t address_size); -void osmo_cc_add_ie_private(osmo_cc_msg_t *msg, uint32_t unique, const uint8_t *data, size_t data_size); -int osmo_cc_get_ie_private(osmo_cc_msg_t *msg, int ie_repeat, uint32_t *unique, uint8_t *data, size_t data_size); - -#endif /* OSMO_CC_MSG_H */ diff --git a/src/libosmocc/rtp.c b/src/libosmocc/rtp.c deleted file mode 100644 index b118833..0000000 --- a/src/libosmocc/rtp.c +++ /dev/null @@ -1,404 +0,0 @@ -/* Osmo-CC: RTP handling - * - * (C) 2016 by Andreas Eversberg - * All Rights Reserved - * - * 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 3 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, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../libdebug/debug.h" -#include "../libtimer/timer.h" -#include "endpoint.h" - -#define RTP_VERSION 2 - -void osmo_cc_set_rtp_ports(osmo_cc_session_config_t *conf, uint16_t from, uint16_t to) -{ - conf->rtp_port_next = from; - conf->rtp_port_from = from; - conf->rtp_port_to = to; -} - -struct rtp_hdr { - uint8_t byte0; - uint8_t byte1; - uint16_t sequence; - uint32_t timestamp; - uint32_t ssrc; -} __attribute__((packed)); - -struct rtp_x_hdr { - uint16_t by_profile; - uint16_t length; -} __attribute__((packed)); - -static int rtp_receive(int sock, uint8_t **payload_p, int *payload_len_p, uint8_t *marker_p, uint8_t *pt_p, uint16_t *sequence_p, uint32_t *timestamp_p, uint32_t *ssrc_p) -{ - static uint8_t data[2048]; - int len; - struct rtp_hdr *rtph = (struct rtp_hdr *)data; - uint8_t version, padding, extension, csrc_count, marker, payload_type; - struct rtp_x_hdr *rtpxh; - uint8_t *payload; - int payload_len; - int x_len; - - len = read(sock, data, sizeof(data)); - if (len < 0) { - if (errno == EAGAIN) - return -EAGAIN; - PDEBUG(DCC, DEBUG_DEBUG, "Read errno = %d (%s)\n", errno, strerror(errno)); - return -EIO; - } - if (len < 12) { - PDEBUG(DCC, DEBUG_NOTICE, "Received RTP frame too short (len = %d).\n", len); - return -EINVAL; - } - - version = rtph->byte0 >> 6; - padding = (rtph->byte0 >> 5) & 1; - extension = (rtph->byte0 >> 4) & 1; - csrc_count = rtph->byte0 & 0x0f; - marker = rtph->byte1 >> 7; - payload_type = rtph->byte1 & 0x7f; - *sequence_p = ntohs(rtph->sequence); - *timestamp_p = ntohl(rtph->timestamp); - *ssrc_p = ntohl(rtph->ssrc); - - if (version != RTP_VERSION) { - PDEBUG(DCC, DEBUG_NOTICE, "Received RTP version %d not supported.\n", version); - return -EINVAL; - } - - payload = data + sizeof(*rtph) + (csrc_count << 2); - payload_len = len - sizeof(*rtph) - (csrc_count << 2); - if (payload_len < 0) { - PDEBUG(DCC, DEBUG_NOTICE, "Received RTP frame too short (len = %d, csrc count = %d).\n", len, csrc_count); - return -EINVAL; - } - - if (extension) { - if (payload_len < (int)sizeof(*rtpxh)) { - PDEBUG(DCC, DEBUG_NOTICE, "Received RTP frame too short for extension header.\n"); - return -EINVAL; - } - rtpxh = (struct rtp_x_hdr *)payload; - x_len = ntohs(rtpxh->length) * 4 + sizeof(*rtpxh); - payload += x_len; - payload_len -= x_len; - if (payload_len < (int)sizeof(*rtpxh)) { - PDEBUG(DCC, DEBUG_NOTICE, "Received RTP frame too short, extension header exceeds frame length.\n"); - return -EINVAL; - } - } - - if (padding) { - if (payload_len < 1) { - PDEBUG(DCC, DEBUG_NOTICE, "Received RTP frame too short for padding length.\n"); - return -EINVAL; - } - payload_len -= payload[payload_len - 1]; - if (payload_len < 0) { - PDEBUG(DCC, DEBUG_NOTICE, "Received RTP frame padding is greater than payload.\n"); - return -EINVAL; - } - } - - *payload_p = payload; - *payload_len_p = payload_len; - *marker_p = marker; - *pt_p = payload_type; - - return 0; -} - -static void rtp_send(int sock, uint8_t *payload, int payload_len, uint8_t marker, uint8_t pt, uint16_t sequence, uint32_t timestamp, uint32_t ssrc) -{ - struct rtp_hdr *rtph; - char data[sizeof(*rtph) + payload_len]; - int len, rc; - - rtph = (struct rtp_hdr *)data; - len = sizeof(*rtph); - rtph->byte0 = RTP_VERSION << 6; - rtph->byte1 = pt | (marker << 7); - rtph->sequence = htons(sequence); - rtph->timestamp = htonl(timestamp); - rtph->ssrc = htonl(ssrc); - len += payload_len; - if (len > (int)sizeof(data)) { - PDEBUG(DCC, DEBUG_NOTICE, "Buffer overflow, please fix!.\n"); - abort(); - } - memcpy(data + sizeof(*rtph), payload, payload_len); - - rc = write(sock, data, len); - if (rc < 0) - PDEBUG(DCC, DEBUG_DEBUG, "Write errno = %d (%s)\n", errno, strerror(errno)); -} - -/* open and bind RTP - * set local port to what we bound - */ -int osmo_cc_rtp_open(osmo_cc_session_media_t *media) -{ - osmo_cc_session_config_t *conf = media->session->config; - int domain = 0; // make GCC happy - uint16_t start_port; - struct sockaddr_storage sa; - int slen = 0; // make GCC happy - struct sockaddr_in6 *sa6; - struct sockaddr_in *sa4; - uint16_t *sport; - int flags; - int rc; - - media->tx_ssrc = rand(); - - osmo_cc_rtp_close(media); - - switch (media->connection_data_local.addrtype) { - case osmo_cc_session_addrtype_ipv4: - domain = AF_INET; - memset(&sa, 0, sizeof(sa)); - sa4 = (struct sockaddr_in *)&sa; - sa4->sin_family = domain; - rc = inet_pton(AF_INET, media->connection_data_local.address, &sa4->sin_addr); - if (rc < 1) { -pton_error: - PDEBUG(DCC, DEBUG_NOTICE, "Cannot bind to address '%s'.\n", media->connection_data_local.address); - return -EINVAL; - } - sport = &sa4->sin_port; - slen = sizeof(*sa4); - break; - case osmo_cc_session_addrtype_ipv6: - domain = AF_INET6; - memset(&sa, 0, sizeof(sa)); - sa6 = (struct sockaddr_in6 *)&sa; - sa6->sin6_family = domain; - rc = inet_pton(AF_INET6, media->connection_data_local.address, &sa6->sin6_addr); - if (rc < 1) - goto pton_error; - sport = &sa6->sin6_port; - slen = sizeof(*sa6); - break; - case osmo_cc_session_addrtype_unknown: - PDEBUG(DCC, DEBUG_NOTICE, "Unsupported address type '%s'.\n", media->connection_data_local.addrtype_name); - return -EINVAL; - } - - /* rtp_port_from/rtp_port_to may be changed at run time, so rtp_port_next can become out of range. */ - if (conf->rtp_port_next < conf->rtp_port_from || conf->rtp_port_next > conf->rtp_port_to) - conf->rtp_port_next = conf->rtp_port_from; - start_port = conf->rtp_port_next; - while (1) { - /* open sockets */ - rc = socket(domain, SOCK_DGRAM, IPPROTO_UDP); - if (rc < 0) { -socket_error: - PDEBUG(DCC, DEBUG_ERROR, "Cannot create socket (domain=%d, errno=%d(%s))\n", domain, errno, strerror(errno)); - osmo_cc_rtp_close(media); - return -EIO; - } - media->rtp_socket = rc; - rc = socket(domain, SOCK_DGRAM, IPPROTO_UDP); - if (rc < 0) - goto socket_error; - media->rtcp_socket = rc; - - /* bind sockets */ - *sport = htons(conf->rtp_port_next); - rc = bind(media->rtp_socket, (struct sockaddr *)&sa, slen); - if (rc < 0) { -bind_error: - osmo_cc_rtp_close(media); - conf->rtp_port_next = (conf->rtp_port_next + 2 > conf->rtp_port_to) ? conf->rtp_port_from : conf->rtp_port_next + 2; - if (conf->rtp_port_next == start_port) { - PDEBUG(DCC, DEBUG_ERROR, "Cannot bind socket (errno=%d(%s))\n", errno, strerror(errno)); - return -EIO; - } - continue; - } - *sport = htons(conf->rtp_port_next + 1); - rc = bind(media->rtcp_socket, (struct sockaddr *)&sa, slen); - if (rc < 0) - goto bind_error; - media->description.port_local = conf->rtp_port_next; - conf->rtp_port_next = (conf->rtp_port_next + 2 > conf->rtp_port_to) ? conf->rtp_port_from : conf->rtp_port_next + 2; - /* set nonblocking io */ - flags = fcntl(media->rtp_socket, F_GETFL); - flags |= O_NONBLOCK; - fcntl(media->rtp_socket, F_SETFL, flags); - flags = fcntl(media->rtcp_socket, F_GETFL); - flags |= O_NONBLOCK; - fcntl(media->rtcp_socket, F_SETFL, flags); - break; - } - - PDEBUG(DCC, DEBUG_DEBUG, "Opening media port %d\n", media->description.port_local); - - return 0; -} - -/* connect RTP - * use remote port to connect to - */ -int osmo_cc_rtp_connect(osmo_cc_session_media_t *media) -{ - struct sockaddr_storage sa; - int slen = 0; // make GCC happy - struct sockaddr_in6 *sa6; - struct sockaddr_in *sa4; - uint16_t *sport; - int rc; - - PDEBUG(DCC, DEBUG_DEBUG, "Connecting media port %d->%d\n", media->description.port_local, media->description.port_remote); - - switch (media->connection_data_remote.addrtype) { - case osmo_cc_session_addrtype_ipv4: - memset(&sa, 0, sizeof(sa)); - sa4 = (struct sockaddr_in *)&sa; - sa4->sin_family = AF_INET; - rc = inet_pton(AF_INET, media->connection_data_remote.address, &sa4->sin_addr); - if (rc < 1) { -pton_error: - PDEBUG(DCC, DEBUG_NOTICE, "Cannot connect to address '%s'.\n", media->connection_data_remote.address); - return -EINVAL; - } - sport = &sa4->sin_port; - slen = sizeof(*sa4); - break; - case osmo_cc_session_addrtype_ipv6: - memset(&sa, 0, sizeof(sa)); - sa6 = (struct sockaddr_in6 *)&sa; - sa6->sin6_family = AF_INET6; - rc = inet_pton(AF_INET6, media->connection_data_remote.address, &sa6->sin6_addr); - if (rc < 1) - goto pton_error; - sport = &sa6->sin6_port; - slen = sizeof(*sa6); - break; - case osmo_cc_session_addrtype_unknown: - PDEBUG(DCC, DEBUG_NOTICE, "Unsupported address type '%s'.\n", media->connection_data_local.addrtype_name); - return -EINVAL; - } - - *sport = htons(media->description.port_remote); - rc = connect(media->rtp_socket, (struct sockaddr *)&sa, slen); - if (rc < 0) { -connect_error: - PDEBUG(DCC, DEBUG_NOTICE, "Cannot connect to address '%s'.\n", media->connection_data_remote.address); - osmo_cc_rtp_close(media); - return -EIO; - } - *sport = htons(media->description.port_remote + 1); - rc = connect(media->rtcp_socket, (struct sockaddr *)&sa, slen); - if (rc < 0) - goto connect_error; - - return 0; -} - -/* send rtp data with given codec */ -void osmo_cc_rtp_send(osmo_cc_session_codec_t *codec, uint8_t *data, int len, uint8_t marker, int inc_sequence, int inc_timestamp) -{ - uint8_t *payload = NULL; - int payload_len = 0; - - if (!codec || !codec->media->rtp_socket) - return; - - if (codec->encoder) - codec->encoder(data, len, &payload, &payload_len); - else { - payload = data; - payload_len = len; - } - - rtp_send(codec->media->rtp_socket, payload, payload_len, marker, codec->payload_type_remote, codec->media->tx_sequence, codec->media->tx_timestamp, codec->media->tx_ssrc); - codec->media->tx_sequence += inc_sequence; - codec->media->tx_timestamp += inc_timestamp; - - if (codec->encoder) - free(payload); -} - -/* receive rtp data for given media, return < 0, if there is nothing this time */ -int osmo_cc_rtp_receive(osmo_cc_session_media_t *media) -{ - int rc; - uint8_t *payload = NULL; - int payload_len = 0; - uint8_t marker; - uint8_t payload_type; - osmo_cc_session_codec_t *codec; - uint8_t *data; - int len; - - if (!media || media->rtp_socket <= 0) - return -EIO; - - rc = rtp_receive(media->rtp_socket, &payload, &payload_len, &marker, &payload_type, &media->rx_sequence, &media->rx_timestamp, &media->rx_ssrc); - if (rc < 0) - return rc; - - /* search for codec */ - for (codec = media->codec_list; codec; codec = codec->next) { - - if (codec->payload_type_local == payload_type) - break; - } - if (!codec) { - PDEBUG(DCC, DEBUG_NOTICE, "Received RTP frame for unknown codec (payload_type = %d).\n", payload_type); - return 0; - } - - if (codec->decoder) - codec->decoder(payload, payload_len, &data, &len); - else { - data = payload; - len = payload_len; - } - - if (codec->media->receive) - codec->media->receiver(codec, marker, media->rx_sequence, media->rx_timestamp, media->rx_ssrc, data, len); - - if (codec->decoder) - free(data); - - return 0; -} - -void osmo_cc_rtp_close(osmo_cc_session_media_t *media) -{ - if (media->rtp_socket) { - close(media->rtp_socket); - media->rtp_socket = 0; - } - if (media->rtcp_socket) { - close(media->rtcp_socket); - media->rtcp_socket = 0; - } -} - diff --git a/src/libosmocc/rtp.h b/src/libosmocc/rtp.h deleted file mode 100644 index eb74f73..0000000 --- a/src/libosmocc/rtp.h +++ /dev/null @@ -1,8 +0,0 @@ - -void osmo_cc_set_rtp_ports(osmo_cc_session_config_t *conf, uint16_t from, uint16_t to); -int osmo_cc_rtp_open(osmo_cc_session_media_t *media); -int osmo_cc_rtp_connect(osmo_cc_session_media_t *media); -void osmo_cc_rtp_send(osmo_cc_session_codec_t *codec, uint8_t *data, int len, uint8_t marker, int inc_sequence, int inc_timestamp); -int osmo_cc_rtp_receive(osmo_cc_session_media_t *media); -void osmo_cc_rtp_close(osmo_cc_session_media_t *media); - diff --git a/src/libosmocc/screen.c b/src/libosmocc/screen.c deleted file mode 100644 index 5558f42..0000000 --- a/src/libosmocc/screen.c +++ /dev/null @@ -1,693 +0,0 @@ -/* Endpoint and call process handling - * - * (C) 2019 by Andreas Eversberg - * All Rights Reserved - * - * 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 3 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, see . - */ - -#include -#include -#include -#include -#include -#include -#include "../libtimer/timer.h" -#include "../libdebug/debug.h" -#include "endpoint.h" -#include "message.h" - -#define SCREEN_QUESTIONMARK 1 -#define SCREEN_STAR 2 -#define SCREEN_AT 3 - -void osmo_cc_help_screen(void) -{ - printf("Screening options:\n\n"); - - printf("screen-calling-in [attrs] [attrs] \n"); - printf("screen-called-in [attrs] [attrs] \n"); - printf("screen-calling-out [attrs] [attrs] \n"); - printf("screen-called-out [attrs] [attrs] \n\n"); - - printf("These options allow to screen an incoming or outgoing caller ID or dialed\n"); - printf("number. If 'the current caller ID' or 'current dialed number' matches, it will\n"); - printf("be replaced by 'new caller ID' or 'new dialed number'. 'incoming' means from\n"); - printf(" the interface and 'outgoing' means towards the interface.\n\n"); - - printf("Attributes prior 'current caller ID' or 'new dialed number' may be used to\n"); - printf("perform screening only if the attribute match. Attributes prior\n"); - printf("'new caller ID' or 'new dialed number' may be used to alter them. Attribute to\n"); - printf("define the type of number can be: 'unknown', 'international', 'national',\n"); - printf("'network', 'subscriber', 'abbreviated' Attribute to define the restriction of a\n"); - printf("caller ID: 'allowed', 'restricted'\n\n"); - - printf("The current caller ID or dialed number may contain one or more '?', to allow\n"); - printf("any digit to match. The current caller ID or dialed number may contain a '*',\n"); - printf("to allow any suffix to match from now on. The new caller ID or dialed number\n"); - printf("may contain a '*', to append the suffix from the current caller ID or dialed\n"); - printf("number.\n\n"); - - printf("When screening an incoming caller ID or dialed number, the '@' can be appended\n"); - printf("to the 'new caller ID', followed by a 'host:port', to route call to a special\n"); - printf("Osmo-CC endpoint. This way it is possible to do simple routing.\n\n"); -} - -char *osmo_cc_strtok_quotes(const char **text_p) -{ - static char token[1024]; - const char *text = *text_p; - int i, quote; - - /* skip spaces */ - while (*text) { - if (*text > 32) - break; - text++; - } - - /* if eol, return NULL */ - if (!(*text)) - return NULL; - - i = 0; - quote = 0; - while (*text) { - /* escape allows all following characters */ - if (*text == '\\') { - text++; - if (*text) - token[i++] = *text++; - continue; - } - /* no quote, check for them or break on white space */ - if (quote == 0) { - if (*text == '\'') { - quote = 1; - text++; - continue; - } - if (*text == '\"') { - quote = 2; - text++; - continue; - } - if (*text <= ' ') - break; - } - /* single quote, check for unquote */ - if (quote == 1 && *text == '\'') { - quote = 0; - text++; - continue; - } - /* double quote, check for unquote */ - if (quote == 2 && *text == '\"') { - quote = 0; - text++; - continue; - } - /* copy character */ - token[i++] = *text++; - } - token[i] = '\0'; - - *text_p = text; - return token; -} - -int osmo_cc_add_screen(osmo_cc_endpoint_t *ep, const char *text) -{ - osmo_cc_screen_list_t **list_p = NULL, *list; - const char *token; - int no_present = 0, calling_in = 0, star_used, at_used; - int i, j; - - star_used = 0; - if (!strncasecmp(text, "screen-calling-in", 17)) { - text += 17; - list_p = &ep->screen_calling_in; - no_present = 1; - calling_in = 1; - } else if (!strncasecmp(text, "screen-called-in", 16)) { - text += 16; - list_p = &ep->screen_called_in; - calling_in = 1; - } else if (!strncasecmp(text, "screen-calling-out", 18)) { - text += 18; - list_p = &ep->screen_calling_out; - no_present = 1; - } else if (!strncasecmp(text, "screen-called-out", 17)) { - text += 17; - list_p = &ep->screen_called_out; - } else { - PDEBUG(DCC, DEBUG_ERROR, "Invalid screening definition \"%s\". It must start with 'screen-calling-in' or 'screen-called-in' or 'screen-calling-out' or 'screen-called-out'\n", text); - return -EINVAL; - } - - /* skip space behind screen list string */ - while (*text) { - if (*text > 32) - break; - text++; - } - - list = calloc(1, sizeof(*list)); - if (!list) - return -ENOMEM; - -next_from: - token = osmo_cc_strtok_quotes(&text); - if (!token) { - free(list); - PDEBUG(DCC, DEBUG_ERROR, "Missing 'from' string in screening definition \"%s\". If the string shall be empty, use double quotes. (\'\' or \"\")\n", text); - return -EINVAL; - } - if (!strcasecmp(token, "unknown")) { - list->has_from_type = 1; - list->from_type = OSMO_CC_TYPE_UNKNOWN; - goto next_from; - } else - if (!strcasecmp(token, "international")) { - list->has_from_type = 1; - list->from_type = OSMO_CC_TYPE_INTERNATIONAL; - goto next_from; - } else - if (!strcasecmp(token, "national")) { - list->has_from_type = 1; - list->from_type = OSMO_CC_TYPE_NATIONAL; - goto next_from; - } else - if (!strcasecmp(token, "network")) { - list->has_from_type = 1; - list->from_type = OSMO_CC_TYPE_NETWORK; - goto next_from; - } else - if (!strcasecmp(token, "subscriber")) { - list->has_from_type = 1; - list->from_type = OSMO_CC_TYPE_SUBSCRIBER; - goto next_from; - } else - if (!strcasecmp(token, "abbreviated")) { - list->has_from_type = 1; - list->from_type = OSMO_CC_TYPE_ABBREVIATED; - goto next_from; - } else - if (!strcasecmp(token, "allowed")) { - if (no_present) { -no_present_error: - free(list); - PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text); - PDEBUG(DCC, DEBUG_ERROR, "Keyword '%s' not allowed in screen entry for called number\n", token); - return -EINVAL; - } - list->has_from_present = 1; - list->from_present = OSMO_CC_PRESENT_ALLOWED; - goto next_from; - } else - if (!strcasecmp(token, "restricted")) { - if (no_present) - goto no_present_error; - list->has_from_present = 1; - list->from_present = OSMO_CC_PRESENT_RESTRICTED; - goto next_from; - } else { - star_used = 0; - for (i = j = 0; token[i] && j < (int)sizeof(list->from) - 1; i++, j++) { - if (token[i] == '?') - list->from[j] = SCREEN_QUESTIONMARK; - else - if (token[i] == '*') { - if (star_used) { - free(list); - PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text); - PDEBUG(DCC, DEBUG_ERROR, "The '*' may be used only once.\n"); - return -EINVAL; - } - list->from[j] = SCREEN_STAR; - star_used = 1; - } else - if (token[i] == '\\' && token[i + 1] != '\0') - list->from[j] = token[++i]; - else - list->from[j] = token[i]; - } - list->from[j] = '\0'; - } - -next_to: - token = osmo_cc_strtok_quotes(&text); - if (!token) { - free(list); - PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text); - PDEBUG(DCC, DEBUG_ERROR, "Missing screening result. If the string shall be empty, use double quotes. (\'\' or \"\")\n"); - return -EINVAL; - } - if (!strcasecmp(token, "unknown")) { - list->has_to_type = 1; - list->to_type = OSMO_CC_TYPE_UNKNOWN; - goto next_to; - } else - if (!strcasecmp(token, "international")) { - list->has_to_type = 1; - list->to_type = OSMO_CC_TYPE_INTERNATIONAL; - goto next_to; - } else - if (!strcasecmp(token, "national")) { - list->has_to_type = 1; - list->to_type = OSMO_CC_TYPE_NATIONAL; - goto next_to; - } else - if (!strcasecmp(token, "network")) { - list->has_to_type = 1; - list->to_type = OSMO_CC_TYPE_NETWORK; - goto next_to; - } else - if (!strcasecmp(token, "subscriber")) { - list->has_to_type = 1; - list->to_type = OSMO_CC_TYPE_SUBSCRIBER; - goto next_to; - } else - if (!strcasecmp(token, "abbreviated")) { - list->has_to_type = 1; - list->to_type = OSMO_CC_TYPE_ABBREVIATED; - goto next_to; - } else - if (!strcasecmp(token, "allowed")) { - if (no_present) - goto no_present_error; - list->has_to_present = 1; - list->to_present = OSMO_CC_PRESENT_ALLOWED; - goto next_to; - } else - if (!strcasecmp(token, "restricted")) { - if (no_present) - goto no_present_error; - list->has_to_present = 1; - list->to_present = OSMO_CC_PRESENT_RESTRICTED; - goto next_to; - } else { - at_used = star_used = 0; - for (i = j = 0; token[i] && j < (int)sizeof(list->to) - 1; i++, j++) { - if (token[i] == '*') { - if (star_used) { - free(list); - PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text); - PDEBUG(DCC, DEBUG_ERROR, "The '*' may be used only once.\n"); - return -EINVAL; - } - list->to[j] = SCREEN_STAR; - star_used = 1; - } else - if (token[i] == '@') { - if (!calling_in) { - free(list); - PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text); - PDEBUG(DCC, DEBUG_ERROR, "The '@' may be used only for incoming calls from interface.\n"); - return -EINVAL; - } - if (at_used) { - free(list); - PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text); - PDEBUG(DCC, DEBUG_ERROR, "The '@' may be used only once.\n"); - return -EINVAL; - } - list->to[j] = SCREEN_AT; - at_used = 1; - } else - if (token[i] == '\\' && token[i + 1] != '\0') - list->to[j] = token[++i]; - else - list->to[j] = token[i]; - } - list->to[j] = '\0'; - } - - token = osmo_cc_strtok_quotes(&text); - if (token) { - free(list); - PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text); - PDEBUG(DCC, DEBUG_ERROR, "Got garbage behind screening result.\n"); - return -EINVAL; - } - - /* attach screen entry to list */ - while (*list_p) - list_p = &((*list_p)->next); - *list_p = list; - - return 0; -} - -void osmo_cc_flush_screen(osmo_cc_screen_list_t *list) -{ - osmo_cc_screen_list_t *temp; - - while (list) { - temp = list; - list = list->next; - free(temp); - } -} - -const char *print_rule_string(const char *input) -{ - static char output[256]; - int i; - - for (i = 0; *input && i < (int)sizeof(output) - 1; i++, input++) { - switch (*input) { - case SCREEN_QUESTIONMARK: - output[i] = '?'; - break; - case SCREEN_STAR: - output[i] = '*'; - break; - case SCREEN_AT: - output[i] = '@'; - break; - default: - output[i] = *input; - } - } - - output[i] = '\0'; - return output; -} - -static int osmo_cc_screen(const char *what, osmo_cc_screen_list_t *list, uint8_t *type, uint8_t *present, char *id_to, int id_to_size, const char *id_from, const char **routing_p) -{ - const char *suffix; - int i, j, rule; - - PDEBUG(DCC, DEBUG_INFO, "Screening %s '%s':\n", what, id_from); - switch (*type) { - case OSMO_CC_TYPE_UNKNOWN: - PDEBUG(DCC, DEBUG_INFO, " -> type = unknown\n"); - break; - case OSMO_CC_TYPE_INTERNATIONAL: - PDEBUG(DCC, DEBUG_INFO, " -> type = international\n"); - break; - case OSMO_CC_TYPE_NATIONAL: - PDEBUG(DCC, DEBUG_INFO, " -> type = national\n"); - break; - case OSMO_CC_TYPE_NETWORK: - PDEBUG(DCC, DEBUG_INFO, " -> type = network\n"); - break; - case OSMO_CC_TYPE_SUBSCRIBER: - PDEBUG(DCC, DEBUG_INFO, " -> type = subscriber\n"); - break; - case OSMO_CC_TYPE_ABBREVIATED: - PDEBUG(DCC, DEBUG_INFO, " -> type = abbreviated\n"); - break; - } - if (present) switch (*present) { - case OSMO_CC_PRESENT_ALLOWED: - PDEBUG(DCC, DEBUG_INFO, " -> present = allowed\n"); - break; - case OSMO_CC_PRESENT_RESTRICTED: - PDEBUG(DCC, DEBUG_INFO, " -> present = restricted\n"); - break; - } - - rule = 0; - while (list) { - rule++; - PDEBUG(DCC, DEBUG_INFO, "Comparing with rule #%d: '%s':\n", rule, print_rule_string(list->from)); - if (list->has_from_type) switch (list->from_type) { - case OSMO_CC_TYPE_UNKNOWN: - PDEBUG(DCC, DEBUG_INFO, " -> type = unknown\n"); - break; - case OSMO_CC_TYPE_INTERNATIONAL: - PDEBUG(DCC, DEBUG_INFO, " -> type = international\n"); - break; - case OSMO_CC_TYPE_NATIONAL: - PDEBUG(DCC, DEBUG_INFO, " -> type = national\n"); - break; - case OSMO_CC_TYPE_NETWORK: - PDEBUG(DCC, DEBUG_INFO, " -> type = network\n"); - break; - case OSMO_CC_TYPE_SUBSCRIBER: - PDEBUG(DCC, DEBUG_INFO, " -> type = subscriber\n"); - break; - case OSMO_CC_TYPE_ABBREVIATED: - PDEBUG(DCC, DEBUG_INFO, " -> type = abbreviated\n"); - break; - } - if (list->has_from_present) switch (list->from_present) { - case OSMO_CC_PRESENT_ALLOWED: - PDEBUG(DCC, DEBUG_INFO, " -> present = allowed\n"); - break; - case OSMO_CC_PRESENT_RESTRICTED: - PDEBUG(DCC, DEBUG_INFO, " -> present = restricted\n"); - break; - } - suffix = NULL; - /* attributes do not match */ - if (list->has_from_type && list->from_type != *type) { - PDEBUG(DCC, DEBUG_INFO, "Rule does not match, because 'type' is different.\n"); - continue; - } - if (present && list->has_from_present && list->from_present != *present) { - PDEBUG(DCC, DEBUG_INFO, "Rule does not match, because 'present' is different.\n"); - continue; - } - for (i = 0; list->from[i] && id_from[i]; i++) { - /* '?' means: any digit, so it machtes */ - if (list->from[i] == SCREEN_QUESTIONMARK) { - continue; - } - /* '*' means: anything may follow, so it machtes */ - if (list->from[i] == SCREEN_STAR) { - suffix = id_from + i; - break; - } - /* check if digit doesn't matches */ - if (list->from[i] != id_from[i]) - break; - } - /* if last checked digit is '*', we have a match */ - /* also if we hit EOL at id_from and next check digit is '*' */ - if (list->from[i] == SCREEN_STAR) - break; - /* if all digits have matched */ - if (list->from[i] == '\0' && id_from[i] == '\0') - break; - PDEBUG(DCC, DEBUG_INFO, "Rule does not match, because %s is different.\n", what); - list = list->next; - } - - /* if no list entry matches */ - if (!list) - return -1; - - /* replace ID */ - if (list->has_to_type) { - *type = list->to_type; - } - if (present && list->has_to_present) { - *present = list->to_present; - } - for (i = j = 0; list->to[i]; i++) { - if (j == id_to_size - 1) - break; - /* '*' means to use suffix of input string */ - if (list->to[i] == SCREEN_STAR && suffix) { - while (*suffix) { - id_to[j++] = *suffix++; - if (j == id_to_size - 1) - break; - } - continue; - /* '@' means to stop and return routing also */ - } else if (list->to[i] == SCREEN_AT) { - if (routing_p) - *routing_p = &list->to[i + 1]; - break; - } - /* copy output digit */ - id_to[j++] = list->to[i]; - } - id_to[j] = '\0'; - - PDEBUG(DCC, DEBUG_INFO, "Rule matches, changing %s to '%s'.\n", what, print_rule_string(id_to)); - if (list->has_to_type) switch (list->to_type) { - case OSMO_CC_TYPE_UNKNOWN: - PDEBUG(DCC, DEBUG_INFO, " -> type = unknown\n"); - break; - case OSMO_CC_TYPE_INTERNATIONAL: - PDEBUG(DCC, DEBUG_INFO, " -> type = international\n"); - break; - case OSMO_CC_TYPE_NATIONAL: - PDEBUG(DCC, DEBUG_INFO, " -> type = national\n"); - break; - case OSMO_CC_TYPE_NETWORK: - PDEBUG(DCC, DEBUG_INFO, " -> type = network\n"); - break; - case OSMO_CC_TYPE_SUBSCRIBER: - PDEBUG(DCC, DEBUG_INFO, " -> type = subscriber\n"); - break; - case OSMO_CC_TYPE_ABBREVIATED: - PDEBUG(DCC, DEBUG_INFO, " -> type = abbreviated\n"); - break; - } - if (list->has_to_present) switch (list->to_present) { - case OSMO_CC_PRESENT_ALLOWED: - PDEBUG(DCC, DEBUG_INFO, " -> present = allowed\n"); - break; - case OSMO_CC_PRESENT_RESTRICTED: - PDEBUG(DCC, DEBUG_INFO, " -> present = restricted\n"); - break; - } - if (routing_p && *routing_p) - PDEBUG(DCC, DEBUG_INFO, " -> remote = %s\n", *routing_p); - - return 0; -} - -osmo_cc_msg_t *osmo_cc_screen_msg(osmo_cc_endpoint_t *ep, osmo_cc_msg_t *old_msg, int in, const char **routing_p) -{ - osmo_cc_msg_t *new_msg; - char id[256], calling[256], called[256], redir[256]; - uint8_t calling_type, calling_plan, calling_present, calling_screen; - uint8_t called_type, called_plan; - uint8_t redir_type, redir_plan, redir_present, redir_screen, redir_reason; - int calling_status = 0, called_status = 0, redir_status = 0; - int rc; - void *ie, *to_ie; - uint8_t ie_type; - uint16_t ie_length; - void *ie_value; - - if (in && ep->screen_calling_in) { - rc = osmo_cc_get_ie_calling(old_msg, 0, &calling_type, &calling_plan, &calling_present, &calling_screen, id, sizeof(id)); - if (rc >= 0) { - rc = osmo_cc_screen("incoming caller ID", ep->screen_calling_in, &calling_type, &calling_present, calling, sizeof(calling), id, routing_p); - if (rc >= 0) - calling_status = 1; - } else { - calling_type = OSMO_CC_TYPE_UNKNOWN; - calling_plan = OSMO_CC_PLAN_TELEPHONY; - calling_present = OSMO_CC_PRESENT_ALLOWED; - calling_screen = OSMO_CC_SCREEN_NETWORK; - rc = osmo_cc_screen("incoming caller ID", ep->screen_calling_in, &calling_type, &calling_present, calling, sizeof(calling), "", routing_p); - if (rc >= 0) - calling_status = 1; - } - rc = osmo_cc_get_ie_redir(old_msg, 0, &redir_type, &redir_plan, &redir_present, &redir_screen, &redir_reason, id, sizeof(id)); - if (rc >= 0) { - rc = osmo_cc_screen("incoming redirecting number", ep->screen_calling_in, &redir_type, &redir_present, redir, sizeof(redir), id, NULL); - if (rc >= 0) - redir_status = 1; - } - } - if (in && ep->screen_called_in) { - rc = osmo_cc_get_ie_called(old_msg, 0, &called_type, &called_plan, id, sizeof(id)); - if (rc >= 0) { - rc = osmo_cc_screen("incoming dialed number", ep->screen_called_in, &called_type, NULL, called, sizeof(called), id, routing_p); - if (rc >= 0) - called_status = 1; - } else { - called_type = OSMO_CC_TYPE_UNKNOWN; - called_plan = OSMO_CC_PLAN_TELEPHONY; - rc = osmo_cc_screen("incoming dialed number", ep->screen_called_in, &called_type, NULL, called, sizeof(called), "", routing_p); - if (rc >= 0) - called_status = 1; - } - } - if (!in && ep->screen_calling_out) { - rc = osmo_cc_get_ie_calling(old_msg, 0, &calling_type, &calling_plan, &calling_present, &calling_screen, id, sizeof(id)); - if (rc >= 0) { - rc = osmo_cc_screen("outgoing caller ID", ep->screen_calling_out, &calling_type, &calling_present, calling, sizeof(calling), id, NULL); - if (rc >= 0) - calling_status = 1; - } else { - calling_type = OSMO_CC_TYPE_UNKNOWN; - calling_plan = OSMO_CC_PLAN_TELEPHONY; - calling_present = OSMO_CC_PRESENT_ALLOWED; - calling_screen = OSMO_CC_SCREEN_NETWORK; - rc = osmo_cc_screen("outgoing caller ID", ep->screen_calling_out, &calling_type, &calling_present, calling, sizeof(calling), "", NULL); - if (rc >= 0) - calling_status = 1; - } - rc = osmo_cc_get_ie_redir(old_msg, 0, &redir_type, &redir_plan, &redir_present, &redir_screen, &redir_reason, id, sizeof(id)); - if (rc >= 0) { - rc = osmo_cc_screen("outgoing redirecting number", ep->screen_calling_out, &redir_type, &redir_present, redir, sizeof(redir), id, NULL); - if (rc >= 0) - redir_status = 1; - } - } - if (!in && ep->screen_called_out) { - rc = osmo_cc_get_ie_called(old_msg, 0, &called_type, &called_plan, id, sizeof(id)); - if (rc >= 0) { - rc = osmo_cc_screen("outgoing dialed number", ep->screen_called_out, &called_type, NULL, called, sizeof(called), id, NULL); - if (rc >= 0) - called_status = 1; - } else { - called_type = OSMO_CC_TYPE_UNKNOWN; - called_plan = OSMO_CC_PLAN_TELEPHONY; - rc = osmo_cc_screen("outgoing dialed number", ep->screen_called_out, &called_type, NULL, called, sizeof(called), "", NULL); - if (rc >= 0) - called_status = 1; - } - } - - /* nothing screened */ - if (!calling_status && !called_status && !redir_status) - return old_msg; - - new_msg = osmo_cc_new_msg(old_msg->type); - - /* copy and replace */ - ie = old_msg->data; - while ((ie_value = osmo_cc_msg_sep_ie(old_msg, &ie, &ie_type, &ie_length))) { - switch (ie_type) { - case OSMO_CC_IE_CALLING: - if (calling_status) { - osmo_cc_add_ie_calling(new_msg, calling_type, calling_plan, calling_present, calling_screen, calling); - calling_status = 0; - break; - } - goto copy; - case OSMO_CC_IE_CALLED: - if (called_status) { - osmo_cc_add_ie_called(new_msg, called_type, called_plan, called); - called_status = 0; - break; - } - goto copy; - case OSMO_CC_IE_REDIR: - if (redir_status) { - osmo_cc_add_ie_redir(new_msg, redir_type, redir_plan, redir_present, redir_screen, redir_reason, redir); - redir_status = 0; - break; - } - goto copy; - default: - copy: - to_ie = osmo_cc_add_ie(new_msg, ie_type, ie_length); - memcpy(to_ie, ie_value, ie_length); - } - } - - /* applend, if not yet in message (except redir, since it must exist) */ - if (calling_status) - osmo_cc_add_ie_calling(new_msg, calling_type, calling_plan, calling_present, calling_screen, calling); - if (called_status) - osmo_cc_add_ie_called(new_msg, called_type, called_plan, called); - - free(old_msg); - return new_msg; -} - diff --git a/src/libosmocc/screen.h b/src/libosmocc/screen.h deleted file mode 100644 index 29f4515..0000000 --- a/src/libosmocc/screen.h +++ /dev/null @@ -1,7 +0,0 @@ - -void osmo_cc_help_screen(void); -char *osmo_cc_strtok_quotes(const char **text_p); -int osmo_cc_add_screen(osmo_cc_endpoint_t *ep, const char *text); -void osmo_cc_flush_screen(osmo_cc_screen_list_t *list); -osmo_cc_msg_t *osmo_cc_screen_msg(osmo_cc_endpoint_t *ep, osmo_cc_msg_t *old_msg, int in, const char **routing_p); - diff --git a/src/libosmocc/sdp.c b/src/libosmocc/sdp.c deleted file mode 100644 index 849bfb9..0000000 --- a/src/libosmocc/sdp.c +++ /dev/null @@ -1,544 +0,0 @@ -/* Session Description Protocol parsing and generator - * This shall be simple and is incomplete. - * - * (C) 2019 by Andreas Eversberg - * All Rights Reserved - * - * 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 3 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, see . - */ - -#include -#include -#include -#include -#include -#include "../libdebug/debug.h" -#include "../libtimer/timer.h" -#include "endpoint.h" -#include "sdp.h" - -#define strncat_printf(sdp, fmt, arg...) \ - { \ - snprintf(sdp + strlen(sdp), sizeof(sdp) - strlen(sdp), fmt, ## arg); \ - sdp[sizeof(sdp) - 1] = '\0'; \ - } - -/* generate SDP from session structure */ -char *osmo_cc_session_gensdp(osmo_cc_session_t *session) -{ - /* calc max size of SDP: quick an dirty (close to max UDP payload size) */ - static char sdp[65000]; - const char *username, *sess_id, *sess_version, *nettype, *addrtype, *unicast_address; - const char *session_name; - int individual_connection_data = 1; /* in case there is no media, there is no connection data */ - int individual_send_receive = 1; /* in case there is no media, there is no send/receive attribute */ - struct osmo_cc_session_media *media; - struct osmo_cc_session_codec *codec; - - sdp[0] = 0; - - /* Version */ - strncat_printf(sdp, "v=0\r\n"); - - /* Origin */ - username = session->origin_local.username; - sess_id = session->origin_local.sess_id; - sess_version = session->origin_local.sess_version; - nettype = session->origin_local.nettype; - addrtype = session->origin_local.addrtype; - unicast_address = session->origin_local.unicast_address; - strncat_printf(sdp, "o=%s %s %s %s %s %s\r\n", username, sess_id, sess_version, nettype, addrtype, unicast_address); - - /* Session */ - session_name = session->name; - strncat_printf(sdp, "s=%s\r\n", session_name); - - /* Connection Data (if all media have the same data) */ - if (session->media_list) { - osmo_cc_session_for_each_media(session->media_list->next, media) { - if (session->media_list->connection_data_local.nettype != media->connection_data_local.nettype) - break; - if (session->media_list->connection_data_local.addrtype != media->connection_data_local.addrtype) - break; - if (!!strcmp(session->media_list->connection_data_local.address, media->connection_data_local.address)) - break; - } - if (!media) - individual_connection_data = 0; - } - if (!individual_connection_data) - strncat_printf(sdp, "c=%s %s %s\r\n", osmo_cc_session_nettype2string(session->media_list->connection_data_local.nettype), osmo_cc_session_addrtype2string(session->media_list->connection_data_local.addrtype), session->media_list->connection_data_local.address); - - /* timestamp */ - strncat_printf(sdp, "t=0 0\r\n"); - - /* sendonly /recvonly (if all media have the same data) */ - if (session->media_list) { - osmo_cc_session_for_each_media(session->media_list->next, media) { - if (session->media_list->send != media->send) - break; - if (session->media_list->receive != media->receive) - break; - } - if (!media) - individual_send_receive = 0; - } - if (!individual_send_receive) { - if (session->media_list->send && !session->media_list->receive) - strncat_printf(sdp, "a=sendonly\r\n"); - if (!session->media_list->send && session->media_list->receive) - strncat_printf(sdp, "a=recvonly\r\n"); - if (!session->media_list->send && !session->media_list->receive) - strncat_printf(sdp, "a=inactive\r\n"); - } - - /* media */ - osmo_cc_session_for_each_media(session->media_list, media) { - strncat_printf(sdp, "m=%s %u %s", - osmo_cc_session_media_type2string(media->description.type) ? : media->description.type_name, - media->description.port_local, - osmo_cc_session_media_proto2string(media->description.proto) ? : media->description.proto_name); - osmo_cc_session_for_each_codec(media->codec_list, codec) - strncat_printf(sdp, " %u", codec->payload_type_local); - strncat_printf(sdp, "\r\n"); - /* don't list rtpmap when session was canceled by setting port to 0 */ - if (media->description.port_local == 0) - continue; - if (individual_connection_data) - strncat_printf(sdp, "c=%s %s %s\r\n", osmo_cc_session_nettype2string(media->connection_data_local.nettype), osmo_cc_session_addrtype2string(media->connection_data_local.addrtype), media->connection_data_local.address); - osmo_cc_session_for_each_codec(media->codec_list, codec) { - strncat_printf(sdp, "a=rtpmap:%u %s/%d", codec->payload_type_local, codec->payload_name, codec->payload_rate); - if (codec->payload_channels >= 2) - strncat_printf(sdp, "/%d", codec->payload_channels); - strncat_printf(sdp, "\r\n"); - } - if (individual_send_receive) { - if (media->send && !media->receive) - strncat_printf(sdp, "a=sendonly\r\n"); - if (!media->send && media->receive) - strncat_printf(sdp, "a=recvonly\r\n"); - if (!media->send && !media->receive) - strncat_printf(sdp, "a=inactive\r\n"); - } - } - - /* check for overflow and return */ - if (strlen(sdp) == sizeof(sdp) - 1) { - PDEBUG(DCC, DEBUG_ERROR, "Fatal error: Allocated SDP buffer with %d bytes is too small, please fix!\n", (int)sizeof(sdp)); - return NULL; - } - return sdp; -} - -/* separate a word from string that is delimited with one or more space characters */ -static char *wordsep(char **text_p) -{ - char *text = *text_p; - static char word[256]; - int i; - - /* no text */ - if (text == NULL || *text == '\0') - return NULL; - /* skip spaces before text */ - while (*text && *text <= ' ') - text++; - /* copy content */ - i = 0; - while (*text > ' ' && i < (int)sizeof(word)) - word[i++] = *text++; - word[i] = '\0'; - /* set next */ - *text_p = text; - return word; -} - -/* - * codecs and their default values - * - * if format is -1, payload type is dynamic - * if rate is 0, rate may be any rate - */ -struct codec_defaults { - int fmt; - char *name; - uint32_t rate; - int channels; -} codec_defaults[] = { - { 0, "PCMU", 8000, 1 }, - { 3, "GSM", 8000, 1 }, - { 4, "G723", 8000, 1 }, - { 5, "DVI4", 8000, 1 }, - { 6, "DVI4", 16000, 1 }, - { 7, "LPC", 8000, 1 }, - { 8, "PCMA", 8000, 1 }, - { 9, "G722", 8000, 1 }, - { 10, "L16", 44100, 2 }, - { 11, "L16", 44100, 1 }, - { 12, "QCELP", 8000, 1 }, - { 13, "CN", 8000, 1 }, - { 14, "MPA", 90000, 1 }, - { 15, "G728", 8000, 1 }, - { 16, "DVI4", 11025, 1 }, - { 17, "DVI4", 22050, 1 }, - { 18, "G729", 8000, 1 }, - { 25, "CELB", 90000, 0 }, - { 26, "JPEG", 90000, 0 }, - { 28, "nv", 90000, 0 }, - { 31, "H261", 90000, 0 }, - { 32, "MPV", 90000, 0 }, - { 33, "MP2T", 90000, 0 }, - { 34, "H263", 90000, 0 }, - { -1, NULL, 0, 0 }, -}; - -static void complete_codec_by_fmt(uint8_t fmt, const char **name, uint32_t *rate, int *channels) -{ - int i; - - for (i = 0; codec_defaults[i].name; i++) { - if (codec_defaults[i].fmt == fmt) - break; - } - if (!codec_defaults[i].name) - return; - - free((char *)*name); - *name = strdup(codec_defaults[i].name); - *rate = codec_defaults[i].rate; - *channels = codec_defaults[i].channels; -} - -int osmo_cc_payload_type_by_attrs(uint8_t *fmt, const char *name, uint32_t *rate, int *channels) -{ - int i; - - for (i = 0; codec_defaults[i].name; i++) { - if (!strcmp(codec_defaults[i].name, name) - && (*rate == 0 || codec_defaults[i].rate == *rate) - && (*channels == 0 || codec_defaults[i].channels == *channels)) - break; - } - if (!codec_defaults[i].name) - return -EINVAL; - - *fmt = codec_defaults[i].fmt; - *rate = codec_defaults[i].rate; - *channels = codec_defaults[i].channels; - - return 0; -} - -/* parses data and codec list from SDP - * - * sdp = given SDP text - * return: SDP session description structure */ -struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf, void *priv, const char *_sdp) -{ - char buffer[strlen(_sdp) + 1], *sdp = buffer; - char *line, *p, *word, *next_word; - int line_no = 0; - struct osmo_cc_session_connection_data ccd, *cd; - int csend = 1, creceive = 1; /* common default */ - struct osmo_cc_session *session = NULL; - struct osmo_cc_session_media *media = NULL; - struct osmo_cc_session_codec *codec = NULL; - - /* prepare data */ - strcpy(sdp, _sdp); - memset(&ccd, 0, sizeof(ccd)); - - /* create SDP session description */ - session = osmo_cc_new_session(conf, priv, NULL, NULL, NULL, 0, 0, NULL, NULL, 0); - - /* check every line of SDP and parse its data */ - while(*sdp) { - if ((p = strchr(sdp, '\r'))) { - *p++ = '\0'; - if (*p == '\n') - p++; - line = sdp; - sdp = p; - } else if ((p = strchr(sdp, '\n'))) { - *p++ = '\0'; - line = sdp; - sdp = p; - } else { - line = sdp; - sdp = strchr(sdp, '\0'); - } - next_word = line + 2; - line_no++; - - if (line[0] == '\0') - continue; - - if (line[1] != '=') { - PDEBUG(DCC, DEBUG_NOTICE, "SDP line %d = '%s' is garbage, expecting '=' as second character.\n", line_no, line); - continue; - } - - switch(line[0]) { - case 'v': - PDEBUG(DCC, DEBUG_DEBUG, " -> Version: %s\n", next_word); - if (atoi(next_word) != 0) { - PDEBUG(DCC, DEBUG_NOTICE, "SDP line %d = '%s' describes unsupported version.\n", line_no, line); - osmo_cc_free_session(session); - return NULL; - } - break; - case 'o': - PDEBUG(DCC, DEBUG_DEBUG, " -> Originator: %s\n", next_word); - /* Originator */ - word = wordsep(&next_word); - if (!word) - break; - free((char *)session->origin_remote.username); // if already set - session->origin_remote.username = strdup(word); - word = wordsep(&next_word); - if (!word) - break; - free((char *)session->origin_remote.sess_id); // if already set - session->origin_remote.sess_id = strdup(word); - word = wordsep(&next_word); - if (!word) - break; - free((char *)session->origin_remote.sess_version); // if already set - session->origin_remote.sess_version = strdup(word); - word = wordsep(&next_word); - if (!word) - break; - free((char *)session->origin_remote.nettype); // if already set - session->origin_remote.nettype = strdup(word); - word = wordsep(&next_word); - if (!word) - break; - free((char *)session->origin_remote.addrtype); // if already set - session->origin_remote.addrtype = strdup(word); - word = wordsep(&next_word); - if (!word) - break; - free((char *)session->origin_remote.unicast_address); // if already set - session->origin_remote.unicast_address = strdup(word); - break; - case 's': - /* Session Name */ - PDEBUG(DCC, DEBUG_DEBUG, " -> Session Name: %s\n", next_word); - free((char *)session->name); // if already set - session->name = strdup(next_word); - break; - case 'c': /* Connection Data */ - PDEBUG(DCC, DEBUG_DEBUG, " -> Connection Data: %s\n", next_word); - if (media) - cd = &media->connection_data_remote; - else - cd = &ccd; - /* network type */ - if (!(word = wordsep(&next_word))) - break; - if (!strcmp(word, "IN")) - cd->nettype = osmo_cc_session_nettype_inet; - else { - PDEBUG(DCC, DEBUG_NOTICE, "Unsupported network type '%s' in SDP line %d = '%s'\n", word, line_no, line); - break; - } - /* address type */ - if (!(word = wordsep(&next_word))) - break; - if (!strcmp(word, "IP4")) { - cd->addrtype = osmo_cc_session_addrtype_ipv4; - PDEBUG(DCC, DEBUG_DEBUG, " -> Address Type = IPv4\n"); - } else - if (!strcmp(word, "IP6")) { - cd->addrtype = osmo_cc_session_addrtype_ipv6; - PDEBUG(DCC, DEBUG_DEBUG, " -> Address Type = IPv6\n"); - } else { - PDEBUG(DCC, DEBUG_NOTICE, "Unsupported address type '%s' in SDP line %d = '%s'\n", word, line_no, line); - break; - } - /* connection address */ - if (!(word = wordsep(&next_word))) - break; - if ((p = strchr(word, '/'))) - *p++ = '\0'; - free((char *)cd->address); // in case of multiple lines of 'c' - cd->address = strdup(word); - PDEBUG(DCC, DEBUG_DEBUG, " -> Address = %s\n", word); - break; - case 'm': /* Media Description */ - PDEBUG(DCC, DEBUG_DEBUG, " -> Media Description: %s\n", next_word); - /* add media description */ - media = osmo_cc_add_media(session, 0, 0, NULL, 0, 0, 0, csend, creceive, NULL, 0); - /* copy common connection data from common connection, if exists */ - cd = &media->connection_data_remote; - memcpy(cd, &ccd, sizeof(*cd)); - /* media type */ - if (!(word = wordsep(&next_word))) - break; - if (!strcmp(word, "audio")) - media->description.type = osmo_cc_session_media_type_audio; - else - if (!strcmp(word, "video")) - media->description.type = osmo_cc_session_media_type_video; - else { - media->description.type = osmo_cc_session_media_type_unknown; - media->description.type_name = strdup(word); - PDEBUG(DCC, DEBUG_DEBUG, "Unsupported media type in SDP line %d = '%s'\n", line_no, line); - } - /* port */ - if (!(word = wordsep(&next_word))) - break; - media->description.port_remote = atoi(word); - /* proto */ - if (!(word = wordsep(&next_word))) - break; - if (!strcmp(word, "RTP/AVP")) - media->description.proto = osmo_cc_session_media_proto_rtp; - else { - media->description.proto = osmo_cc_session_media_proto_unknown; - media->description.proto_name = strdup(word); - PDEBUG(DCC, DEBUG_NOTICE, "Unsupported protocol type in SDP line %d = '%s'\n", line_no, line); - break; - } - /* create codec description for each codec and link */ - while ((word = wordsep(&next_word))) { - /* create codec */ - codec = osmo_cc_add_codec(media, NULL, 0, 1, NULL, NULL, 0); - /* fmt */ - codec->payload_type_remote = atoi(word); - complete_codec_by_fmt(codec->payload_type_remote, &codec->payload_name, &codec->payload_rate, &codec->payload_channels); - PDEBUG(DCC, DEBUG_DEBUG, " -> payload type = %d\n", codec->payload_type_remote); - if (codec->payload_name) - PDEBUG(DCC, DEBUG_DEBUG, " -> payload name = %s\n", codec->payload_name); - if (codec->payload_rate) - PDEBUG(DCC, DEBUG_DEBUG, " -> payload rate = %d\n", codec->payload_rate); - if (codec->payload_channels) - PDEBUG(DCC, DEBUG_DEBUG, " -> payload channels = %d\n", codec->payload_channels); - } - break; - case 'a': - PDEBUG(DCC, DEBUG_DEBUG, " -> Attribute: %s\n", next_word); - word = wordsep(&next_word); - if (!strcmp(word, "sendrecv")) { - if (media) { - media->receive = 1; - media->send = 1; - } else { - creceive = 1; - csend = 1; - } - break; - } else - if (!strcmp(word, "recvonly")) { - if (media) { - media->receive = 1; - media->send = 0; - } else { - creceive = 1; - csend = 0; - } - break; - } else - if (!strcmp(word, "sendonly")) { - if (media) { - media->receive = 0; - media->send = 1; - } else { - creceive = 0; - csend = 1; - } - break; - } else - if (!strcmp(word, "inactive")) { - if (media) { - media->receive = 0; - media->send = 0; - } else { - creceive = 0; - csend = 0; - } - break; - } else - if (!media) { - PDEBUG(DCC, DEBUG_NOTICE, "Attribute without previously defined media in SDP line %d = '%s'\n", line_no, line); - break; - } - if (!strncmp(word, "rtpmap:", 7)) { - int fmt = atoi(word + 7); - osmo_cc_session_for_each_codec(media->codec_list, codec) { - if (codec->payload_type_remote == fmt) - break; - } - if (!codec) { - PDEBUG(DCC, DEBUG_NOTICE, "Attribute without previously defined codec in SDP line %d = '%s'\n", line_no, line); - break; - } - PDEBUG(DCC, DEBUG_DEBUG, " -> (rtpmap) payload type = %d\n", codec->payload_type_remote); - if (!(word = wordsep(&next_word))) - goto rtpmap_done; - if ((p = strchr(word, '/'))) - *p++ = '\0'; - free((char *)codec->payload_name); // in case it is already set above - codec->payload_name = strdup(word); - PDEBUG(DCC, DEBUG_DEBUG, " -> (rtpmap) payload name = %s\n", codec->payload_name); - if (!(word = p)) - goto rtpmap_done; - if ((p = strchr(word, '/'))) - *p++ = '\0'; - codec->payload_rate = atoi(word); - PDEBUG(DCC, DEBUG_DEBUG, " -> (rtpmap) payload rate = %d\n", codec->payload_rate); - if (!(word = p)) { - /* if no channel is given and no default was specified, we must set 1 channel */ - if (!codec->payload_channels) - codec->payload_channels = 1; - goto rtpmap_done; - } - codec->payload_channels = atoi(word); - PDEBUG(DCC, DEBUG_DEBUG, " -> (rtpmap) payload channels = %d\n", codec->payload_channels); - rtpmap_done: - if (!codec->payload_name || !codec->payload_rate || !codec->payload_channels) { - PDEBUG(DCC, DEBUG_NOTICE, "Broken 'rtpmap' definition in SDP line %d = '%s' Skipping codec!\n", line_no, line); - osmo_cc_free_codec(codec); - } - } - break; - } - } - - /* if something is incomplete, abort here */ - if (osmo_cc_session_check(session, 1)) { - PDEBUG(DCC, DEBUG_NOTICE, "Parsing SDP failed.\n"); - osmo_cc_free_session(session); - return NULL; - } - - return session; -} - -void osmo_cc_debug_sdp(const char *_sdp) -{ - const unsigned char *sdp = (const unsigned char *)_sdp; - char text[256]; - int i; - - while (*sdp) { - for (i = 0; *sdp > 0 && *sdp >= 32 && i < (int)sizeof(text) - 1; i++) - text[i] = *sdp++; - text[i] = '\0'; - PDEBUG(DCC, DEBUG_DEBUG, " | %s\n", text); - while (*sdp > 0 && *sdp < 32) - sdp++; - } -} - diff --git a/src/libosmocc/sdp.h b/src/libosmocc/sdp.h deleted file mode 100644 index c9bc721..0000000 --- a/src/libosmocc/sdp.h +++ /dev/null @@ -1,6 +0,0 @@ - -char *osmo_cc_session_gensdp(struct osmo_cc_session *session); -struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf, void *priv, const char *_sdp); -int osmo_cc_payload_type_by_attrs(uint8_t *fmt, const char *name, uint32_t *rate, int *channels); -void osmo_cc_debug_sdp(const char *sdp); - diff --git a/src/libosmocc/session.c b/src/libosmocc/session.c deleted file mode 100644 index 8216c05..0000000 --- a/src/libosmocc/session.c +++ /dev/null @@ -1,640 +0,0 @@ -/* Osmo-CC: Media Session handling - * - * (C) 2016 by Andreas Eversberg - * All Rights Reserved - * - * 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 3 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, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include "../libtimer/timer.h" -#include "../libdebug/debug.h" -#include "../liboptions/options.h" -#include "endpoint.h" - -#define NTP_OFFSET 2208988800U - -void osmo_cc_set_local_peer(osmo_cc_session_config_t *conf, enum osmo_cc_session_nettype nettype, enum osmo_cc_session_addrtype addrtype, const char *address) -{ - conf->default_nettype = nettype; - conf->default_addrtype = addrtype; - conf->default_unicast_address = options_strdup(address); -} - -osmo_cc_session_t *osmo_cc_new_session(osmo_cc_session_config_t *conf, void *priv, const char *username, const char *sess_id, const char *sess_version, enum osmo_cc_session_nettype nettype, enum osmo_cc_session_addrtype addrtype, const char *unicast_address, const char *session_name, int debug) -{ - osmo_cc_session_t *session; - - if (debug) PDEBUG(DCC, DEBUG_DEBUG, "Creating session structure.\n"); - - session = calloc(1, sizeof(*session)); - if (!session) { - PDEBUG(DCC, DEBUG_ERROR, "No mem!\n"); - abort(); - } - session->config = conf; - session->priv = priv; - if (username) { - int i; - for (i = 0; username[i]; i++) { - if ((uint8_t)username[i] < 33) { - PDEBUG(DCC, DEBUG_ERROR, "Fatal error: SDP's originator (username) uses invalid characters, please fix!\n"); - abort(); - } - } - session->origin_local.username = strdup(username); - } - if (!username) - session->origin_local.username = strdup("-"); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> user name = %s\n", session->origin_local.username); - if (sess_id) - session->origin_local.sess_id = strdup(sess_id); - if (sess_version) - session->origin_local.sess_version = strdup(sess_version); - if (!sess_id || !sess_version) { - struct timeval tv; - char ntp_timestamp[32]; - /* get time NTP format time stamp (time since 1900) */ - gettimeofday(&tv, NULL); - sprintf(ntp_timestamp, "%" PRIu64, (uint64_t)tv.tv_sec + NTP_OFFSET); - if (!sess_id) - session->origin_local.sess_id = strdup(ntp_timestamp); - if (!sess_version) - session->origin_local.sess_version = strdup(ntp_timestamp); - } - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> session ID = %s\n", session->origin_local.sess_id); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> session version = %s\n", session->origin_local.sess_version); - if (nettype) - session->origin_local.nettype = strdup(osmo_cc_session_nettype2string(nettype)); - else - session->origin_local.nettype = strdup(osmo_cc_session_nettype2string(conf->default_nettype)); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> network type = %s\n", session->origin_local.nettype); - if (addrtype) - session->origin_local.addrtype = strdup(osmo_cc_session_addrtype2string(addrtype)); - else - session->origin_local.addrtype = strdup(osmo_cc_session_addrtype2string(conf->default_addrtype)); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> address type = %s\n", session->origin_local.addrtype); - if (unicast_address) - session->origin_local.unicast_address = strdup(unicast_address); - else - session->origin_local.unicast_address = strdup(conf->default_unicast_address); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> unicast address = %s\n", session->origin_local.unicast_address); - if (session_name) - session->name = strdup(session_name); - if (!session_name) - session->name = strdup("-"); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> session name = %s\n", session->name); - - return session; -} - -void osmo_cc_free_session(osmo_cc_session_t *session) -{ - PDEBUG(DCC, DEBUG_DEBUG, "Free session structure.\n"); - - free((char *)session->origin_local.username); - free((char *)session->origin_local.sess_id); - free((char *)session->origin_local.sess_version); - free((char *)session->origin_local.nettype); - free((char *)session->origin_local.addrtype); - free((char *)session->origin_local.unicast_address); - free((char *)session->origin_remote.username); - free((char *)session->origin_remote.sess_id); - free((char *)session->origin_remote.sess_version); - free((char *)session->origin_remote.nettype); - free((char *)session->origin_remote.addrtype); - free((char *)session->origin_remote.unicast_address); - free((char *)session->name); - while (session->media_list) - osmo_cc_free_media(session->media_list); - free(session); -} - -osmo_cc_session_media_t *osmo_cc_add_media(osmo_cc_session_t *session, enum osmo_cc_session_nettype nettype, enum osmo_cc_session_addrtype addrtype, const char *address, enum osmo_cc_session_media_type type, uint16_t port, enum osmo_cc_session_media_proto proto, int send, int receive, void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len), int debug) -{ - osmo_cc_session_config_t *conf = session->config; - osmo_cc_session_media_t *media, **mediap; - - media = calloc(1, sizeof(*media)); - if (!media) { - PDEBUG(DCC, DEBUG_ERROR, "No mem!\n"); - abort(); - } - media->session = session; - if (nettype) - media->connection_data_local.nettype = nettype; - else - media->connection_data_local.nettype = conf->default_nettype; - if (addrtype) - media->connection_data_local.addrtype = addrtype; - else - media->connection_data_local.addrtype = conf->default_addrtype; - if (address) - media->connection_data_local.address = strdup(address); - else - media->connection_data_local.address = strdup(conf->default_unicast_address); - media->description.type = type; - media->description.port_local = port; - media->description.proto = proto; - media->send = send; - media->receive = receive; - media->receiver = receiver; - media->tx_sequence = random(); - media->tx_timestamp = random(); - mediap = &media->session->media_list; - while (*mediap) - mediap = &((*mediap)->next); - *mediap = media; - - if (debug) PDEBUG(DCC, DEBUG_DEBUG, "Adding session media.\n"); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> network type = %s\n", osmo_cc_session_nettype2string(media->connection_data_local.nettype)); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> address type = %s\n", osmo_cc_session_addrtype2string(media->connection_data_local.addrtype)); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> address = %s\n", media->connection_data_local.address); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> media type = %s\n", osmo_cc_session_media_type2string(media->description.type)); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> media port = %d\n", media->description.port_local); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> media proto = %s\n", osmo_cc_session_media_proto2string(media->description.proto)); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, "Opening and binding media port %d\n", media->description.port_local); - - return media; -} - -void osmo_cc_free_media(osmo_cc_session_media_t *media) -{ - osmo_cc_session_media_t **mediap; - - PDEBUG(DCC, DEBUG_DEBUG, "Free session media.\n"); - - osmo_cc_rtp_close(media); - free((char *)media->connection_data_local.nettype_name); - free((char *)media->connection_data_local.addrtype_name); - free((char *)media->connection_data_local.address); - free((char *)media->connection_data_remote.nettype_name); - free((char *)media->connection_data_remote.addrtype_name); - free((char *)media->connection_data_remote.address); - while (media->codec_list) - osmo_cc_free_codec(media->codec_list); - mediap = &media->session->media_list; - while (*mediap != media) - mediap = &((*mediap)->next); - *mediap = media->next; - free(media); -} - -osmo_cc_session_codec_t *osmo_cc_add_codec(osmo_cc_session_media_t *media, const char *payload_name, uint32_t payload_rate, int payload_channels, void (*encoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len), void (*decoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len), int debug) -{ - osmo_cc_session_codec_t *codec, **codecp; - int rc; - - codec = calloc(1, sizeof(*codec)); - if (!codec) { - PDEBUG(DCC, DEBUG_ERROR, "No mem!\n"); - abort(); - } - codec->media = media; - if (payload_name) { - codec->payload_name = strdup(payload_name); - codec->payload_rate = payload_rate; - codec->payload_channels = payload_channels; - rc = osmo_cc_payload_type_by_attrs(&codec->payload_type_local, payload_name, &payload_rate, &payload_channels); - if (rc < 0) { - /* hunt for next free dynamic payload type */ - uint8_t fmt = 96; - osmo_cc_session_codec_t *c; - osmo_cc_session_for_each_codec(media->codec_list, c) { - if (c->payload_type_local >= fmt) - fmt = c->payload_type_local + 1; - } - codec->payload_type_local = fmt; - } - } - codec->encoder = encoder; - codec->decoder = decoder; - codecp = &codec->media->codec_list; - while (*codecp) - codecp = &((*codecp)->next); - *codecp = codec; - - if (debug) PDEBUG(DCC, DEBUG_DEBUG, "Adding session codec.\n"); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> payload type = %d\n", codec->payload_type_local); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> payload name = %s\n", codec->payload_name); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> payload rate = %d\n", codec->payload_rate); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> payload channels = %d\n", codec->payload_channels); - - return codec; -} - -void osmo_cc_free_codec(osmo_cc_session_codec_t *codec) -{ - osmo_cc_session_codec_t **codecp; - - PDEBUG(DCC, DEBUG_DEBUG, "Free session codec.\n"); - - free((char *)codec->payload_name); - codecp = &codec->media->codec_list; - while (*codecp != codec) - codecp = &((*codecp)->next); - *codecp = codec->next; - free(codec); -} - -int osmo_cc_session_check(osmo_cc_session_t *session, int remote) -{ - struct osmo_cc_session_origin *orig; - struct osmo_cc_session_media *media; - struct osmo_cc_session_connection_data *cd; - struct osmo_cc_session_media_description *md; - struct osmo_cc_session_codec *codec; - int i, j; - - if (remote) - orig = &session->origin_remote; - else - orig = &session->origin_local; - if (!orig->username - || !orig->sess_id - || !orig->sess_version - || !orig->nettype - || !orig->addrtype - || !orig->unicast_address) { - PDEBUG(DCC, DEBUG_NOTICE, "Missing data in session origin\n"); - return -EINVAL; - } - if (!session->name) { - PDEBUG(DCC, DEBUG_NOTICE, "Missing data in session origin\n"); - return -EINVAL; - } - if (!session->media_list) { - PDEBUG(DCC, DEBUG_NOTICE, "Missing media session\n"); - return -EINVAL; - } - i = 0; - osmo_cc_session_for_each_media(session->media_list, media) { - i++; - if (remote) - cd = &media->connection_data_remote; - else - cd = &media->connection_data_local; - if (!cd->nettype && !cd->nettype_name) { - PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d is missing connection network type\n", i); - return -EINVAL; - } - if (!cd->addrtype && !cd->addrtype_name) { - PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d is missing connection address type\n", i); - return -EINVAL; - } - if (!cd->address) { - PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d is missing connection address\n", i); - return -EINVAL; - } - md = &media->description; - if (!md->type && !md->type_name) { - PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d is missing media type\n", i); - return -EINVAL; - } - if (!md->proto && !md->proto_name) { - PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d is missing protocol\n", i); - return -EINVAL; - } - j = 0; - osmo_cc_session_for_each_codec(media->codec_list, codec) { - j++; - if (!codec->payload_name) { - PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d, codec #%d is missing name\n", i, j); - return -EINVAL; - } - if (!codec->payload_rate) { - PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d, codec #%d is missing rate\n", i, j); - return -EINVAL; - } - if (!codec->payload_channels) { - PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d, codec #%d is missing channel count\n", i, j); - return -EINVAL; - } - } - } - - return 0; -} - -/* check session description and generate SDP */ -const char *osmo_cc_session_send_offer(osmo_cc_session_t *session) -{ - const char *sdp; - int rc; - - PDEBUG(DCC, DEBUG_DEBUG, "Generating session offer and opening RTP stream.\n"); - - rc = osmo_cc_session_check(session, 0); - if (rc < 0) { - PDEBUG(DCC, DEBUG_ERROR, "Please fix!\n"); - abort(); - } - - sdp = osmo_cc_session_gensdp(session); - osmo_cc_debug_sdp(sdp); - - return sdp; -} - -osmo_cc_session_t *osmo_cc_session_receive_offer(osmo_cc_session_config_t *conf, void *priv, const char *sdp) -{ - osmo_cc_session_t *session; - int rc; - - PDEBUG(DCC, DEBUG_DEBUG, "Parsing session offer.\n"); - - osmo_cc_debug_sdp(sdp); - session = osmo_cc_session_parsesdp(conf, priv, sdp); - if (!session) - return NULL; - - rc = osmo_cc_session_check(session, 0); - if (rc < 0) { - osmo_cc_free_session(session); - return NULL; - } - - return session; -} - -void osmo_cc_session_accept_media(osmo_cc_session_media_t *media, enum osmo_cc_session_nettype nettype, enum osmo_cc_session_addrtype addrtype, const char *address, int send, int receive, void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len)) -{ - osmo_cc_session_config_t *conf = media->session->config; - - media->accepted = 1; - if (nettype) - media->connection_data_local.nettype = nettype; - else - media->connection_data_local.nettype = conf->default_nettype; - if (addrtype) - media->connection_data_local.addrtype = addrtype; - else - media->connection_data_local.addrtype = conf->default_addrtype; - free((char *)media->connection_data_local.address); - if (address) - media->connection_data_local.address = strdup(address); - else - media->connection_data_local.address = strdup(conf->default_unicast_address); - media->send = send; - media->receive = receive; - media->receiver = receiver; - - PDEBUG(DCC, DEBUG_DEBUG, "Accepting session media.\n"); - PDEBUG(DCC, DEBUG_DEBUG, " -> network type = %s\n", osmo_cc_session_nettype2string(media->connection_data_local.nettype)); - PDEBUG(DCC, DEBUG_DEBUG, " -> address type = %s\n", osmo_cc_session_addrtype2string(media->connection_data_local.addrtype)); - PDEBUG(DCC, DEBUG_DEBUG, " -> address = %s\n", media->connection_data_local.address); -} - - -void osmo_cc_session_accept_codec(osmo_cc_session_codec_t *codec, void (*encoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len), void (*decoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len)) -{ - codec->accepted = 1; - codec->encoder = encoder; - codec->decoder = decoder; - /* when we accept a codec, we just use the same payload type as the remote */ - codec->payload_type_local = codec->payload_type_remote; - - PDEBUG(DCC, DEBUG_DEBUG, "Accepting session codec.\n"); - PDEBUG(DCC, DEBUG_DEBUG, " -> payload type = %d\n", codec->payload_type_local); - PDEBUG(DCC, DEBUG_DEBUG, " -> payload name = %s\n", codec->payload_name); - PDEBUG(DCC, DEBUG_DEBUG, " -> payload rate = %d\n", codec->payload_rate); - PDEBUG(DCC, DEBUG_DEBUG, " -> payload channels = %d\n", codec->payload_channels); -} - -/* remove codecs/media that have not been accepted and generate SDP */ -const char *osmo_cc_session_send_answer(osmo_cc_session_t *session) -{ - osmo_cc_session_media_t *media; - osmo_cc_session_codec_t *codec, **codec_p; - const char *sdp; - int rc; - - PDEBUG(DCC, DEBUG_DEBUG, "Generating session answer.\n"); - - /* loop all media */ - osmo_cc_session_for_each_media(session->media_list, media) { - /* remove unaccepted codecs */ - codec_p = &media->codec_list; - codec = *codec_p; - while (codec) { - if (!codec->accepted) { - osmo_cc_free_codec(codec); - codec = *codec_p; - continue; - } - codec_p = &codec->next; - codec = *codec_p; - } - /* mark media as unused, if no codec or not accepted */ - if (!media->accepted || !media->codec_list) - media->description.port_local = 0; - } - - rc = osmo_cc_session_check(session, 0); - if (rc < 0) { - PDEBUG(DCC, DEBUG_ERROR, "Please fix!\n"); - abort(); - } - - sdp = osmo_cc_session_gensdp(session); - osmo_cc_debug_sdp(sdp); - - return sdp; -} - -/* Apply remote session description to local session description. - * If remote media's port is 0, remove from local session description. - * If codecs in the remote session description are missing, remove from local session description. - */ -static int osmo_cc_session_negotiate(osmo_cc_session_t *session_local, struct osmo_cc_session *session_remote) -{ - osmo_cc_session_media_t *media_local, *media_remote, **media_local_p; - osmo_cc_session_codec_t *codec_local, *codec_remote, **codec_local_p; - int rc; - - PDEBUG(DCC, DEBUG_DEBUG, "Negotiating session.\n"); - - /* copy remote session information */ - session_local->origin_remote.username = strdup(session_remote->origin_remote.username); - session_local->origin_remote.sess_id = strdup(session_remote->origin_remote.sess_id); - session_local->origin_remote.sess_version = strdup(session_remote->origin_remote.sess_version); - session_local->origin_remote.nettype = strdup(session_remote->origin_remote.nettype); - session_local->origin_remote.addrtype = strdup(session_remote->origin_remote.addrtype); - session_local->origin_remote.unicast_address = strdup(session_remote->origin_remote.unicast_address); - - /* loop all media */ - for (media_local = session_local->media_list, media_remote = session_remote->media_list; media_local && media_remote; media_local = media_local->next, media_remote = media_remote->next) { - /* copy remote media information */ - media_local->connection_data_remote.nettype = media_remote->connection_data_remote.nettype; - if (media_remote->connection_data_remote.nettype_name) - media_local->connection_data_remote.nettype_name = strdup(media_remote->connection_data_remote.nettype_name); - media_local->connection_data_remote.addrtype = media_remote->connection_data_remote.addrtype; - if (media_remote->connection_data_remote.addrtype_name) - media_local->connection_data_remote.addrtype_name = strdup(media_remote->connection_data_remote.addrtype_name); - if (media_remote->connection_data_remote.address) - media_local->connection_data_remote.address = strdup(media_remote->connection_data_remote.address); - media_local->description.port_remote = media_remote->description.port_remote; - media_local->send = media_remote->send; - media_local->receive = media_remote->receive; - /* loop all codecs and remove if they are not found in local session description */ - codec_local_p = &media_local->codec_list; - codec_local = *codec_local_p; - while (codec_local) { - /* search for equal codec, payload type may differe for each direction */ - osmo_cc_session_for_each_codec(media_remote->codec_list, codec_remote) { - if (!strcmp(codec_local->payload_name, codec_remote->payload_name) - && codec_local->payload_rate == codec_remote->payload_rate - && codec_local->payload_channels == codec_remote->payload_channels) - break; - } - if (!codec_remote) { - osmo_cc_free_codec(codec_local); - codec_local = *codec_local_p; - continue; - } - /* copy remote codec information */ - codec_local->payload_type_remote = codec_remote->payload_type_remote; - codec_local_p = &codec_local->next; - codec_local = *codec_local_p; - } - } - if (media_local) { - PDEBUG(DCC, DEBUG_NOTICE, "Negotiation failed, because remote endpoint returns less media streams than we offered.\n"); - return -EINVAL; - } - if (media_remote) { - PDEBUG(DCC, DEBUG_NOTICE, "Negotiation failed, because remote endpoint returns more media streams than we offered.\n"); - return -EINVAL; - } - - /* remove media with port == 0 or no codec at all */ - media_local_p = &session_local->media_list; - media_local = *media_local_p; - while (media_local) { - if (media_local->description.port_remote == 0 || !media_local->codec_list) { - osmo_cc_free_media(media_local); - media_local = *media_local_p; - continue; - } - media_local_p = &media_local->next; - media_local = *media_local_p; - } - - rc = osmo_cc_session_check(session_local, 1); - if (rc < 0) - return rc; - - return 0; -} - -int osmo_cc_session_receive_answer(osmo_cc_session_t *session, const char *sdp) -{ - osmo_cc_session_t *session_remote; - int rc; - - PDEBUG(DCC, DEBUG_DEBUG, "Parsing session answer.\n"); - - osmo_cc_debug_sdp(sdp); - session_remote = osmo_cc_session_parsesdp(session->config, NULL, sdp); - if (!session_remote) - return -EINVAL; - - rc = osmo_cc_session_check(session_remote, 1); - if (rc < 0) { - osmo_cc_free_session(session_remote); - return rc; - } - rc = osmo_cc_session_negotiate(session, session_remote); - if (rc < 0) { - osmo_cc_free_session(session_remote); - return rc; - } - osmo_cc_free_session(session_remote); - - return 0; -} - -const char *osmo_cc_session_nettype2string(enum osmo_cc_session_nettype nettype) -{ - switch (nettype) { - case osmo_cc_session_nettype_inet: - return "IN"; - default: - return NULL; - } -} - -const char *osmo_cc_session_addrtype2string(enum osmo_cc_session_addrtype addrtype) -{ - switch (addrtype) { - case osmo_cc_session_addrtype_ipv4: - return "IP4"; - case osmo_cc_session_addrtype_ipv6: - return "IP6"; - default: - return NULL; - } -} - -const char *osmo_cc_session_media_type2string(enum osmo_cc_session_media_type media_type) -{ - switch (media_type) { - case osmo_cc_session_media_type_audio: - return "audio"; - case osmo_cc_session_media_type_video: - return "video"; - default: - return NULL; - } -} - -const char *osmo_cc_session_media_proto2string(enum osmo_cc_session_media_proto media_proto) -{ - switch (media_proto) { - case osmo_cc_session_media_proto_rtp: - return "RTP/AVP"; - default: - return NULL; - } -} - -int osmo_cc_session_if_codec(osmo_cc_session_codec_t *codec, const char *name, uint32_t rate, int channels) -{ - return (!strcmp(codec->payload_name, name) - && codec->payload_rate == rate - && codec->payload_channels == channels); -} - -int osmo_cc_session_handle(osmo_cc_session_t *session) -{ - osmo_cc_session_media_t *media; - int w = 0, rc; - - osmo_cc_session_for_each_media(session->media_list, media) { - do { - rc = osmo_cc_rtp_receive(media); - if (rc >= 0) - w = 1; - } while (rc >= 0); - } - - return w; -} - diff --git a/src/libosmocc/session.h b/src/libosmocc/session.h deleted file mode 100644 index 791bcb4..0000000 --- a/src/libosmocc/session.h +++ /dev/null @@ -1,130 +0,0 @@ -/* configuration */ - -enum osmo_cc_session_nettype { - osmo_cc_session_nettype_unknown = 0, - osmo_cc_session_nettype_inet, -}; - -enum osmo_cc_session_addrtype { - osmo_cc_session_addrtype_unknown = 0, - osmo_cc_session_addrtype_ipv4, - osmo_cc_session_addrtype_ipv6, -}; - -typedef struct osmo_cc_session_config { - enum osmo_cc_session_nettype default_nettype; - enum osmo_cc_session_addrtype default_addrtype; - const char *default_unicast_address; - uint16_t rtp_port_next; - uint16_t rtp_port_from; - uint16_t rtp_port_to; -} osmo_cc_session_config_t; - -/* session description, global part: */ - -typedef struct osmo_cc_session_origin { - const char *username; - const char *sess_id; - const char *sess_version; - const char *nettype; - const char *addrtype; - const char *unicast_address; -} osmo_cc_session_origin_t; - -/* session instance */ -typedef struct osmo_cc_session { - osmo_cc_session_config_t *config; - void *priv; - osmo_cc_session_origin_t origin_local, origin_remote; - const char *name; - struct osmo_cc_session_media *media_list; -} osmo_cc_session_t; - -/* connection description: */ - -typedef struct osmo_cc_session_connection_data { - enum osmo_cc_session_nettype nettype; - const char *nettype_name; - enum osmo_cc_session_addrtype addrtype; - const char *addrtype_name; - const char *address; -} osmo_cc_session_connection_data_t; - -/* one media of session description: */ - -enum osmo_cc_session_media_type { - osmo_cc_session_media_type_unknown, - osmo_cc_session_media_type_audio, - osmo_cc_session_media_type_video, -}; - -enum osmo_cc_session_media_proto { - osmo_cc_session_media_proto_unknown, - osmo_cc_session_media_proto_rtp, -}; - -typedef struct osmo_cc_session_media_description { - enum osmo_cc_session_media_type type; - const char *type_name; - uint16_t port_local, port_remote; - enum osmo_cc_session_media_proto proto; - const char *proto_name; -} osmo_cc_session_media_description_t; - -/* media entry */ -typedef struct osmo_cc_session_media { - struct osmo_cc_session_media *next; - osmo_cc_session_t *session; - osmo_cc_session_media_description_t description; - osmo_cc_session_connection_data_t connection_data_local, connection_data_remote; - struct osmo_cc_session_codec *codec_list; - int send, receive; - void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len); - int rtp_socket; - int rtcp_socket; - uint32_t tx_ssrc, rx_ssrc; - uint16_t tx_sequence, rx_sequence; - uint32_t tx_timestamp, rx_timestamp; - int accepted; -} osmo_cc_session_media_t; - -/* codec entry */ -typedef struct osmo_cc_session_codec { - struct osmo_cc_session_codec *next; - osmo_cc_session_media_t *media; - uint8_t payload_type_local, payload_type_remote; /* local = towards local, remote = toward remote */ - const char *payload_name; - uint32_t payload_rate; - int payload_channels; - void (*encoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); - void (*decoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); - int accepted; -} osmo_cc_session_codec_t; - -#define osmo_cc_session_for_each_media(head, m) \ - for (m = (head); m; m = m->next) - -#define osmo_cc_session_for_each_codec(head, c) \ - for (c = (head); c; c = c->next) - -void osmo_cc_set_local_peer(osmo_cc_session_config_t *conf, enum osmo_cc_session_nettype nettype, enum osmo_cc_session_addrtype addrtype, const char *address); -osmo_cc_session_t *osmo_cc_new_session(osmo_cc_session_config_t *conf, void *priv, const char *username, const char *sess_id, const char *sess_version, enum osmo_cc_session_nettype nettype, enum osmo_cc_session_addrtype addrtype, const char *unicast_address, const char *session_name, int debug); -void osmo_cc_free_session(osmo_cc_session_t *session); -osmo_cc_session_media_t *osmo_cc_add_media(osmo_cc_session_t *session, enum osmo_cc_session_nettype nettype, enum osmo_cc_session_addrtype addrtype, const char *address, enum osmo_cc_session_media_type type, uint16_t port, enum osmo_cc_session_media_proto proto, int send, int receive, void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len), int debug); -void osmo_cc_free_media(osmo_cc_session_media_t *media); -osmo_cc_session_codec_t *osmo_cc_add_codec(osmo_cc_session_media_t *media, const char *playload_name, uint32_t playload_rate, int playload_channels, void (*encoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len), void (*decoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len), int debug); -void osmo_cc_free_codec(osmo_cc_session_codec_t *codec); -int osmo_cc_session_check(struct osmo_cc_session *session, int remote); -const char *osmo_cc_session_send_offer(osmo_cc_session_t *session); -osmo_cc_session_t *osmo_cc_session_receive_offer(osmo_cc_session_config_t *conf, void *priv, const char *sdp); -void osmo_cc_session_accept_media(osmo_cc_session_media_t *media, enum osmo_cc_session_nettype nettype, enum osmo_cc_session_addrtype addrtype, const char *address, int send, int receive, void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len)); -void osmo_cc_session_accept_codec(osmo_cc_session_codec_t *codec, void (*encoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len), void (*decoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len)); -const char *osmo_cc_session_send_answer(osmo_cc_session_t *session); -int osmo_cc_session_receive_answer(osmo_cc_session_t *session, const char *sdp); -const char *osmo_cc_session_nettype2string(enum osmo_cc_session_nettype nettype); -const char *osmo_cc_session_addrtype2string(enum osmo_cc_session_addrtype addrtype); -const char *osmo_cc_session_media_type2string(enum osmo_cc_session_media_type media_type); -const char *osmo_cc_session_media_proto2string(enum osmo_cc_session_media_proto media_proto); -int osmo_cc_session_if_codec(osmo_cc_session_codec_t *codec, const char *name, uint32_t rate, int channels); -int osmo_cc_session_handle(osmo_cc_session_t *session); - diff --git a/src/libosmocc/socket.c b/src/libosmocc/socket.c deleted file mode 100644 index d25e1f1..0000000 --- a/src/libosmocc/socket.c +++ /dev/null @@ -1,583 +0,0 @@ -/* Osmo-CC: Socket handling - * - * (C) 2016 by Andreas Eversberg - * All Rights Reserved - * - * 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 3 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, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../libdebug/debug.h" -#include "../libtimer/timer.h" -#include "message.h" -#include "cause.h" -#include "socket.h" - -static const char version_string[] = OSMO_CC_VERSION; - -static int _getaddrinfo(const char *host, uint16_t port, struct addrinfo **result) -{ - char portstr[8]; - struct addrinfo hints; - int rc; - - sprintf(portstr, "%d", port); - - /* bind socket */ - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; - hints.ai_protocol = 0; - hints.ai_canonname = NULL; - hints.ai_addr = NULL; - hints.ai_next = NULL; - - rc = getaddrinfo(host, portstr, &hints, result); - if (rc < 0) { - PDEBUG(DCC, DEBUG_ERROR, "Failed to create socket for host '%s', port '%d': %s.\n", host, port, gai_strerror(rc)); - return rc; - } - return rc; -} - -/* send a reject message toward CC process. - * the CC process will change the reject message to a release message when not in INIT_IN state - */ -static void rej_msg(osmo_cc_socket_t *os, uint32_t callref, uint8_t socket_cause, uint8_t isdn_cause, uint16_t sip_cause) -{ - osmo_cc_msg_t *msg; - - /* create message */ - msg = osmo_cc_new_msg(OSMO_CC_MSG_REJ_REQ); - if (!msg) - abort(); - - /* add cause */ - osmo_cc_add_ie_cause(msg, os->location, isdn_cause, sip_cause, socket_cause); - osmo_cc_convert_cause_msg(msg); - - /* message down */ - os->recv_msg_cb(os->priv, callref, msg); -} - -void tx_keepalive_timeout(struct timer *timer) -{ - osmo_cc_conn_t *conn = (osmo_cc_conn_t *)timer->priv; - osmo_cc_msg_t *msg; - - /* send keepalive message */ - msg = osmo_cc_new_msg(OSMO_CC_MSG_DUMMY_REQ); - osmo_cc_msg_list_enqueue(&conn->os->write_list, msg, conn->callref); - timer_start(&conn->tx_keepalive_timer, OSMO_CC_SOCKET_TX_KEEPALIVE); -} - -static void close_conn(osmo_cc_conn_t *conn, uint8_t socket_cause); - -void rx_keepalive_timeout(struct timer *timer) -{ - osmo_cc_conn_t *conn = (osmo_cc_conn_t *)timer->priv; - - PDEBUG(DCC, DEBUG_ERROR, "OsmoCC-Socket failed due to timeout.\n"); - close_conn(conn, OSMO_CC_SOCKET_CAUSE_TIMEOUT); -} - -/* create socket process and bind socket */ -int osmo_cc_open_socket(osmo_cc_socket_t *os, const char *host, uint16_t port, void *priv, void (*recv_msg_cb)(void *priv, uint32_t callref, osmo_cc_msg_t *msg), uint8_t location) -{ - int try = 0, auto_port = 0; - struct addrinfo *result, *rp; - int rc, sock, flags; - - memset(os, 0, sizeof(*os)); - -try_again: - /* check for given port, if NULL, autoselect port */ - if (!port || auto_port) { - port = OSMO_CC_DEFAULT_PORT + try; - try++; - auto_port = 1; - } - - PDEBUG(DCC, DEBUG_DEBUG, "Create socket for host %s port %d.\n", host, port); - - rc = _getaddrinfo(host, port, &result); - if (rc < 0) - return rc; - for (rp = result; rp; rp = rp->ai_next) { - int on = 1; - sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - if (sock < 0) - continue; - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&on, sizeof(on)); - rc = bind(sock, rp->ai_addr, rp->ai_addrlen); - if (rc == 0) - break; - close(sock); - } - freeaddrinfo(result); - if (rp == NULL) { - if (auto_port && port < OSMO_CC_DEFAULT_PORT_MAX) { - PDEBUG(DCC, DEBUG_DEBUG, "Failed to bind host %s port %d, trying again.\n", host, port); - goto try_again; - } - PDEBUG(DCC, DEBUG_ERROR, "Failed to bind given host %s port %d.\n", host, port); - return -EIO; - } - - /* listen to socket */ - rc = listen(sock, 10); - if (rc < 0) { - PDEBUG(DCC, DEBUG_ERROR, "Failed to listen on socket.\n"); - return rc; - } - - /* set nonblocking io */ - flags = fcntl(sock, F_GETFL); - flags |= O_NONBLOCK; - fcntl(sock, F_SETFL, flags); - - os->socket = sock; - os->recv_msg_cb = recv_msg_cb; - os->priv = priv; - os->location = location; - - return port; -} - -/* create a connection */ -static osmo_cc_conn_t *open_conn(osmo_cc_socket_t *os, int sock, uint32_t callref, int read_setup) -{ - osmo_cc_conn_t *conn, **connp; - - /* create connection */ - conn = calloc(1, sizeof(*conn)); - if (!conn) { - PDEBUG(DCC, DEBUG_ERROR, "No mem!\n"); - abort(); - } - conn->os = os; - conn->socket = sock; - conn->read_version = 1; - conn->write_version = 1; - conn->read_setup = read_setup; - if (callref) - conn->callref = callref; - else - conn->callref = osmo_cc_new_callref(); - - timer_init(&conn->tx_keepalive_timer, tx_keepalive_timeout, conn); - timer_init(&conn->rx_keepalive_timer, rx_keepalive_timeout, conn); - timer_start(&conn->tx_keepalive_timer, OSMO_CC_SOCKET_TX_KEEPALIVE); - timer_start(&conn->rx_keepalive_timer, OSMO_CC_SOCKET_RX_KEEPALIVE); - - PDEBUG(DCC, DEBUG_DEBUG, "New socket connection (callref %d).\n", conn->callref); - - /* attach to list */ - connp = &os->conn_list; - while (*connp) - connp = &((*connp)->next); - *connp = conn; - - return conn; -} - -/* remove a connection */ -static void close_conn(osmo_cc_conn_t *conn, uint8_t socket_cause) -{ - osmo_cc_conn_t **connp; - osmo_cc_msg_list_t *ml; - - /* detach connection first, to prevent a destruction during message handling (double free) */ - connp = &conn->os->conn_list; - while (*connp != conn) - connp = &((*connp)->next); - *connp = conn->next; - /* send reject message, if socket_cause is set */ - if (socket_cause && !conn->read_setup) { - /* receive a release or reject (depending on state), but only if we sent a setup */ - rej_msg(conn->os, conn->callref, socket_cause, 0, 0); - } - - PDEBUG(DCC, DEBUG_DEBUG, "Destroy socket connection (callref %d).\n", conn->callref); - - /* close socket */ - if (conn->socket) - close(conn->socket); - /* free partly received message */ - if (conn->read_msg) - osmo_cc_free_msg(conn->read_msg); - /* free send queue */ - while ((ml = conn->write_list)) { - osmo_cc_free_msg(ml->msg); - conn->write_list = ml->next; - free(ml); - } - /* free timers */ - timer_exit(&conn->tx_keepalive_timer); - timer_exit(&conn->rx_keepalive_timer); - /* free connection (already detached above) */ - free(conn); -} - -/* close socket and remove */ -void osmo_cc_close_socket(osmo_cc_socket_t *os) -{ - osmo_cc_msg_list_t *ml; - - PDEBUG(DCC, DEBUG_DEBUG, "Destroy socket.\n"); - - /* free all connections */ - while (os->conn_list) - close_conn(os->conn_list, 0); - /* close socket */ - if (os->socket > 0) { - close(os->socket); - os->socket = 0; - } - /* free send queue */ - while ((ml = os->write_list)) { - osmo_cc_free_msg(ml->msg); - os->write_list = ml->next; - free(ml); - } -} - -/* send message to send_queue of sock instance */ -int osmo_cc_sock_send_msg(osmo_cc_socket_t *os, uint32_t callref, osmo_cc_msg_t *msg, const char *host, uint16_t port) -{ - osmo_cc_msg_list_t *ml; - - /* turn _IND into _REQ and _CNF into _RSP */ - msg->type &= ~1; - - /* create list entry */ - ml = osmo_cc_msg_list_enqueue(&os->write_list, msg, callref); - if (host) - strncpy(ml->host, host, sizeof(ml->host) - 1); - ml->port = port; - - return 0; -} - -/* receive message - * return 1 if work was done. - */ -static int receive_conn(osmo_cc_conn_t *conn) -{ - uint8_t socket_cause = OSMO_CC_SOCKET_CAUSE_BROKEN_PIPE; - int rc; - osmo_cc_msg_t *msg; - uint8_t msg_type; - int len; - int work = 0; - - /* get version from remote */ - if (conn->read_version) { - rc = recv(conn->socket, conn->read_version_string + conn->read_version_pos, strlen(version_string) - conn->read_version_pos, 0); - if (rc < 0 && errno == EAGAIN) - return work; - work = 1; - if (rc <= 0) { - goto close; - } - conn->read_version_pos += rc; - if (conn->read_version_pos == strlen(version_string)) { - conn->read_version = 0; - if (!!memcmp(conn->read_version_string, version_string, strlen(version_string) - 1)) { - PDEBUG(DCC, DEBUG_NOTICE, "Remote does not seem to be an Osmo-CC socket, rejecting!\n"); - socket_cause = OSMO_CC_SOCKET_CAUSE_FAILED; - goto close; - } - if (conn->read_version_string[strlen(version_string) - 1] != version_string[strlen(version_string) - 1]) { - PDEBUG(DCC, DEBUG_NOTICE, "Remote Osmo-CC socket has wrong version (local=%s, remote=%s), rejecting!\n", version_string, conn->read_version_string); - socket_cause = OSMO_CC_SOCKET_CAUSE_VERSION_MISMATCH; - goto close; - } - } else - return work; - } - -try_next_message: - /* read message header from remote */ - if (!conn->read_msg) { - rc = recv(conn->socket, ((uint8_t *)&conn->read_hdr) + conn->read_pos, sizeof(conn->read_hdr) - conn->read_pos, 0); - if (rc < 0 && errno == EAGAIN) - return work; - work = 1; - if (rc <= 0) { - goto close; - } - conn->read_pos += rc; - if (conn->read_pos == sizeof(conn->read_hdr)) { - conn->read_msg = osmo_cc_new_msg(conn->read_hdr.type); - if (!conn->read_msg) - abort(); - conn->read_msg->length_networkorder = conn->read_hdr.length_networkorder; - /* prepare for reading message */ - conn->read_pos = 0; - } else - return work; - } - - /* read message data from remote */ - msg = conn->read_msg; - len = ntohs(msg->length_networkorder); - if (len == 0) - goto empty_message; - rc = recv(conn->socket, msg->data + conn->read_pos, len - conn->read_pos, 0); - if (rc < 0 && errno == EAGAIN) - return work; - work = 1; - if (rc <= 0) { - goto close; - } - conn->read_pos += rc; - if (conn->read_pos == len) { -empty_message: - /* start RX keepalive timeer, if not already */ - timer_start(&conn->rx_keepalive_timer, OSMO_CC_SOCKET_RX_KEEPALIVE); - /* we got our setup message, so we clear the flag */ - conn->read_setup = 0; - /* prepare for reading header */ - conn->read_pos = 0; - /* detach message first, because the connection might be destroyed during message handling */ - msg_type = conn->read_msg->type; - conn->read_msg = NULL; - /* drop dummy or forward message */ - if (msg_type == OSMO_CC_MSG_DUMMY_REQ) - osmo_cc_free_msg(msg); - else - conn->os->recv_msg_cb(conn->os->priv, conn->callref, msg); - if (msg_type == OSMO_CC_MSG_REL_REQ || msg_type == OSMO_CC_MSG_REJ_REQ) { - PDEBUG(DCC, DEBUG_DEBUG, "closing socket because we received a release or reject message.\n"); - close_conn(conn, 0); - return 1; /* conn removed */ - } - goto try_next_message; - } - return work; - -close: - PDEBUG(DCC, DEBUG_ERROR, "OsmoCC-Socket failed, socket cause %d.\n", socket_cause); - close_conn(conn, socket_cause); - return work; /* conn removed */ -} - -/* transmit message - * return 1 if work was done. - */ -static int transmit_conn(osmo_cc_conn_t *conn) -{ - uint8_t socket_cause = OSMO_CC_SOCKET_CAUSE_BROKEN_PIPE; - int rc; - osmo_cc_msg_t *msg; - int len; - osmo_cc_msg_list_t *ml; - int work = 0; - - /* send socket version to remote */ - if (conn->write_version) { - rc = write(conn->socket, version_string, strlen(version_string)); - if (rc < 0 && errno == EAGAIN) - return work; - work = 1; - if (rc <= 0) { - goto close; - } - if (rc != strlen(version_string)) { - PDEBUG(DCC, DEBUG_ERROR, "short write, please fix handling!\n"); - abort(); - } - conn->write_version = 0; - } - - /* send message to remote */ - while (conn->write_list) { - timer_stop(&conn->tx_keepalive_timer); - msg = conn->write_list->msg; - len = sizeof(*msg) + ntohs(msg->length_networkorder); - rc = write(conn->socket, msg, len); - if (rc < 0 && errno == EAGAIN) - return work; - work = 1; - if (rc <= 0) { - goto close; - } - if (rc != len) { - PDEBUG(DCC, DEBUG_ERROR, "short write, please fix handling!\n"); - abort(); - } - /* close socket after sending release/reject message */ - if (msg->type == OSMO_CC_MSG_REL_REQ || msg->type == OSMO_CC_MSG_REJ_REQ) { - PDEBUG(DCC, DEBUG_DEBUG, "closing socket because we sent a release or reject message.\n"); - close_conn(conn, 0); - return work; /* conn removed */ - } - /* free message after sending */ - ml = conn->write_list; - conn->write_list = ml->next; - osmo_cc_free_msg(msg); - free(ml); - } - - /* start TX keepalive timeer, if not already - * because we stop at every message above, we actually restart the timer here. - * only if there is no message for the amount of time, the timer fires. - */ - if (!timer_running(&conn->tx_keepalive_timer)) - timer_start(&conn->tx_keepalive_timer, OSMO_CC_SOCKET_TX_KEEPALIVE); - - return work; - -close: - PDEBUG(DCC, DEBUG_NOTICE, "OsmoCC-Socket failed.\n"); - close_conn(conn, socket_cause); - return work; /* conn removed */ -} - -/* handle all sockets of a socket interface - * return 1 if work was done. - */ -int osmo_cc_handle_socket(osmo_cc_socket_t *os) -{ - struct sockaddr_storage sa; - socklen_t slen = sizeof(sa); - int sock; - osmo_cc_conn_t *conn; - osmo_cc_msg_list_t *ml, **mlp; - int flags; - struct addrinfo *result, *rp; - int rc; - int work = 0; - - /* handle messages in send queue */ - while ((ml = os->write_list)) { - work = 1; - /* detach list entry */ - os->write_list = ml->next; - ml->next = NULL; - /* search for socket connection */ - for (conn = os->conn_list; conn; conn=conn->next) { - if (conn->callref == ml->callref) - break; - } - if (conn) { - /* attach to list */ - mlp = &conn->write_list; - while (*mlp) - mlp = &((*mlp)->next); - *mlp = ml; - /* done with message */ - continue; - } - - /* reject and release are ignored */ - if (ml->msg->type == OSMO_CC_MSG_REJ_REQ - || ml->msg->type == OSMO_CC_MSG_REL_REQ) { - /* drop message */ - osmo_cc_free_msg(ml->msg); - free(ml); - /* done with message */ - continue; - } - - /* reject, if this is not a setup message */ - if (ml->msg->type != OSMO_CC_MSG_SETUP_REQ - && ml->msg->type != OSMO_CC_MSG_ATTACH_REQ) { - PDEBUG(DCC, DEBUG_ERROR, "Message with unknown callref.\n"); - rej_msg(os, ml->callref, 0, OSMO_CC_ISDN_CAUSE_INVAL_CALLREF, 0); - /* drop message */ - osmo_cc_free_msg(ml->msg); - free(ml); - /* done with message */ - continue; - } - /* connect to remote */ - rc = _getaddrinfo(ml->host, ml->port, &result); - if (rc < 0) { - rej_msg(os, ml->callref, OSMO_CC_SOCKET_CAUSE_FAILED, 0, 0); - /* drop message */ - osmo_cc_free_msg(ml->msg); - free(ml); - /* done with message */ - continue; - } - for (rp = result; rp; rp = rp->ai_next) { - sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - if (sock < 0) - continue; - /* set nonblocking io */ - flags = fcntl(sock, F_GETFL); - flags |= O_NONBLOCK; - fcntl(sock, F_SETFL, flags); - /* connect */ - rc = connect(sock, rp->ai_addr, rp->ai_addrlen); - if (rc == 0 || errno == EINPROGRESS) - break; - close(sock); - } - freeaddrinfo(result); - if (rp == NULL) { - PDEBUG(DCC, DEBUG_ERROR, "Failed to connect to given host %s port %d.\n", ml->host, ml->port); - rej_msg(os, ml->callref, OSMO_CC_SOCKET_CAUSE_FAILED, 0, 0); - /* drop message */ - osmo_cc_free_msg(ml->msg); - free(ml); - /* done with message */ - continue; - } - /* create connection */ - conn = open_conn(os, sock, ml->callref, 0); - /* attach to list */ - conn->write_list = ml; - /* done with (setup) message */ - } - - /* handle new socket connection */ - while ((sock = accept(os->socket, (struct sockaddr *)&sa, &slen)) > 0) { - work = 1; - /* set nonblocking io */ - flags = fcntl(sock, F_GETFL); - flags |= O_NONBLOCK; - fcntl(sock, F_SETFL, flags); - /* create connection */ - open_conn(os, sock, 0, 1); - } - - /* start with list after each read/write, because while handling (the message), one or more connections may be destroyed */ - for (conn = os->conn_list; conn; conn=conn->next) { - /* check for rx */ - work = receive_conn(conn); - /* if "change" is set, connection list might have changed, so we restart processing the list */ - if (work) - break; - /* check for tx */ - work = transmit_conn(conn); - /* if "change" is set, connection list might have changed, so we restart processing the list */ - if (work) - break; - } - - return work; -} - diff --git a/src/libosmocc/socket.h b/src/libosmocc/socket.h deleted file mode 100644 index bcd8b7c..0000000 --- a/src/libosmocc/socket.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef OSMO_CC_SOCKET_H -#define OSMO_CC_SOCKET_H - -#define OSMO_CC_DEFAULT_PORT 4200 -#define OSMO_CC_DEFAULT_PORT_MAX 4219 - -#define OSMO_CC_SOCKET_TX_KEEPALIVE 10.0 -#define OSMO_CC_SOCKET_RX_KEEPALIVE 20.0 - -struct osmo_cc_socket; - -typedef struct osmo_cc_conn { - struct osmo_cc_conn *next; - struct osmo_cc_socket *os; - int socket; - uint32_t callref; - int read_setup; - int read_version; - char read_version_string[sizeof(OSMO_CC_VERSION)]; /* must include 0-termination */ - int read_version_pos; - int write_version; - osmo_cc_msg_t read_hdr; - osmo_cc_msg_t *read_msg; - int read_pos; - osmo_cc_msg_list_t *write_list; - struct timer tx_keepalive_timer; - struct timer rx_keepalive_timer; -} osmo_cc_conn_t; - -typedef struct osmo_cc_socket { - int socket; - osmo_cc_conn_t *conn_list; - osmo_cc_msg_list_t *write_list; - void (*recv_msg_cb)(void *priv, uint32_t callref, osmo_cc_msg_t *msg); - void *priv; - uint8_t location; -} osmo_cc_socket_t; - -int osmo_cc_open_socket(osmo_cc_socket_t *os, const char *host, uint16_t port, void *priv, void (*recv_msg_cb)(void *priv, uint32_t callref, osmo_cc_msg_t *msg), uint8_t location); -void osmo_cc_close_socket(osmo_cc_socket_t *os); -int osmo_cc_sock_send_msg(osmo_cc_socket_t *os, uint32_t callref, osmo_cc_msg_t *msg, const char *host, uint16_t port); -int osmo_cc_handle_socket(osmo_cc_socket_t *os); - -#endif /* OSMO_CC_SOCKET_H */ diff --git a/src/libtimer/Makefile.am b/src/libtimer/Makefile.am deleted file mode 100644 index 538670a..0000000 --- a/src/libtimer/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) - -noinst_LIBRARIES = libtimer.a - -libtimer_a_SOURCES = \ - timer.c diff --git a/src/libtimer/timer.c b/src/libtimer/timer.c deleted file mode 100644 index 174533f..0000000 --- a/src/libtimer/timer.c +++ /dev/null @@ -1,119 +0,0 @@ -/* Timer handling - * - * (C) 2016 by Andreas Eversberg - * All Rights Reserved - * - * 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 3 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, see . - */ - -#include -#include -#include -#include -//#include -#include -#include -#include "timer.h" - -static struct timer *timer_head = NULL; -static struct timer **timer_tail_p = &timer_head; - -double get_time(void) -{ - static struct timespec tv; - - clock_gettime(CLOCK_REALTIME, &tv); - - return (double)tv.tv_sec + (double)tv.tv_nsec / 1000000000.0; -} - -void timer_init(struct timer *timer, void (*fn)(struct timer *timer), void *priv) -{ - if (timer->linked) { - fprintf(stderr, "Timer is already initialized, aborting!\n"); - abort(); - } - - timer->timeout = 0; - timer->fn = fn; - timer->priv = priv; - timer->next = NULL; - *timer_tail_p = timer; - timer_tail_p = &timer->next; - timer->linked = 1; -} - -void timer_exit(struct timer *timer) -{ - timer_tail_p = &timer_head; - while (*timer_tail_p) { - if (timer == *timer_tail_p) - *timer_tail_p = (*timer_tail_p)->next; - else - timer_tail_p = &((*timer_tail_p)->next); - } - timer->linked = 0; -} - -void timer_start(struct timer *timer, double duration) -{ - if (!timer->linked) { - fprintf(stderr, "Timer is not initialized, aborting!\n"); - abort(); - } - - timer->duration = duration; - timer->timeout = get_time() + duration; -} - -void timer_stop(struct timer *timer) -{ - if (!timer->linked) { - fprintf(stderr, "Timer is not initialized, aborting!\n"); - abort(); - } - - timer->timeout = 0; -} - -int timer_running(struct timer *timer) -{ - if (!timer->linked) { - fprintf(stderr, "Timer is not initialized, aborting!\n"); - abort(); - } - - return (timer->timeout != 0); -} - -void process_timer(void) -{ - struct timer *timer; - double now; - - now = get_time(); - -again: - timer = timer_head; - - while (timer) { - if (timer->linked && timer->timeout > 0 && now >= timer->timeout) { - timer->timeout = 0; - timer->fn(timer); - goto again; - } - timer = timer->next; - } -} - diff --git a/src/libtimer/timer.h b/src/libtimer/timer.h deleted file mode 100644 index 2073a8f..0000000 --- a/src/libtimer/timer.h +++ /dev/null @@ -1,18 +0,0 @@ - -struct timer { - struct timer *next; - int linked; /* set is timer is initialized and linked */ - double duration; - double timeout; - void (*fn)(struct timer *timer); - void *priv; -}; - -double get_time(void); -void timer_init(struct timer *timer, void (*fn)(struct timer *timer), void *priv); -void timer_exit(struct timer *timer); -void timer_start(struct timer *timer, double duration); -void timer_stop(struct timer *timer); -int timer_running(struct timer *timer); -void process_timer(void); - diff --git a/src/sip/Makefile.am b/src/sip/Makefile.am index ec5bc33..ca20191 100644 --- a/src/sip/Makefile.am +++ b/src/sip/Makefile.am @@ -9,9 +9,9 @@ osmo_cc_sip_endpoint_SOURCES = \ osmo_cc_sip_endpoint_LDADD = \ $(COMMON_LA) \ - ../libdebug/libdebug.a \ ../liboptions/liboptions.a \ - ../libtimer/libtimer.a \ - ../libosmocc/libosmocc.a \ + ../liblogging/liblogging.a \ + $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOCC_LIBS) \ $(SOFIA_LIBS) diff --git a/src/sip/main.c b/src/sip/main.c index 41c0ec4..717b03e 100644 --- a/src/sip/main.c +++ b/src/sip/main.c @@ -24,7 +24,8 @@ #include #include #include -#include "../libdebug/debug.h" +#include +#include "../liblogging/logging.h" #include "../liboptions/options.h" #include "sip.h" @@ -77,7 +78,7 @@ static void print_help() printf(" --config [~/]\n"); printf(" Give a config file to use. If it starts with '~/', path is at home dir.\n"); printf(" Each line in config file is one option, '-' or '--' must not be given!\n"); - debug_print_help(); + logging_print_help(); printf(" -D --sofia-debug \n"); printf(" A level of 0 is off, a level of 9 is full debugging. (default = %d)\n", sofia_debug); printf(" --send-rap\n"); @@ -205,11 +206,9 @@ static int handle_options(int short_option, int argi, char **argv) print_help(); return 0; case 'v': - if (!strcasecmp(argv[argi], "list")) { - debug_list_cat(); + rc = parse_logging_opt(argv[argi]); + if (rc > 0) return 0; - } - rc = parse_debug_opt(argv[argi]); if (rc < 0) { fprintf(stderr, "Failed to parse debug option, please use -h for help.\n"); return rc; @@ -338,6 +337,8 @@ int main(int argc, char *argv[]) { int argi, rc; + logging_init(); + cc_argv[cc_argc++] = options_strdup("remote auto"); /* handle options / config file */ @@ -358,24 +359,24 @@ int main(int argc, char *argv[]) remote_auth = 1; if (!local_peer) { - PDEBUG(DSIP, DEBUG_ERROR, "You must specify local SIP peer!\n"); + LOGP(DSIP, LOGL_ERROR, "You must specify local SIP peer!\n"); goto error; } if (!remote_peer && !local_register) { - PDEBUG(DSIP, DEBUG_ERROR, "You must specify remote SIP peer!\n"); + LOGP(DSIP, LOGL_ERROR, "You must specify remote SIP peer!\n"); goto error; } if (!auth_user && local_auth) { - PDEBUG(DSIP, DEBUG_ERROR, "You must specify authentication parameters!\n"); + LOGP(DSIP, LOGL_ERROR, "You must specify authentication parameters!\n"); goto error; } if (!cc_argc || !!strncasecmp(cc_argv[0], "help", 4)) { sip_ep = sip_endpoint_create(user_agent, remote_user_agent, send_no_ringing_after_progress, receive_no_ringing_after_progress, name, local_user, local_peer, remote_user, remote_peer, asserted_id, local_register, remote_register, remote_nat_sip, remote_nat_rtp, register_user, register_peer, local_auth, remote_auth, auth_user, auth_password, auth_realm, public_ip, stun_server, register_interval, options_interval, stun_interval, expires, block_failure); if (!sip_ep) { - PDEBUG(DSIP, DEBUG_ERROR, "SIP initializing failed!\n"); + LOGP(DSIP, LOGL_ERROR, "SIP initializing failed!\n"); goto error; } } @@ -390,13 +391,13 @@ int main(int argc, char *argv[]) signal(SIGPIPE, sighandler); while (!quit) { - int w; - process_timer(); + int work; sip_handle(sip_ep); do { - w = 0; - w |= osmo_cc_handle(); - } while (w); + work = 0; + work |= osmo_cc_handle(); + } while (work); + osmo_select_main(1); usleep(1000); } diff --git a/src/sip/sip.c b/src/sip/sip.c index dfc8daf..a4110cf 100755 --- a/src/sip/sip.c +++ b/src/sip/sip.c @@ -23,7 +23,11 @@ #include #include #include -#include "../libdebug/debug.h" +#include +#include +#include +#include +#include "../liblogging/logging.h" #include #include #include @@ -44,7 +48,7 @@ #define NUTAG_WITH_THIS_MSG(msg) nutag_with, tag_ptr_v(msg) -static void invite_option_timeout(struct timer *timer); +static void invite_option_timeout(void *data); call_t *call_create(sip_endpoint_t *sip_ep) { @@ -52,7 +56,7 @@ call_t *call_create(sip_endpoint_t *sip_ep) call = calloc(1, sizeof(*call)); if (!call) { - PDEBUG(DSIP, DEBUG_ERROR, "No memory!\n"); + LOGP(DSIP, LOGL_ERROR, "No memory!\n"); abort(); } @@ -63,9 +67,9 @@ call_t *call_create(sip_endpoint_t *sip_ep) call->sip_ep = sip_ep; - timer_init(&call->invite_option_timer, invite_option_timeout, call); + osmo_timer_setup(&call->invite_option_timer, invite_option_timeout, call); - PDEBUG(DSIP, DEBUG_DEBUG, "Created new call\n"); + LOGP(DSIP, LOGL_DEBUG, "Created new call\n"); return call; } @@ -85,11 +89,11 @@ void call_destroy(call_t *call) free(call->sdp_request); free(call->sdp_response); - timer_exit(&call->invite_option_timer); + osmo_timer_del(&call->invite_option_timer); free(call); - PDEBUG(DSIP, DEBUG_DEBUG, "destroyed call instance\n"); + LOGP(DSIP, LOGL_DEBUG, "destroyed call instance\n"); } static const char *state_names[] = { @@ -105,7 +109,7 @@ static void new_state(call_t *call, enum sip_state state) { if (call->state == state) return; - PDEBUG(DSIP, DEBUG_DEBUG, "Changing state %s -> %s\n", state_names[call->state], state_names[state]); + LOGP(DSIP, LOGL_DEBUG, "Changing state %s -> %s\n", state_names[call->state], state_names[state]); call->state = state; } @@ -124,7 +128,7 @@ static const char *sdp_replace_contact(const char *input, const char *address) type = "IP6"; break; default: - PDEBUG(DSIP, DEBUG_ERROR, "Public IP '%s' is not IPv4 nor IPv6, please correct config!\n", address); + LOGP(DSIP, LOGL_ERROR, "Public IP '%s' is not IPv4 nor IPv6, please correct config!\n", address); return input; } @@ -196,14 +200,14 @@ static int authenticate(sip_endpoint_t *sip_ep, nua_handle_t *nh, sip_t const *s char *cur; char authentication[256] = ""; - PDEBUG(DSIP, DEBUG_DEBUG, "challenge order received\n"); + LOGP(DSIP, LOGL_DEBUG, "challenge order received\n"); if (!sip_ep->authenticate_remote) { - PDEBUG(DSIP, DEBUG_NOTICE, "No remote authentication enabled, cannot authenticate us towards remote peer.\n"); + LOGP(DSIP, LOGL_NOTICE, "No remote authentication enabled, cannot authenticate us towards remote peer.\n"); return -1; } if (!sip_ep->auth_user[0]) { - PDEBUG(DSIP, DEBUG_NOTICE, "No credentials available\n"); + LOGP(DSIP, LOGL_NOTICE, "No credentials available\n"); return -1; } @@ -212,7 +216,7 @@ static int authenticate(sip_endpoint_t *sip_ep, nua_handle_t *nh, sip_t const *s } else if (sip->sip_proxy_authenticate) { authenticate = sip->sip_proxy_authenticate; } else { - PDEBUG(DSIP, DEBUG_NOTICE, "No authentication header found\n"); + LOGP(DSIP, LOGL_NOTICE, "No authentication header found\n"); return -1; } @@ -227,13 +231,13 @@ static int authenticate(sip_endpoint_t *sip_ep, nua_handle_t *nh, sip_t const *s } if (!scheme || !realm) { - PDEBUG(DSIP, DEBUG_NOTICE, "No scheme or no realm in authentication header found\n"); + LOGP(DSIP, LOGL_NOTICE, "No scheme or no realm in authentication header found\n"); return -1; } snprintf(authentication, sizeof(authentication) - 1, "%s:%s:%s:%s", scheme, realm, sip_ep->auth_user, sip_ep->auth_password); authentication[sizeof(authentication) - 1] = '\0'; - PDEBUG(DSIP, DEBUG_DEBUG, "auth: '%s'\n", authentication); + LOGP(DSIP, LOGL_DEBUG, "auth: '%s'\n", authentication); nua_authenticate(nh, /*SIPTAG_EXPIRES_STR("3600"),*/ NUTAG_AUTH(authentication), TAG_END()); @@ -299,7 +303,7 @@ static int check_authorization(sip_authorization_t const *authorization, const c *p = '\0'; } - PDEBUG(DSIP, DEBUG_DEBUG, "Found in Auth header: %s = %s\n", var, val); + LOGP(DSIP, LOGL_DEBUG, "Found in Auth header: %s = %s\n", var, val); if (!strcasecmp(var, "username")) { username = strdup(val); } else if (!strcasecmp(var, "realm")) { @@ -348,7 +352,7 @@ static int check_authorization(sip_authorization_t const *authorization, const c /* perform hash */ snprintf(temp, sizeof(temp) - 1, "%s:%s:%s", check_user, realm, check_pass); temp[sizeof(temp) - 1] = '\0'; - PDEBUG(DSIP, DEBUG_DEBUG, "First hash: %s\n", temp); + LOGP(DSIP, LOGL_DEBUG, "First hash: %s\n", temp); su_md5_init(&md5_ctx); su_md5_strupdate(&md5_ctx, temp); su_md5_hexdigest(&md5_ctx, first_digest); @@ -356,7 +360,7 @@ static int check_authorization(sip_authorization_t const *authorization, const c snprintf(temp, sizeof(temp) - 1, "%s:%s", regstr, uri); temp[sizeof(temp) - 1] = '\0'; - PDEBUG(DSIP, DEBUG_DEBUG, "Second hash: %s\n", temp); + LOGP(DSIP, LOGL_DEBUG, "Second hash: %s\n", temp); su_md5_init(&md5_ctx); su_md5_strupdate(&md5_ctx, temp); su_md5_hexdigest(&md5_ctx, second_digest); @@ -367,7 +371,7 @@ static int check_authorization(sip_authorization_t const *authorization, const c else snprintf(temp, sizeof(temp) - 1, "%s:%s:%s", first_digest, nonce, second_digest); temp[sizeof(temp) - 1] = '\0'; - PDEBUG(DSIP, DEBUG_DEBUG, "Third hash: %s\n", temp); + LOGP(DSIP, LOGL_DEBUG, "Third hash: %s\n", temp); su_md5_init(&md5_ctx); su_md5_strupdate(&md5_ctx, temp); su_md5_hexdigest(&md5_ctx, third_digest); @@ -434,20 +438,20 @@ static void release_and_destroy(call_t *call, uint8_t cc_isdn_cause, uint16_t cc if (call->nua_handle && (isdn_cause || sip_cause)) { if (call->state == SIP_STATE_IN_INVITE) { - PDEBUG(DSIP, DEBUG_INFO, "Sending INVITE response: %d %s (callref %d)\n", sip_cause, sip_cause_text, cc_callref); + LOGP(DSIP, LOGL_INFO, "Sending INVITE response: %d %s (callref %d)\n", sip_cause, sip_cause_text, cc_callref); nua_respond(call->nua_handle, (sip_cause < 300) ? 486 : sip_cause, sip_cause_text, // if no usable sip_cause, use 486 (Busy Here) TAG_IF(isdn_cause_str[0], SIPTAG_REASON_STR(isdn_cause_str)), TAG_END()); } else if (call->state == SIP_STATE_OUT_INVITE) { - PDEBUG(DSIP, DEBUG_INFO, "Sending CANCEL (callref %d)\n", call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Sending CANCEL (callref %d)\n", call->cc_callref); nua_cancel(call->nua_handle, TAG_IF(sip_cause_str[0], SIPTAG_REASON_STR(sip_cause_str)), TAG_IF(isdn_cause_str[0], SIPTAG_REASON_STR(isdn_cause_str)), TAG_END()); return; } else { - PDEBUG(DSIP, DEBUG_INFO, "Sending BYE (callref %d)\n", call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Sending BYE (callref %d)\n", call->cc_callref); nua_bye(call->nua_handle, TAG_IF(sip_cause_str[0], SIPTAG_REASON_STR(sip_cause_str)), TAG_IF(isdn_cause_str[0], SIPTAG_REASON_STR(isdn_cause_str)), @@ -457,7 +461,7 @@ static void release_and_destroy(call_t *call, uint8_t cc_isdn_cause, uint16_t cc } if (call->nua_handle) { - PDEBUG(DSIP, DEBUG_DEBUG, "destroying nua_handle %p\n", call->nua_handle); + LOGP(DSIP, LOGL_DEBUG, "destroying nua_handle %p\n", call->nua_handle); nua_handle_destroy(call->nua_handle); call->nua_handle = NULL; } @@ -485,20 +489,20 @@ static void setup_req(call_t *call, osmo_cc_msg_t *msg) int rc; if (!call->sip_ep->remote_peer || !call->sip_ep->remote_peer[0]) { - PDEBUG(DSIP, DEBUG_NOTICE, "No remote peer set or no peer has registered to us.\n"); + LOGP(DSIP, LOGL_NOTICE, "No remote peer set or no peer has registered to us.\n"); release_and_destroy(call, OSMO_CC_ISDN_CAUSE_DEST_OOO, 0, 0, 0, ""); return; } - PDEBUG(DSIP, DEBUG_INFO, "Sending INVITE (callref %d)\n", call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Sending INVITE (callref %d)\n", call->cc_callref); call->nua_handle = nua_handle(call->sip_ep->nua, NULL, TAG_END()); if (!call->nua_handle) { - PDEBUG(DSIP, DEBUG_ERROR, "Failed to create handle\n"); + LOGP(DSIP, LOGL_ERROR, "Failed to create handle\n"); release_and_destroy(call, OSMO_CC_ISDN_CAUSE_TEMP_FAILURE, 0, 0, 0, ""); return; } - PDEBUG(DSIP, DEBUG_DEBUG, " -> new nua_handle %p\n", call->nua_handle); + LOGP(DSIP, LOGL_DEBUG, " -> new nua_handle %p\n", call->nua_handle); /* caller information (also used for contact) */ rc = osmo_cc_get_ie_calling(msg, 0, &type, &plan, &present, &screen, callerid, sizeof(callerid)); @@ -517,7 +521,7 @@ static void setup_req(call_t *call, osmo_cc_msg_t *msg) sprintf(from, "sip:%s@%s", user, peer); else sprintf(from, "sip:%s", peer); - PDEBUG(DSIP, DEBUG_DEBUG, " -> From = %s\n", from); + LOGP(DSIP, LOGL_DEBUG, " -> From = %s\n", from); /* contact information, equal to 'from', but with port number added, if not already exists */ strcpy(contact, from); @@ -530,7 +534,7 @@ static void setup_req(call_t *call, osmo_cc_msg_t *msg) strcat(contact, ":"); strcat(contact, p); } - PDEBUG(DSIP, DEBUG_DEBUG, " -> Contact = %s\n", contact); + LOGP(DSIP, LOGL_DEBUG, " -> Contact = %s\n", contact); /* dialing information */ rc = osmo_cc_get_ie_called(msg, 0, &type, &plan, dialing, sizeof(dialing)); @@ -548,13 +552,13 @@ static void setup_req(call_t *call, osmo_cc_msg_t *msg) sprintf(to, "sip:%s@%s", user, peer); } else sprintf(to, "sip:%s", peer); - PDEBUG(DSIP, DEBUG_DEBUG, " -> To = %s\n", to); + LOGP(DSIP, LOGL_DEBUG, " -> To = %s\n", to); /* asserted id */ if (call->sip_ep->asserted_id) { sprintf(asserted_id, "sip:%s@%s", call->sip_ep->asserted_id, call->sip_ep->local_peer); sprintf(asserted_msg, "P-Asserted-Identity: <%s>", asserted_id); - PDEBUG(DSIP, DEBUG_DEBUG, " -> Asserted ID = %s\n", asserted_id); + LOGP(DSIP, LOGL_DEBUG, " -> Asserted ID = %s\n", asserted_id); } /* SDP */ @@ -564,7 +568,7 @@ static void setup_req(call_t *call, osmo_cc_msg_t *msg) sdp = sdp_buffer; if (call->sip_ep->public_ip[0]) { sdp = sdp_replace_contact(sdp, call->sip_ep->public_ip); - PDEBUG(DSIP, DEBUG_DEBUG, " -> Modify Contact line(s) of SDP:\n"); + LOGP(DSIP, LOGL_DEBUG, " -> Modify Contact line(s) of SDP:\n"); } free(call->sdp_request); call->sdp_request = strdup(sdp); @@ -615,7 +619,7 @@ static const char *response_contact(call_t *call) strcat(contact, ":"); strcat(contact, p); } - PDEBUG(DSIP, DEBUG_DEBUG, " -> Contact = %s\n", contact); + LOGP(DSIP, LOGL_DEBUG, " -> Contact = %s\n", contact); return contact; } @@ -627,17 +631,17 @@ static void send_progress_sdp(call_t *call, const char *sdp) if (call->sdp_sent) return; - PDEBUG(DSIP, DEBUG_DEBUG, " -> Reply with 183 'Session Progress'\n"); + LOGP(DSIP, LOGL_DEBUG, " -> Reply with 183 'Session Progress'\n"); if (call->sip_ep->public_ip[0]) { sdp = sdp_replace_contact(sdp, call->sip_ep->public_ip); - PDEBUG(DSIP, DEBUG_DEBUG, " -> Modify Contact line(s) of SDP:\n"); + LOGP(DSIP, LOGL_DEBUG, " -> Modify Contact line(s) of SDP:\n"); } free(call->sdp_response); call->sdp_response = strdup(sdp); osmo_cc_debug_sdp(sdp); - PDEBUG(DSIP, DEBUG_INFO, "Sending INVITE response: %d %s (callref %d)\n", SIP_183_SESSION_PROGRESS, call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Sending INVITE response: %d %s (callref %d)\n", SIP_183_SESSION_PROGRESS, call->cc_callref); contact = response_contact(call); @@ -681,13 +685,13 @@ static void alert_req(call_t *call, osmo_cc_msg_t *msg) send_progress_sdp(call, sdp); if (call->sdp_sent && call->sip_ep->send_no_ringing_after_progress) { - PDEBUG(DSIP, DEBUG_DEBUG, "Sending no 180 'Ringing' after 183 'Session Progress' with SDP.\n"); + LOGP(DSIP, LOGL_DEBUG, "Sending no 180 'Ringing' after 183 'Session Progress' with SDP.\n"); return; } contact = response_contact(call); - PDEBUG(DSIP, DEBUG_INFO, "Sending INVITE response: %d %s (callref %d)\n", SIP_180_RINGING, call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Sending INVITE response: %d %s (callref %d)\n", SIP_180_RINGING, call->cc_callref); nua_respond(call->nua_handle, SIP_180_RINGING, TAG_IF(contact[0], SIPTAG_CONTACT_STR(contact)), @@ -703,7 +707,7 @@ static void setup_rsp(call_t *call, osmo_cc_msg_t *msg) rc = osmo_cc_get_ie_sdp(msg, 0, sdp_buffer, sizeof(sdp_buffer)); if (rc < 0) { - PDEBUG(DSIP, DEBUG_DEBUG, " -> No SDP, so we re-use the one we received earlier.\n"); + LOGP(DSIP, LOGL_DEBUG, " -> No SDP, so we re-use the one we received earlier.\n"); sdp = call->sdp_response; } else sdp = sdp_buffer; @@ -711,7 +715,7 @@ static void setup_rsp(call_t *call, osmo_cc_msg_t *msg) if (sdp) { if (call->sip_ep->public_ip[0]) { sdp = sdp_replace_contact(sdp, call->sip_ep->public_ip); - PDEBUG(DSIP, DEBUG_DEBUG, " -> Modify Contact line(s) of SDP:\n"); + LOGP(DSIP, LOGL_DEBUG, " -> Modify Contact line(s) of SDP:\n"); } /* Prevent use-after-free bug, by cloning sdp before freeing sdp_response. */ sdp = strdup(sdp); @@ -719,11 +723,11 @@ static void setup_rsp(call_t *call, osmo_cc_msg_t *msg) call->sdp_response = (char*)sdp; osmo_cc_debug_sdp(sdp); } else - PDEBUG(DSIP, DEBUG_INFO, "There was no SDP received during PROC/ALERT/PROGRESS/SETUP-RSP from Osmo-CC. The call will fail due to missing SDP. (callref %d)\n", call->cc_callref); + LOGP(DSIP, LOGL_INFO, "There was no SDP received during PROC/ALERT/PROGRESS/SETUP-RSP from Osmo-CC. The call will fail due to missing SDP. (callref %d)\n", call->cc_callref); contact = response_contact(call); - PDEBUG(DSIP, DEBUG_INFO, "Sending INVITE response: %d %s (callref %d)\n", SIP_200_OK, call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Sending INVITE response: %d %s (callref %d)\n", SIP_200_OK, call->cc_callref); nua_respond(call->nua_handle, SIP_200_OK, NUTAG_MEDIA_ENABLE(0), @@ -763,9 +767,9 @@ static void info_req(call_t *call, osmo_cc_msg_t *msg) /* prepare DTMF info payload */ sprintf(dtmf_str, "Signal=%c\r\nDuration=%d\r\n", digits[0], duration_ms); - PDEBUG(DSIP, DEBUG_INFO, "Sending INFO (callref %d)\n", call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Sending INFO (callref %d)\n", call->cc_callref); - PDEBUG(DSIP, DEBUG_DEBUG, " -> DTMF digit %c\n", digits[0]); + LOGP(DSIP, LOGL_DEBUG, " -> DTMF digit %c\n", digits[0]); /* start invite to handle DTMF */ nua_info(call->nua_handle, @@ -778,7 +782,7 @@ static void info_req(call_t *call, osmo_cc_msg_t *msg) static void notify_req(void) { - PDEBUG(DSIP, DEBUG_NOTICE, "CC-NOTIFY-REQUEST not supported!\n"); + LOGP(DSIP, LOGL_NOTICE, "CC-NOTIFY-REQUEST not supported!\n"); } static void rej_req(call_t *call, osmo_cc_msg_t *msg) @@ -849,13 +853,13 @@ void cc_message(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg) /* process SETUP */ if (!call) { if (msg->type != OSMO_CC_MSG_SETUP_REQ) { - PDEBUG(DSIP, DEBUG_ERROR, "received message without call instance, please fix!\n"); + LOGP(DSIP, LOGL_ERROR, "received message without call instance, please fix!\n"); return; } /* creating call instance, transparent until setup with hdlc */ call = call_create(sip_ep); if (!call) { - PDEBUG(DSIP, DEBUG_ERROR, "Cannot create calll instance.\n"); + LOGP(DSIP, LOGL_ERROR, "Cannot create calll instance.\n"); abort(); } /* link with cc */ @@ -925,7 +929,7 @@ void cc_message(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg) break; default: - PDEBUG(DSIP, DEBUG_ERROR, "received an unsupported CC message: %d\n", msg->type); + LOGP(DSIP, LOGL_ERROR, "received an unsupported CC message: %d\n", msg->type); } osmo_cc_free_msg(msg); @@ -940,7 +944,7 @@ void block_address(const char *block_failure, const char *src_addr, const char * char command[256]; sprintf(command, block_failure, src_addr); - PDEBUG(DSIP, DEBUG_NOTICE, "Blocking due to %s: \"%s\"\n", why, command); + LOGP(DSIP, LOGL_NOTICE, "Blocking due to %s: \"%s\"\n", why, command); system(command); } @@ -958,17 +962,17 @@ static void ep_i_register(sip_endpoint_t *sip_ep, int status, nua_t *nua, nua_ha const char *auth_text = NULL; char auth_str[256] = ""; - PDEBUG(DSIP, DEBUG_INFO, "Received REGISTER (registration)\n"); + LOGP(DSIP, LOGL_INFO, "Received REGISTER (registration)\n"); getnameinfo(addrinfo->ai_addr, (socklen_t)addrinfo->ai_addrlen, src_addr, sizeof(src_addr), NULL, 0, NI_NUMERICHOST); - PDEBUG(DSIP, DEBUG_DEBUG, " -> from source address: %s\n", src_addr); + LOGP(DSIP, LOGL_DEBUG, " -> from source address: %s\n", src_addr); if (!sip->sip_contact || !sip->sip_contact->m_url || !sip->sip_contact->m_url->url_host) { - PDEBUG(DSIP, DEBUG_NOTICE, "Not found, because we don't have a contact line"); - PDEBUG(DSIP, DEBUG_INFO, "Sending REGISTER response: %d %s (registration)\n", SIP_404_NOT_FOUND); + LOGP(DSIP, LOGL_NOTICE, "Not found, because we don't have a contact line"); + LOGP(DSIP, LOGL_INFO, "Sending REGISTER response: %d %s (registration)\n", SIP_404_NOT_FOUND); nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS_MSG(data->e_msg), TAG_END()); nua_destroy_event(saved); - PDEBUG(DSIP, DEBUG_DEBUG, "destroying nua_handle %p (register)\n", nh); + LOGP(DSIP, LOGL_DEBUG, "destroying nua_handle %p (register)\n", nh); nua_handle_destroy(nh); return; } @@ -984,7 +988,7 @@ static void ep_i_register(sip_endpoint_t *sip_ep, int status, nua_t *nua, nua_ha sprintf(contact_peer, "[%s]:%d", src_addr, ntohs(((struct sockaddr_in6 *) addrinfo->ai_addr)->sin6_port)); break; } - PDEBUG(DSIP, DEBUG_DEBUG, " -> contact %s@%s (given by source address)\n", contact_user, contact_peer); + LOGP(DSIP, LOGL_DEBUG, " -> contact %s@%s (given by source address)\n", contact_user, contact_peer); } else { if (sip->sip_contact->m_url->url_host) { // FIXME: unstable/might not work with IPv6 @@ -994,32 +998,32 @@ static void ep_i_register(sip_endpoint_t *sip_ep, int status, nua_t *nua, nua_ha strcat(contact_peer, sip->sip_contact->m_url->url_port); } } - PDEBUG(DSIP, DEBUG_DEBUG, " -> contact %s@%s (given by remote)\n", contact_user, contact_peer); + LOGP(DSIP, LOGL_DEBUG, " -> contact %s@%s (given by remote)\n", contact_user, contact_peer); } if (sip->sip_user_agent && sip->sip_user_agent->g_string) { strncpy(user_agent, sip->sip_user_agent->g_string, sizeof(user_agent)); user_agent[sizeof(user_agent) - 1] = '\0'; - PDEBUG(DSIP, DEBUG_DEBUG, " -> User Agent \"%s\"\n", user_agent); + LOGP(DSIP, LOGL_DEBUG, " -> User Agent \"%s\"\n", user_agent); } if (sip_ep->remote_user_agent && !!strcmp(user_agent, sip_ep->remote_user_agent)) { if (sip_ep->block_failure) block_address(sip_ep->block_failure, src_addr, "invalid remote user agent"); - PDEBUG(DSIP, DEBUG_INFO, "Sending REGISTER response: %d %s (registration) because user agnet does not match\n", SIP_403_FORBIDDEN); + LOGP(DSIP, LOGL_INFO, "Sending REGISTER response: %d %s (registration) because user agnet does not match\n", SIP_403_FORBIDDEN); nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS_MSG(data->e_msg), TAG_END()); nua_destroy_event(saved); - PDEBUG(DSIP, DEBUG_DEBUG, "destroying nua_handle %p (register)\n", nh); + LOGP(DSIP, LOGL_DEBUG, "destroying nua_handle %p (register)\n", nh); nua_handle_destroy(nh); return; } if (!sip_ep->local_register) { - PDEBUG(DSIP, DEBUG_DEBUG, "forbidden, because we don't accept registration"); - PDEBUG(DSIP, DEBUG_INFO, "Sending REGISTER response: %d %s (registration)\n", SIP_403_FORBIDDEN); + LOGP(DSIP, LOGL_DEBUG, "forbidden, because we don't accept registration"); + LOGP(DSIP, LOGL_INFO, "Sending REGISTER response: %d %s (registration)\n", SIP_403_FORBIDDEN); nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS_MSG(data->e_msg), TAG_END()); nua_destroy_event(saved); - PDEBUG(DSIP, DEBUG_DEBUG, "destroying nua_handle %p (register)\n", nh); + LOGP(DSIP, LOGL_DEBUG, "destroying nua_handle %p (register)\n", nh); nua_handle_destroy(nh); return; } @@ -1036,9 +1040,9 @@ static void ep_i_register(sip_endpoint_t *sip_ep, int status, nua_t *nua, nua_ha status = 200; auth_text = "Authentication not required"; } - PDEBUG(DSIP, DEBUG_DEBUG, " -> Authentication: %d %s\n", status, auth_text); + LOGP(DSIP, LOGL_DEBUG, " -> Authentication: %d %s\n", status, auth_text); if (sip->sip_expires) - PDEBUG(DSIP, DEBUG_DEBUG, " -> Expires: %d\n", (int)sip->sip_expires->ex_delta); + LOGP(DSIP, LOGL_DEBUG, " -> Expires: %d\n", (int)sip->sip_expires->ex_delta); if (status == 200) { strcpy(sip_ep->remote_contact_user, contact_user); @@ -1047,22 +1051,22 @@ static void ep_i_register(sip_endpoint_t *sip_ep, int status, nua_t *nua, nua_ha sip_ep->remote_peer = sip_ep->remote_contact_peer; sip_ep->register_nonce[0] = '\0'; if (sip->sip_expires && sip->sip_expires->ex_delta == 0) { - PDEBUG(DSIP, DEBUG_INFO, "This in an unregister session.\n"); - timer_stop(&sip_ep->register_expire_timer); + LOGP(DSIP, LOGL_INFO, "This in an unregister session.\n"); + osmo_timer_del(&sip_ep->register_expire_timer); sip_ep->remote_peer = NULL; } if (sip->sip_expires && sip->sip_expires->ex_delta > 0) { - PDEBUG(DSIP, DEBUG_DEBUG, "Starting expire timer with extra 10 seconds: %d seconds\n", (int)sip->sip_expires->ex_delta + 10); - timer_start(&sip_ep->register_expire_timer, sip->sip_expires->ex_delta + 10); + LOGP(DSIP, LOGL_DEBUG, "Starting expire timer with extra 10 seconds: %d seconds\n", (int)sip->sip_expires->ex_delta + 10); + osmo_timer_schedule(&sip_ep->register_expire_timer, sip->sip_expires->ex_delta + 10,0); } } - PDEBUG(DSIP, DEBUG_INFO, "Sending REGISTER response: %d %s (registration)\n", status, auth_text); + LOGP(DSIP, LOGL_INFO, "Sending REGISTER response: %d %s (registration)\n", status, auth_text); nua_respond(nh, status, auth_text, SIPTAG_CONTACT(sip->sip_contact), NUTAG_WITH_THIS_MSG(data->e_msg), TAG_IF(auth_str[0], SIPTAG_WWW_AUTHENTICATE_STR(auth_str)), TAG_END()); nua_destroy_event(saved); -// PDEBUG(DSIP, DEBUG_DEBUG, "nua_handle %p (register)\n", nh); - PDEBUG(DSIP, DEBUG_DEBUG, "destroying nua_handle %p (register)\n", nh); +// LOGP(DSIP, LOGL_DEBUG, "nua_handle %p (register)\n", nh); + LOGP(DSIP, LOGL_DEBUG, "destroying nua_handle %p (register)\n", nh); nua_handle_destroy(nh); if (sip_ep->block_failure && status == 403) @@ -1073,7 +1077,7 @@ static void ep_r_register(sip_endpoint_t *sip_ep, int status, char const *phrase { int rc; - PDEBUG(DSIP, DEBUG_INFO, "Received REGISTER response: %d %s (registration)\n", status, phrase); + LOGP(DSIP, LOGL_INFO, "Received REGISTER response: %d %s (registration)\n", status, phrase); switch (status) { case 200: @@ -1081,21 +1085,21 @@ static void ep_r_register(sip_endpoint_t *sip_ep, int status, char const *phrase /* if not registered, become registered and start register interval timer */ if (sip_ep->register_state != REGISTER_STATE_REGISTERED) { if (sip_ep->register_interval) - timer_start(&sip_ep->register_retry_timer, sip_ep->register_interval); + osmo_timer_schedule(&sip_ep->register_retry_timer, sip_ep->register_interval,0); sip_ep->register_state = REGISTER_STATE_REGISTERED; } #if 0 //register options does not work /* start option timer */ if (sip_ep->options_interval) { - PDEBUG(DSIP, DEBUG_DEBUG, "Register ok, scheduling option timer with %d seconds\n", sip_ep->options_interval); - timer_start(&sip_ep->register_option_timer, sip_ep->options_interval); + LOGP(DSIP, LOGL_DEBUG, "Register ok, scheduling option timer with %d seconds\n", sip_ep->options_interval); + osmo_timer_schedule(&sip_ep->register_option_timer, sip_ep->options_interval,0); } #endif break; case 401: case 407: - PDEBUG(DSIP, DEBUG_DEBUG, "Register challenge received\n"); + LOGP(DSIP, LOGL_DEBUG, "Register challenge received\n"); rc = authenticate(sip_ep, nh, sip); if (rc < 0) goto status_400; @@ -1106,55 +1110,55 @@ static void ep_r_register(sip_endpoint_t *sip_ep, int status, char const *phrase if (status < 400) break; status_400: - PDEBUG(DSIP, DEBUG_DEBUG, "Register failed, starting register timer\n"); + LOGP(DSIP, LOGL_DEBUG, "Register failed, starting register timer\n"); sip_ep->register_state = REGISTER_STATE_FAILED; - PDEBUG(DSIP, DEBUG_DEBUG, "destroying nua_handle %p (register)\n", nh); + LOGP(DSIP, LOGL_DEBUG, "destroying nua_handle %p (register)\n", nh); nua_handle_destroy(nh); sip_ep->register_handle = NULL; /* stop option timer */ - timer_stop(&sip_ep->register_option_timer); + osmo_timer_del(&sip_ep->register_option_timer); /* if failed, start register interval timer with REGISTER_RETRY_TIMER */ - timer_start(&sip_ep->register_retry_timer, REGISTER_RETRY_TIMER); + osmo_timer_schedule(&sip_ep->register_retry_timer, REGISTER_RETRY_TIMER,0); } } static void ep_i_options(nua_t *nua, nua_handle_t *nh) { - PDEBUG(DSIP, DEBUG_INFO, "Received OPTIONS (registration)\n"); + LOGP(DSIP, LOGL_INFO, "Received OPTIONS (registration)\n"); nua_saved_event_t saved[1]; nua_save_event(nua, saved); nua_event_data_t const *data = nua_event_data(saved); - PDEBUG(DSIP, DEBUG_INFO, "Sending OPTIONS response: %d %s (registration)\n", SIP_200_OK); + LOGP(DSIP, LOGL_INFO, "Sending OPTIONS response: %d %s (registration)\n", SIP_200_OK); nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(data->e_msg), TAG_END()); nua_destroy_event(saved); - PDEBUG(DSIP, DEBUG_DEBUG, "nua_handle %p (register)\n", nh); + LOGP(DSIP, LOGL_DEBUG, "nua_handle %p (register)\n", nh); // NOTE: nh will be destroyed by caller of this function } static void ep_r_options(sip_endpoint_t __attribute__((unused)) *sip_ep, int status, char const *phrase, nua_handle_t __attribute__((unused)) *nh) { - PDEBUG(DSIP, DEBUG_INFO, "Received OPTIONS response: %d %s (registration)\n", status, phrase); + LOGP(DSIP, LOGL_INFO, "Received OPTIONS response: %d %s (registration)\n", status, phrase); #if 0 //register options does not work if (status >= 200 && status <= 299) { - PDEBUG(DSIP, DEBUG_DEBUG, "options ok, scheduling option timer with %d seconds\n", sip_ep->options_interval); + LOGP(DSIP, LOGL_DEBUG, "options ok, scheduling option timer with %d seconds\n", sip_ep->options_interval); /* restart option timer */ - timer_start(&sip_ep->register_option_timer, sip_ep->options_interval); + osmo_timer_schedule(&sip_ep->register_option_timer, sip_ep->options_interval,0); return; } - PDEBUG(DSIP, DEBUG_DEBUG, "Register options failed, starting register timer\n"); + LOGP(DSIP, LOGL_DEBUG, "Register options failed, starting register timer\n"); sip_ep->register_state = REGISTER_STATE_FAILED; - PDEBUG(DSIP, DEBUG_DEBUG, "destroying nua_handle %p (register)\n", nh); + LOGP(DSIP, LOGL_DEBUG, "destroying nua_handle %p (register)\n", nh); nua_handle_destroy(nh); sip_ep->register_handle = NULL; /* if failed, start register interval timer with REGISTER_RETRY_TIMER */ - timer_start(&sip_ep->register_retry_timer, REGISTER_RETRY_TIMER); + osmo_timer_schedule(&sip_ep->register_retry_timer, REGISTER_RETRY_TIMER,0); #endif } @@ -1187,15 +1191,15 @@ static void call_i_invite(call_t *call, nua_t *nua, nua_handle_t *nh, sip_t cons } if (call->state != SIP_STATE_IDLE) - PDEBUG(DSIP, DEBUG_INFO, "Received RE-INVITE (callref %d)\n", call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Received RE-INVITE (callref %d)\n", call->cc_callref); else - PDEBUG(DSIP, DEBUG_INFO, "Received INVITE (callref %d)\n", call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Received INVITE (callref %d)\n", call->cc_callref); getnameinfo(addrinfo->ai_addr, (socklen_t)addrinfo->ai_addrlen, src_addr, sizeof(src_addr), NULL, 0, NI_NUMERICHOST); - PDEBUG(DSIP, DEBUG_DEBUG, " -> from source address: %s\n", src_addr); + LOGP(DSIP, LOGL_DEBUG, " -> from source address: %s\n", src_addr); - PDEBUG(DSIP, DEBUG_DEBUG, " -> From = %s '%s'\n", from, from_name); - PDEBUG(DSIP, DEBUG_DEBUG, " -> To = %s '%s'\n", to, to_name); + LOGP(DSIP, LOGL_DEBUG, " -> From = %s '%s'\n", from, from_name); + LOGP(DSIP, LOGL_DEBUG, " -> To = %s '%s'\n", to, to_name); if (call->sip_ep->authenticate_local && call->sip_ep->auth_realm[0] && call->state == SIP_STATE_IDLE) { /* only authenticate remote, if we don't have a re-invite */ @@ -1214,13 +1218,13 @@ static void call_i_invite(call_t *call, nua_t *nua, nua_handle_t *nh, sip_t cons if (sip->sip_user_agent && sip->sip_user_agent->g_string) { strncpy(user_agent, sip->sip_user_agent->g_string, sizeof(user_agent)); user_agent[sizeof(user_agent) - 1] = '\0'; - PDEBUG(DSIP, DEBUG_DEBUG, " -> User Agent \"%s\"\n", user_agent); + LOGP(DSIP, LOGL_DEBUG, " -> User Agent \"%s\"\n", user_agent); } if (call->sip_ep->remote_user_agent && !!strcmp(user_agent, call->sip_ep->remote_user_agent)) { if (call->sip_ep->block_failure) block_address(call->sip_ep->block_failure, src_addr, "invalid remote user agent"); - PDEBUG(DSIP, DEBUG_INFO, "Sending INVITE response: %d %s (callref %d) because user agent does not match\n", SIP_403_FORBIDDEN, call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Sending INVITE response: %d %s (callref %d) because user agent does not match\n", SIP_403_FORBIDDEN, call->cc_callref); nua_respond(nh, SIP_403_FORBIDDEN, SIPTAG_CONTACT(sip->sip_contact), TAG_END()); nua_handle_destroy(nh); call_destroy(call); @@ -1231,7 +1235,7 @@ static void call_i_invite(call_t *call, nua_t *nua, nua_handle_t *nh, sip_t cons if (call->sip_ep->block_failure && status == 403) block_address(call->sip_ep->block_failure, src_addr, "failed authentication"); - PDEBUG(DSIP, DEBUG_INFO, "Sending INVITE response: %d %s (callref %d)\n", status, auth_text, call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Sending INVITE response: %d %s (callref %d)\n", status, auth_text, call->cc_callref); nua_respond(nh, status, auth_text, SIPTAG_CONTACT(sip->sip_contact), TAG_IF(auth_str[0], SIPTAG_PROXY_AUTHENTICATE_STR(auth_str)), TAG_END()); nua_handle_destroy(nh); call_destroy(call); @@ -1246,7 +1250,7 @@ static void call_i_invite(call_t *call, nua_t *nua, nua_handle_t *nh, sip_t cons call->sdp_request[sip->sip_payload->pl_len] = '\0'; rtp_peer_nat(call->sip_ep, &call->sdp_request); } else { - PDEBUG(DSIP, DEBUG_DEBUG, " -> No SDP in message\n"); + LOGP(DSIP, LOGL_DEBUG, " -> No SDP in message\n"); new_state(call, SIP_STATE_IN_INVITE); release_and_destroy(call, 0, 400, 0, SIP_400_BAD_REQUEST); return; @@ -1255,7 +1259,7 @@ static void call_i_invite(call_t *call, nua_t *nua, nua_handle_t *nh, sip_t cons /* handle re-invite */ if (call->state != SIP_STATE_IDLE) { char *sdp = call->sdp_response; - PDEBUG(DSIP, DEBUG_INFO, "Sending RE-INVITE response: %d %s (callref %d)\n", SIP_200_OK, call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Sending RE-INVITE response: %d %s (callref %d)\n", SIP_200_OK, call->cc_callref); nua_respond(call->nua_handle, SIP_200_OK, NUTAG_MEDIA_ENABLE(0), TAG_IF(sdp, SIPTAG_CONTENT_TYPE_STR("application/sdp")), @@ -1266,7 +1270,7 @@ static void call_i_invite(call_t *call, nua_t *nua, nua_handle_t *nh, sip_t cons /* apply handle */ - PDEBUG(DSIP, DEBUG_DEBUG, "new nua_handle %p\n", nh); + LOGP(DSIP, LOGL_DEBUG, "new nua_handle %p\n", nh); call->nua_handle = nh; /* create osmo-cc message */ @@ -1303,14 +1307,14 @@ static void call_i_invite(call_t *call, nua_t *nua, nua_handle_t *nh, sip_t cons #ifdef NUTAG_AUTO100 /* send trying (proceeding) */ - PDEBUG(DSIP, DEBUG_INFO, "Sending INVITE response: %d %s (callref %d)\n", SIP_100_TRYING, call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Sending INVITE response: %d %s (callref %d)\n", SIP_100_TRYING, call->cc_callref); nua_respond(nh, SIP_100_TRYING, TAG_END()); #endif /* create endpoint */ osmo_cc_call_t *cc_call = osmo_cc_call_new(&call->sip_ep->cc_ep); call->cc_callref = cc_call->callref; - PDEBUG(DSIP, DEBUG_INFO, "New callref created. (callref %d)\n", call->cc_callref); + LOGP(DSIP, LOGL_INFO, "New callref created. (callref %d)\n", call->cc_callref); new_state(call, SIP_STATE_IN_INVITE); @@ -1319,8 +1323,8 @@ static void call_i_invite(call_t *call, nua_t *nua, nua_handle_t *nh, sip_t cons /* start option timer */ if (call->sip_ep->options_interval) { - PDEBUG(DSIP, DEBUG_DEBUG, "Invite received, scheduling option timer with %d seconds\n", call->sip_ep->options_interval); - timer_start(&call->invite_option_timer, call->sip_ep->options_interval); + LOGP(DSIP, LOGL_DEBUG, "Invite received, scheduling option timer with %d seconds\n", call->sip_ep->options_interval); + osmo_timer_schedule(&call->invite_option_timer, call->sip_ep->options_interval,0); } } @@ -1330,12 +1334,12 @@ static void call_r_invite(call_t *call, int status, char const *phrase, nua_hand int rc; if (call->state == SIP_STATE_CONNECT) - PDEBUG(DSIP, DEBUG_INFO, "Received RE-INVITE response: %d %s (callref %d)\n", status, phrase, call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Received RE-INVITE response: %d %s (callref %d)\n", status, phrase, call->cc_callref); else - PDEBUG(DSIP, DEBUG_INFO, "Received INVITE response: %d %s (callref %d)\n", status, phrase, call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Received INVITE response: %d %s (callref %d)\n", status, phrase, call->cc_callref); if (status == 401 || status == 407) { - PDEBUG(DSIP, DEBUG_DEBUG, "Invite challenge received\n"); + LOGP(DSIP, LOGL_DEBUG, "Invite challenge received\n"); rc = authenticate(call->sip_ep, nh, sip); if (rc < 0) { release_and_destroy(call, 0, status, 0, 0, ""); @@ -1353,7 +1357,7 @@ static void call_r_invite(call_t *call, int status, char const *phrase, nua_hand rtp_peer_nat(call->sip_ep, &call->sdp_response); osmo_cc_debug_sdp(call->sdp_response); } else if (!call->sdp_response && status >= 200 && status <= 299) { - PDEBUG(DSIP, DEBUG_DEBUG, " -> No SDP in message\n"); + LOGP(DSIP, LOGL_DEBUG, " -> No SDP in message\n"); release_and_destroy(call, 0, 400, 0, SIP_400_BAD_REQUEST); return; } @@ -1399,8 +1403,8 @@ static void call_r_invite(call_t *call, int status, char const *phrase, nua_hand /* start option timer */ if (call->sip_ep->options_interval) { - PDEBUG(DSIP, DEBUG_DEBUG, "Invite response, scheduling option timer with %d seconds\n", call->sip_ep->options_interval); - timer_start(&call->invite_option_timer, call->sip_ep->options_interval); + LOGP(DSIP, LOGL_DEBUG, "Invite response, scheduling option timer with %d seconds\n", call->sip_ep->options_interval); + osmo_timer_schedule(&call->invite_option_timer, call->sip_ep->options_interval,0); } /* create osmo-cc message */ @@ -1421,7 +1425,7 @@ static void call_r_invite(call_t *call, int status, char const *phrase, nua_hand goto status_200; if (status < 100 || status > 199) break; - PDEBUG(DSIP, DEBUG_DEBUG, "skipping 1xx message\n"); + LOGP(DSIP, LOGL_DEBUG, "skipping 1xx message\n"); return; } @@ -1431,9 +1435,9 @@ static void call_r_invite(call_t *call, int status, char const *phrase, nua_hand static void call_i_options(call_t *call, nua_handle_t *nh) { - PDEBUG(DSIP, DEBUG_INFO, "Received OPTIONS (callref %d)\n", call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Received OPTIONS (callref %d)\n", call->cc_callref); - PDEBUG(DSIP, DEBUG_INFO, "Sending OPTIONS response: %d %s (callref %d)\n", SIP_200_OK, call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Sending OPTIONS response: %d %s (callref %d)\n", SIP_200_OK, call->cc_callref); nua_respond(nh, SIP_200_OK, TAG_END()); } @@ -1442,16 +1446,16 @@ static void call_r_options(call_t *call, int status, char const *phrase) { osmo_cc_msg_t *msg; - PDEBUG(DSIP, DEBUG_INFO, "Received OPTIONS response: %d %s (callref %d)\n", status, phrase, call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Received OPTIONS response: %d %s (callref %d)\n", status, phrase, call->cc_callref); if (status >= 200 && status <= 499) { - PDEBUG(DSIP, DEBUG_DEBUG, "scheduling option timer with %d seconds\n", call->sip_ep->options_interval); + LOGP(DSIP, LOGL_DEBUG, "scheduling option timer with %d seconds\n", call->sip_ep->options_interval); /* restart option timer */ - timer_start(&call->invite_option_timer, call->sip_ep->options_interval); + osmo_timer_schedule(&call->invite_option_timer, call->sip_ep->options_interval,0); return; } - PDEBUG(DSIP, DEBUG_DEBUG, "options failed, release call\n"); + LOGP(DSIP, LOGL_DEBUG, "options failed, release call\n"); /* create osmo-cc message */ msg = osmo_cc_new_msg(OSMO_CC_MSG_REL_IND); @@ -1462,7 +1466,7 @@ static void call_r_options(call_t *call, int status, char const *phrase) /* send message to osmo-cc */ osmo_cc_ll_msg(&call->sip_ep->cc_ep, call->cc_callref, msg); - PDEBUG(DSIP, DEBUG_DEBUG, "destroying nua_handle %p\n", call->nua_handle); + LOGP(DSIP, LOGL_DEBUG, "destroying nua_handle %p\n", call->nua_handle); nua_handle_destroy(call->nua_handle); call->nua_handle = NULL; call_destroy(call); @@ -1488,7 +1492,7 @@ static void call_i_info(call_t *call, nua_t *nua, nua_handle_t *nh, sip_t const nua_save_event(nua, saved); nua_event_data_t const *data = nua_event_data(saved); - PDEBUG(DSIP, DEBUG_INFO, "Received INFO (callref %d)\n", call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Received INFO (callref %d)\n", call->cc_callref); // code stolen from freeswitch.... @@ -1520,7 +1524,7 @@ static void call_i_info(call_t *call, nua_t *nua, nua_handle_t *nh, sip_t const } } - PDEBUG(DSIP, DEBUG_INFO, "Sending INFO response: %d %s (callref %d)\n", SIP_200_OK, call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Sending INFO response: %d %s (callref %d)\n", SIP_200_OK, call->cc_callref); nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(data->e_msg), TAG_END()); nua_destroy_event(saved); @@ -1528,7 +1532,7 @@ static void call_i_info(call_t *call, nua_t *nua, nua_handle_t *nh, sip_t const if (digit) { char digits[2] = { digit, '\0' }; - PDEBUG(DSIP, DEBUG_DEBUG, " -> DTMF digit: %c\n", digit); + LOGP(DSIP, LOGL_DEBUG, " -> DTMF digit: %c\n", digit); /* create osmo-cc message */ msg = osmo_cc_new_msg(OSMO_CC_MSG_INFO_IND); @@ -1548,22 +1552,22 @@ static void call_i_bye(call_t *call, nua_handle_t *nh, sip_t const *sip) uint16_t sip_cause = 0; osmo_cc_msg_t *msg; - PDEBUG(DSIP, DEBUG_INFO, "Received BYE (callref %d)\n", call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Received BYE (callref %d)\n", call->cc_callref); for (reason = sip->sip_reason; reason; reason = reason->re_next) { if (!reason->re_protocol) continue; if (!isdn_cause && !strcasecmp(sip->sip_reason->re_protocol, "Q.850") && sip->sip_reason->re_cause) { isdn_cause = atoi(sip->sip_reason->re_cause); - PDEBUG(DSIP, DEBUG_INFO, " -> ISDN cause: %d\n", isdn_cause); + LOGP(DSIP, LOGL_INFO, " -> ISDN cause: %d\n", isdn_cause); } if (!sip_cause && !strcasecmp(sip->sip_reason->re_protocol, "SIP") && sip->sip_reason->re_cause) { sip_cause = atoi(sip->sip_reason->re_cause); - PDEBUG(DSIP, DEBUG_INFO, " -> SIP cause: %d\n", sip_cause); + LOGP(DSIP, LOGL_INFO, " -> SIP cause: %d\n", sip_cause); } } - PDEBUG(DSIP, DEBUG_INFO, "Sending BYE response: %d %s (callref %d)\n", SIP_200_OK, call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Sending BYE response: %d %s (callref %d)\n", SIP_200_OK, call->cc_callref); nua_respond(nh, SIP_200_OK, TAG_END()); @@ -1576,7 +1580,7 @@ static void call_i_bye(call_t *call, nua_handle_t *nh, sip_t const *sip) /* send message to osmo-cc */ osmo_cc_ll_msg(&call->sip_ep->cc_ep, call->cc_callref, msg); - PDEBUG(DSIP, DEBUG_DEBUG, "destroying nua_handle %p\n", nh); + LOGP(DSIP, LOGL_DEBUG, "destroying nua_handle %p\n", nh); nua_handle_destroy(nh); call->nua_handle = NULL; call_destroy(call); @@ -1584,7 +1588,7 @@ static void call_i_bye(call_t *call, nua_handle_t *nh, sip_t const *sip) static void call_r_bye(call_t *call, int status, char const *phrase) { - PDEBUG(DSIP, DEBUG_INFO, "Received BYE response: %d %s (callref %d)\n", status, phrase, call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Received BYE response: %d %s (callref %d)\n", status, phrase, call->cc_callref); release_and_destroy(call, 0, status, 0, 0, ""); } @@ -1593,9 +1597,9 @@ static void call_i_cancel(call_t *call, nua_handle_t *nh) { osmo_cc_msg_t *msg; - PDEBUG(DSIP, DEBUG_INFO, "Received CANCEL (callref %d)\n", call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Received CANCEL (callref %d)\n", call->cc_callref); - PDEBUG(DSIP, DEBUG_INFO, "Sending CANCEL response: %d %s (callref %d)\n", SIP_200_OK, call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Sending CANCEL response: %d %s (callref %d)\n", SIP_200_OK, call->cc_callref); nua_respond(nh, SIP_200_OK, TAG_END()); @@ -1605,7 +1609,7 @@ static void call_i_cancel(call_t *call, nua_handle_t *nh) /* send message to osmo-cc */ osmo_cc_ll_msg(&call->sip_ep->cc_ep, call->cc_callref, msg); - PDEBUG(DSIP, DEBUG_DEBUG, "destroying nua_handle %p\n", nh); + LOGP(DSIP, LOGL_DEBUG, "destroying nua_handle %p\n", nh); nua_handle_destroy(nh); call->nua_handle = NULL; call_destroy(call); @@ -1613,14 +1617,14 @@ static void call_i_cancel(call_t *call, nua_handle_t *nh) static void call_r_cancel(call_t *call, int status, char const *phrase) { - PDEBUG(DSIP, DEBUG_INFO, "Received CANCEL response: %d %s (callref %d)\n", status, phrase, call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Received CANCEL response: %d %s (callref %d)\n", status, phrase, call->cc_callref); release_and_destroy(call, 0, status, 0, 0, ""); } static void call_i_state(call_t *call, int status, char const *phrase) { - PDEBUG(DSIP, DEBUG_DEBUG, "State change received: %d %s (callref %d)\n", status, phrase, call->cc_callref); + LOGP(DSIP, LOGL_DEBUG, "State change received: %d %s (callref %d)\n", status, phrase, call->cc_callref); } /* messages from SIP stack */ @@ -1629,7 +1633,7 @@ static void sip_message(nua_event_t event, int status, char const *phrase, nua_t sip_endpoint_t *sip_ep = (sip_endpoint_t *)magic; call_t *call; - PDEBUG(DSIP, DEBUG_DEBUG, "Event %d from SIP stack received (handle=%p)\n", event, nh); + LOGP(DSIP, LOGL_DEBUG, "Event %d from SIP stack received (handle=%p)\n", event, nh); switch (event) { case nua_r_shutdown: @@ -1667,7 +1671,7 @@ static void sip_message(nua_event_t event, int status, char const *phrase, nua_t if (!call) { ep_i_options(nua, nh); if (sip_ep->register_handle != nh) { - PDEBUG(DSIP, DEBUG_DEBUG, "destroying nua_handle %p\n", nh); + LOGP(DSIP, LOGL_DEBUG, "destroying nua_handle %p\n", nh); nua_handle_destroy(nh); } return; @@ -1681,21 +1685,21 @@ static void sip_message(nua_event_t event, int status, char const *phrase, nua_t break; case nua_i_invite: if (!call) { - PDEBUG(DSIP, DEBUG_DEBUG, "New call instance\n"); + LOGP(DSIP, LOGL_DEBUG, "New call instance\n"); /* create call instance */ call = call_create(sip_ep); if (!call) { - PDEBUG(DSIP, DEBUG_ERROR, "Cannot create call instance.\n"); + LOGP(DSIP, LOGL_ERROR, "Cannot create call instance.\n"); abort(); } } break; case nua_i_outbound: - PDEBUG(DSIP, DEBUG_DEBUG, "Outbound status\n"); + LOGP(DSIP, LOGL_DEBUG, "Outbound status\n"); break; case nua_i_notify: - PDEBUG(DSIP, DEBUG_NOTICE, "Notify not supported.\n"); + LOGP(DSIP, LOGL_NOTICE, "Notify not supported.\n"); return; default: @@ -1705,10 +1709,10 @@ static void sip_message(nua_event_t event, int status, char const *phrase, nua_t if (!call) { /* terminate call, if it does not exist */ if (nh != sip_ep->register_handle) { - PDEBUG(DSIP, DEBUG_ERROR, "no SIP Port found for handle %p\n", nh); - PDEBUG(DSIP, DEBUG_INFO, "Sending INVITE response: %d %s\n", SIP_500_INTERNAL_SERVER_ERROR); + LOGP(DSIP, LOGL_ERROR, "no SIP Port found for handle %p\n", nh); + LOGP(DSIP, LOGL_INFO, "Sending INVITE response: %d %s\n", SIP_500_INTERNAL_SERVER_ERROR); nua_respond(nh, SIP_500_INTERNAL_SERVER_ERROR, TAG_END()); - PDEBUG(DSIP, DEBUG_DEBUG, "destroying nua_handle %p\n", nh); + LOGP(DSIP, LOGL_DEBUG, "destroying nua_handle %p\n", nh); nua_handle_destroy(nh); } return; @@ -1716,10 +1720,10 @@ static void sip_message(nua_event_t event, int status, char const *phrase, nua_t switch (event) { case nua_r_set_params: - PDEBUG(DSIP, DEBUG_DEBUG, "setparam response\n"); + LOGP(DSIP, LOGL_DEBUG, "setparam response\n"); break; case nua_i_error: - PDEBUG(DSIP, DEBUG_DEBUG, "error received\n"); + LOGP(DSIP, LOGL_DEBUG, "error received\n"); break; case nua_i_invite: call_i_invite(call, nua, nh, sip); @@ -1728,10 +1732,10 @@ static void sip_message(nua_event_t event, int status, char const *phrase, nua_t call_r_invite(call, status, phrase, nh, sip); break; case nua_i_ack: - PDEBUG(DSIP, DEBUG_DEBUG, "ack received\n"); + LOGP(DSIP, LOGL_DEBUG, "ack received\n"); break; case nua_i_active: - PDEBUG(DSIP, DEBUG_DEBUG, "active received\n"); + LOGP(DSIP, LOGL_DEBUG, "active received\n"); break; case nua_i_options: call_i_options(call, nh); @@ -1758,16 +1762,16 @@ static void sip_message(nua_event_t event, int status, char const *phrase, nua_t call_i_state(call, status, phrase); break; case nua_i_terminated: - PDEBUG(DSIP, DEBUG_DEBUG, "terminated received\n"); + LOGP(DSIP, LOGL_DEBUG, "terminated received\n"); break; case nua_i_prack: - PDEBUG(DSIP, DEBUG_DEBUG, "prack indication received\n"); + LOGP(DSIP, LOGL_DEBUG, "prack indication received\n"); break; case nua_r_prack: - PDEBUG(DSIP, DEBUG_DEBUG, "prack response received\n"); + LOGP(DSIP, LOGL_DEBUG, "prack response received\n"); break; default: - PDEBUG(DSIP, DEBUG_DEBUG, "Event %d not handled\n", event); + LOGP(DSIP, LOGL_DEBUG, "Event %d not handled\n", event); } } @@ -1778,7 +1782,7 @@ static void stun_bind_cb(stun_discovery_magic_t *magic, stun_handle_t __attribut socklen_t addrlen; char public_ip[sizeof(sip_ep->public_ip)]; - PDEBUG(DSIP, DEBUG_DEBUG, "Event %d from STUN stack received\n", event); + LOGP(DSIP, LOGL_DEBUG, "Event %d from STUN stack received\n", event); switch (event) { case stun_discovery_done: @@ -1789,9 +1793,9 @@ static void stun_bind_cb(stun_discovery_magic_t *magic, stun_handle_t __attribut su_inet_ntop(sa.su_family, SU_ADDR(&sa), public_ip, sizeof(sip_ep->public_ip)); sip_ep->stun_state = STUN_STATE_RESOLVED; /* start timer for next stun request with sip_ep->stun_interval */ - timer_start(&sip_ep->stun_retry_timer, sip_ep->stun_interval); - PDEBUG(DSIP, DEBUG_INFO, "STUN resolved!\n"); - PDEBUG(DSIP, DEBUG_DEBUG, " -> Public IP = %s\n", public_ip); + osmo_timer_schedule(&sip_ep->stun_retry_timer, sip_ep->stun_interval,0); + LOGP(DSIP, LOGL_INFO, "STUN resolved!\n"); + LOGP(DSIP, LOGL_DEBUG, " -> Public IP = %s\n", public_ip); /* only if IP changed and only if we do register */ if (!!strcmp(sip_ep->public_ip, public_ip)) { strcpy(sip_ep->public_ip, public_ip); @@ -1801,69 +1805,69 @@ static void stun_bind_cb(stun_discovery_magic_t *magic, stun_handle_t __attribut break; default: failed: - PDEBUG(DSIP, DEBUG_INFO, "STUN Resolving failed!\n"); + LOGP(DSIP, LOGL_INFO, "STUN Resolving failed!\n"); sip_ep->stun_state = STUN_STATE_FAILED; /* start timer for next stun request (after failing) with STUN_RETRY_TIMER */ - timer_start(&sip_ep->stun_retry_timer, STUN_RETRY_TIMER); + osmo_timer_schedule(&sip_ep->stun_retry_timer, STUN_RETRY_TIMER,0); } } -static void invite_option_timeout(struct timer *timer) +static void invite_option_timeout(void *data) { - call_t *call = timer->priv; + call_t *call = data; - PDEBUG(DSIP, DEBUG_DEBUG, "invite options timer fired\n"); + LOGP(DSIP, LOGL_DEBUG, "invite options timer fired\n"); - PDEBUG(DSIP, DEBUG_INFO, "Sending OPTIONS (callref %d)\n", call->cc_callref); + LOGP(DSIP, LOGL_INFO, "Sending OPTIONS (callref %d)\n", call->cc_callref); nua_options(call->nua_handle, TAG_END()); } -static void stun_retry_timeout(struct timer *timer) +static void stun_retry_timeout(void *data) { - sip_endpoint_t *sip_ep = timer->priv; + sip_endpoint_t *sip_ep = data; - PDEBUG(DSIP, DEBUG_DEBUG, "timeout, restart stun lookup\n"); + LOGP(DSIP, LOGL_DEBUG, "timeout, restart stun lookup\n"); sip_ep->stun_state = STUN_STATE_UNRESOLVED; } -static void register_retry_timeout(struct timer *timer) +static void register_retry_timeout(void *data) { - sip_endpoint_t *sip_ep = timer->priv; + sip_endpoint_t *sip_ep = data; - PDEBUG(DSIP, DEBUG_DEBUG, "timeout, restart register\n"); + LOGP(DSIP, LOGL_DEBUG, "timeout, restart register\n"); /* if we have a handle, destroy it and becom unregistered, so registration is * triggered next */ if (sip_ep->register_handle) { /* stop option timer */ - timer_stop(&sip_ep->register_option_timer); - PDEBUG(DSIP, DEBUG_DEBUG, "destroying nua_handle %p\n", sip_ep->register_handle); + osmo_timer_del(&sip_ep->register_option_timer); + LOGP(DSIP, LOGL_DEBUG, "destroying nua_handle %p\n", sip_ep->register_handle); nua_handle_destroy(sip_ep->register_handle); sip_ep->register_handle = NULL; } sip_ep->register_state = REGISTER_STATE_UNREGISTERED; } -static void register_expire_timeout(struct timer *timer) +static void register_expire_timeout(void *data) { - sip_endpoint_t *sip_ep = timer->priv; + sip_endpoint_t *sip_ep = data; - PDEBUG(DSIP, DEBUG_DEBUG, "timeout, registration expired\n"); + LOGP(DSIP, LOGL_DEBUG, "timeout, registration expired\n"); - PDEBUG(DSIP, DEBUG_INFO, "Peer is now unregistered, due to registration timeout.\n"); + LOGP(DSIP, LOGL_INFO, "Peer is now unregistered, due to registration timeout.\n"); sip_ep->remote_peer = NULL; } -static void register_option_timeout(struct timer *timer) +static void register_option_timeout(void *data) { - sip_endpoint_t *sip_ep = timer->priv; + sip_endpoint_t *sip_ep = data; - PDEBUG(DSIP, DEBUG_DEBUG, "register options timer fired\n"); + LOGP(DSIP, LOGL_DEBUG, "register options timer fired\n"); - PDEBUG(DSIP, DEBUG_INFO, "Sending OPTIONS (registration)\n"); + LOGP(DSIP, LOGL_INFO, "Sending OPTIONS (registration)\n"); nua_options(sip_ep->register_handle, TAG_END()); @@ -1877,7 +1881,7 @@ sip_endpoint_t *sip_endpoint_create(const char *user_agent, const char *remote_u sip_ep = calloc(1, sizeof(*sip_ep)); if (!sip_ep) { - PDEBUG(DSIP, DEBUG_ERROR, "No mem!\n"); + LOGP(DSIP, LOGL_ERROR, "No mem!\n"); return NULL; } @@ -1917,15 +1921,15 @@ sip_endpoint_t *sip_endpoint_create(const char *user_agent, const char *remote_u sip_ep->stun_interval = stun_interval; /* create timers */ - timer_init(&sip_ep->stun_retry_timer, stun_retry_timeout, sip_ep); - timer_init(&sip_ep->register_retry_timer, register_retry_timeout, sip_ep); - timer_init(&sip_ep->register_expire_timer, register_expire_timeout, sip_ep); - timer_init(&sip_ep->register_option_timer, register_option_timeout, sip_ep); + osmo_timer_setup(&sip_ep->stun_retry_timer, stun_retry_timeout, sip_ep); + osmo_timer_setup(&sip_ep->register_retry_timer, register_retry_timeout, sip_ep); + osmo_timer_setup(&sip_ep->register_expire_timer, register_expire_timeout, sip_ep); + osmo_timer_setup(&sip_ep->register_option_timer, register_option_timeout, sip_ep); /* init root object */ sip_ep->su_root = su_root_create(sip_ep); if (!sip_ep->su_root) { - PDEBUG(DSIP, DEBUG_ERROR, "Failed to create SIP root\n"); + LOGP(DSIP, LOGL_ERROR, "Failed to create SIP root\n"); goto error; } @@ -1935,7 +1939,7 @@ sip_endpoint_t *sip_endpoint_create(const char *user_agent, const char *remote_u strcat(local, ":5060"); sip_ep->nua = nua_create(sip_ep->su_root, sip_message, sip_ep, NUTAG_URL(local), TAG_END()); if (!sip_ep->nua) { - PDEBUG(DSIP, DEBUG_ERROR, "Failed to create SIP stack object\n"); + LOGP(DSIP, LOGL_ERROR, "Failed to create SIP stack object\n"); goto error; } nua_set_params(sip_ep->nua, @@ -1968,18 +1972,18 @@ sip_endpoint_t *sip_endpoint_create(const char *user_agent, const char *remote_u STUNTAG_SERVER(sip_ep->stun_server), TAG_NULL()); if (!sip_ep->stun_handle) { - PDEBUG(DSIP, DEBUG_ERROR, "Failed to create STUN handle\n"); + LOGP(DSIP, LOGL_ERROR, "Failed to create STUN handle\n"); goto error; } sip_ep->stun_socket = su_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sip_ep->stun_socket < 0) { - PDEBUG(DSIP, DEBUG_ERROR, "Failed to create STUN socket\n"); + LOGP(DSIP, LOGL_ERROR, "Failed to create STUN socket\n"); goto error; } sip_ep->stun_state = STUN_STATE_UNRESOLVED; } - PDEBUG(DSIP, DEBUG_DEBUG, "SIP endpoint created\n"); + LOGP(DSIP, LOGL_DEBUG, "SIP endpoint created\n"); return sip_ep; @@ -1993,10 +1997,10 @@ void sip_endpoint_destroy(sip_endpoint_t *sip_ep) { if (!sip_ep) return; - timer_exit(&sip_ep->stun_retry_timer); - timer_exit(&sip_ep->register_retry_timer); - timer_exit(&sip_ep->register_expire_timer); - timer_exit(&sip_ep->register_option_timer); + osmo_timer_del(&sip_ep->stun_retry_timer); + osmo_timer_del(&sip_ep->register_retry_timer); + osmo_timer_del(&sip_ep->register_expire_timer); + osmo_timer_del(&sip_ep->register_option_timer); if (sip_ep->stun_socket) su_close(sip_ep->stun_socket); if (sip_ep->stun_handle) @@ -2015,7 +2019,7 @@ void sip_endpoint_destroy(sip_endpoint_t *sip_ep) nua_destroy(sip_ep->nua); free(sip_ep); - PDEBUG(DSIP, DEBUG_DEBUG, "SIP endpoint destroyed\n"); + LOGP(DSIP, LOGL_DEBUG, "SIP endpoint destroyed\n"); } extern su_log_t su_log_default[]; @@ -2036,7 +2040,7 @@ int sip_init(int debug_level) //su_log_set_level(soa_log, debug_level); } - PDEBUG(DSIP, DEBUG_DEBUG, "SIP globals initialized\n"); + LOGP(DSIP, LOGL_DEBUG, "SIP globals initialized\n"); return 0; } @@ -2047,7 +2051,7 @@ void sip_exit(void) su_home_deinit(sip_home); su_deinit(); - PDEBUG(DSIP, DEBUG_DEBUG, "SIP globals de-initialized\n"); + LOGP(DSIP, LOGL_DEBUG, "SIP globals de-initialized\n"); } /* trigger stun resolver */ @@ -2058,21 +2062,21 @@ static void sip_handle_stun(sip_endpoint_t *sip_ep) switch (sip_ep->stun_state) { case STUN_STATE_UNRESOLVED: - PDEBUG(DSIP, DEBUG_INFO, "STUN resolving for public IP\n"); + LOGP(DSIP, LOGL_INFO, "STUN resolving for public IP\n"); rc = stun_bind(sip_ep->stun_handle, stun_bind_cb, (stun_discovery_magic_t *)sip_ep, STUNTAG_SOCKET(sip_ep->stun_socket), STUNTAG_REGISTER_EVENTS(1), TAG_NULL()); if (rc < 0) { - PDEBUG(DSIP, DEBUG_ERROR, "Failed to call stun_bind()\n"); + LOGP(DSIP, LOGL_ERROR, "Failed to call stun_bind()\n"); sip_ep->stun_state = STUN_STATE_FAILED; /* start timer for next stun request (after failing) with STUN_RETRY_TIMER */ - timer_start(&sip_ep->stun_retry_timer, STUN_RETRY_TIMER); + osmo_timer_schedule(&sip_ep->stun_retry_timer, STUN_RETRY_TIMER,0); break; } - PDEBUG(DSIP, DEBUG_DEBUG, " -> Server = %s\n", sip_ep->stun_server); + LOGP(DSIP, LOGL_DEBUG, " -> Server = %s\n", sip_ep->stun_server); sip_ep->stun_state = STUN_STATE_RESOLVING; break; @@ -2096,20 +2100,20 @@ static void sip_handle_register(sip_endpoint_t *sip_ep) if (sip_ep->stun_handle && sip_ep->stun_state != STUN_STATE_RESOLVED) return; - PDEBUG(DSIP, DEBUG_INFO, "Sending REGISTER\n"); + LOGP(DSIP, LOGL_INFO, "Sending REGISTER\n"); sip_ep->register_handle = nua_handle(sip_ep->nua, NULL, TAG_END()); if (!sip_ep->register_handle) { - PDEBUG(DSIP, DEBUG_ERROR, "Failed to create handle\n"); + LOGP(DSIP, LOGL_ERROR, "Failed to create handle\n"); sip_ep->register_state = REGISTER_STATE_FAILED; break; } - PDEBUG(DSIP, DEBUG_DEBUG, "new nua_handle %p (register)\n", sip_ep->register_handle); + LOGP(DSIP, LOGL_DEBUG, "new nua_handle %p (register)\n", sip_ep->register_handle); sprintf(from, "sip:%s@%s", sip_ep->register_user, sip_ep->register_peer); - PDEBUG(DSIP, DEBUG_DEBUG, " -> From = %s\n", from); + LOGP(DSIP, LOGL_DEBUG, " -> From = %s\n", from); sprintf(to, "sip:%s@%s", sip_ep->register_user, sip_ep->register_peer); - PDEBUG(DSIP, DEBUG_DEBUG, " -> To = %s\n", to); + LOGP(DSIP, LOGL_DEBUG, " -> To = %s\n", to); /* use public_ip if set, otherwise use local_peer */ if (sip_ep->public_ip[0]) @@ -2126,11 +2130,11 @@ static void sip_handle_register(sip_endpoint_t *sip_ep) strcat(contact, ":"); strcat(contact, p); } - PDEBUG(DSIP, DEBUG_DEBUG, " -> Contact = %s\n", contact); + LOGP(DSIP, LOGL_DEBUG, " -> Contact = %s\n", contact); if (sip_ep->register_interval) { sprintf(expires, "%d", sip_ep->register_interval + 60); - PDEBUG(DSIP, DEBUG_DEBUG, " -> Expires = %s\n", expires); + LOGP(DSIP, LOGL_DEBUG, " -> Expires = %s\n", expires); } nua_register(sip_ep->register_handle, diff --git a/src/sip/sip.h b/src/sip/sip.h index d6a128d..e51aa86 100644 --- a/src/sip/sip.h +++ b/src/sip/sip.h @@ -1,6 +1,6 @@ -#include "../libtimer/timer.h" -#include "../libosmocc/endpoint.h" +#include +#include #include #include @@ -74,10 +74,10 @@ typedef struct sip_endpoint { int register_interval; int options_interval; int stun_interval; - struct timer stun_retry_timer; - struct timer register_retry_timer; - struct timer register_expire_timer; - struct timer register_option_timer; + struct osmo_timer_list stun_retry_timer; + struct osmo_timer_list register_retry_timer; + struct osmo_timer_list register_expire_timer; + struct osmo_timer_list register_option_timer; /* SIP stack */ su_root_t *su_root; @@ -108,7 +108,7 @@ typedef struct sip_call { nua_handle_t *nua_handle; - struct timer invite_option_timer; + struct osmo_timer_list invite_option_timer; char *sdp_request, *sdp_response; int sdp_sent;