diff --git a/src/lib/libdebug/Makefile.am b/src/lib/libdebug/Makefile.am deleted file mode 100644 index 210a097..0000000 --- a/src/lib/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/lib/libdebug/debug.c b/src/lib/libdebug/debug.c deleted file mode 100644 index 67ba00c..0000000 --- a/src/lib/libdebug/debug.c +++ /dev/null @@ -1,313 +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" }, - { "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" }, - { NULL, NULL } -}; - -int debuglevel = DEBUG_INFO; -int debug_date = 0; -uint64_t debug_mask = ~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 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; - int rc; - - if (debuglevel > level) - return; - - if (!(debug_mask & ((uint64_t)1 << cat))) - return; - - if (!lock_initialized) { - rc = pthread_mutex_init(&debug_mutex, NULL); - if (rc == 0) - lock_initialized = 1; - } - if (lock_initialized) - pthread_mutex_lock(&debug_mutex); - - 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\033[0;39m", debug_cat[cat].color, file, line, 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); - - if (lock_initialized) - pthread_mutex_unlock(&debug_mutex); -} - -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) - debug_mask = 0; - 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 |= ((uint64_t)1 << i); - } - - 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/lib/libdebug/debug.h b/src/lib/libdebug/debug.h deleted file mode 100644 index ae16857..0000000 --- a/src/lib/libdebug/debug.h +++ /dev/null @@ -1,76 +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 DFRAME 15 -#define DCALL 16 -#define DCC 17 -#define DDB 18 -#define DTRANS 19 -#define DDMS 20 -#define DSMS 21 -#define DSDR 22 -#define DUHD 23 -#define DSOAPY 24 -#define DWAVE 25 -#define DRADIO 26 -#define DAM791X 27 -#define DUART 28 -#define DDEVICE 29 -#define DDATENKLO 30 -#define DZEIT 31 -#define DSIM1 32 -#define DSIM2 33 -#define DSIMI 34 -#define DSIM7 35 -#define DMTP2 36 -#define DMTP3 37 -#define DMUP 38 -#define DROUTER 39 -#define DSTDERR 40 -#define DSS5 41 -#define DISDN 42 -#define DMISDN 43 -#define DDSS1 44 -#define DSIP 45 -#define DTEL 46 - -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/lib/libfilter/Makefile.am b/src/lib/libfilter/Makefile.am deleted file mode 100644 index 45d2ec2..0000000 --- a/src/lib/libfilter/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) - -noinst_LIBRARIES = libfilter.a - -libfilter_a_SOURCES = \ - iir_filter.c \ - fir_filter.c - diff --git a/src/lib/libfilter/fir_filter.c b/src/lib/libfilter/fir_filter.c deleted file mode 100644 index c86ac5b..0000000 --- a/src/lib/libfilter/fir_filter.c +++ /dev/null @@ -1,197 +0,0 @@ -/* FIR filter - * - * (C) 2017 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 "../libsample/sample.h" -#include "fir_filter.h" - -//#define DEBUG_TAPS - -static void kernel(double *taps, int M, double cutoff, int invert) -{ - int i; - double sum; - - for (i = 0; i <= M; i++) { - /* gen sinc */ - if (i == M / 2) - taps[i] = 2.0 * M_PI * cutoff; - else - taps[i] = sin(2.0 * M_PI * cutoff * (double)(i - M / 2)) - / (double)(i - M / 2); - /* blackman window */ - taps[i] *= 0.42 - 0.50 * cos(2 * M_PI * (double)(i / M)) - + 0.08 * cos(4 * M_PI * (double)(i / M)); - } - - /* normalize */ - sum = 0; - for (i = 0; i <= M; i++) - sum += taps[i]; - for (i = 0; i <= M; i++) - taps[i] /= sum; - - /* invert */ - if (invert) { - for (i = 0; i <= M; i++) - taps[i] = -taps[i]; - taps[M / 2] += 1.0; - } - -#ifdef DEBUG_TAPS - puts("start"); - for (i = 0; i <= M; i++) - puts(debug_amplitude(taps[i])); -#endif -} - -static fir_filter_t *fir_init(double samplerate, double transition_bandwidth) -{ - fir_filter_t *fir; - int M; - - /* alloc struct */ - fir = calloc(1, sizeof(*fir)); - if (!fir) { - fprintf(stderr, "No memory creating FIR filter!\n"); - return NULL; - } - - /* transition bandwidth */ - M = ceil(1.0 / (transition_bandwidth / samplerate)); - if ((M & 1)) - M++; - -// printf("cutoff=%.4f\n", cutoff / samplerate); -// printf("tb=%.4f\n", transition_bandwidth / samplerate); - fir->ntaps = M + 1; - fir->delay = M / 2; - - /* alloc taps */ - fir->taps = calloc(fir->ntaps, sizeof(*fir->taps)); - if (!fir->taps) { - fprintf(stderr, "No memory creating FIR filter!\n"); - fir_exit(fir); - return NULL; - } - - /* alloc ring buffer */ - fir->buffer = calloc(fir->ntaps, sizeof(*fir->buffer)); - if (!fir->buffer) { - fprintf(stderr, "No memory creating FIR filter!\n"); - fir_exit(fir); - return NULL; - } - - - return fir; -} - -fir_filter_t *fir_lowpass_init(double samplerate, double cutoff, double transition_bandwidth) -{ - /* calculate kernel */ - fir_filter_t *fir = fir_init(samplerate, transition_bandwidth); - if (!fir) - return NULL; - kernel(fir->taps, fir->ntaps - 1, cutoff / samplerate, 0); - return fir; -} - -fir_filter_t *fir_highpass_init(double samplerate, double cutoff, double transition_bandwidth) -{ - fir_filter_t *fir = fir_init(samplerate, transition_bandwidth); - if (!fir) - return NULL; - kernel(fir->taps, fir->ntaps - 1, cutoff / samplerate, 1); - return fir; -} - -fir_filter_t *fir_allpass_init(double samplerate, double transition_bandwidth) -{ - fir_filter_t *fir = fir_init(samplerate, transition_bandwidth); - if (!fir) - return NULL; - fir->taps[(fir->ntaps - 1) / 2] = 1.0; - return fir; -} - -fir_filter_t *fir_twopass_init(double samplerate, double cutoff_low, double cutoff_high, double transition_bandwidth) -{ - int i; - double sum; - fir_filter_t *fir = fir_init(samplerate, transition_bandwidth); - if (!fir) - return NULL; - double lp_taps[fir->ntaps], hp_taps[fir->ntaps]; - kernel(lp_taps, fir->ntaps - 1, cutoff_low / samplerate, 0); - kernel(hp_taps, fir->ntaps - 1, cutoff_high / samplerate, 1); - sum = 0; - printf("#warning does not work as expected\n"); - abort(); - for (i = 0; i < fir->ntaps; i++) { - fir->taps[i] = lp_taps[i] + hp_taps[i]; - sum += fir->taps[i]; - } - /* hp will die */ -// for (i = 0; i < fir->ntaps; i++) - // fir->taps[i] /= sum; - return fir; -} - -void fir_exit(fir_filter_t *fir) -{ - if (!fir) - return; - free(fir->taps); - free(fir->buffer); - free(fir); -} - -void fir_process(fir_filter_t *fir, sample_t *samples, int num) -{ - int i, j; - double y; - - for (i = 0; i < num; i++) { - /* put sample in ring buffer */ - fir->buffer[fir->buffer_pos] = samples[i]; - if (++fir->buffer_pos == fir->ntaps) - fir->buffer_pos = 0; - - /* convolve samples */ - y = 0; - for (j = 0; j < fir->ntaps; j++) { - /* convolve sample from ring buffer, starting with oldest */ - y += fir->buffer[fir->buffer_pos] * fir->taps[j]; - if (++fir->buffer_pos == fir->ntaps) - fir->buffer_pos = 0; - } - samples[i] = y; - } -} - -int fir_get_delay(fir_filter_t *fir) -{ - return fir->delay; -} - diff --git a/src/lib/libfilter/fir_filter.h b/src/lib/libfilter/fir_filter.h deleted file mode 100644 index 7d94091..0000000 --- a/src/lib/libfilter/fir_filter.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _FIR_FILTER_H -#define _FIR_FILTER_H - -typedef struct fir_filter { - int ntaps; - int delay; - double *taps; - double *buffer; - int buffer_pos; -} fir_filter_t; - -fir_filter_t *fir_lowpass_init(double samplerate, double cutoff, double transition_bandwidth); -fir_filter_t *fir_highpass_init(double samplerate, double cutoff, double transition_bandwidth); -fir_filter_t *fir_allpass_init(double samplerate, double transition_bandwidth); -fir_filter_t *fir_twopass_init(double samplerate, double cutoff_low, double cutoff_high, double transition_bandwidth); -void fir_exit(fir_filter_t *fir); -void fir_process(fir_filter_t *fir, sample_t *samples, int num); -int fir_get_delay(fir_filter_t *fir); - -#endif /* _FIR_FILTER_H */ - diff --git a/src/lib/libfilter/iir_filter.c b/src/lib/libfilter/iir_filter.c deleted file mode 100644 index 5872d61..0000000 --- a/src/lib/libfilter/iir_filter.c +++ /dev/null @@ -1,204 +0,0 @@ -/* cut-off filter (biquad) based on Nigel Redmon (www.earlevel.com) - * - * (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 "../libsample/sample.h" -#include "iir_filter.h" - -//#define DEBUG_NAN - -#define PI M_PI - -void iir_lowpass_init(iir_filter_t *filter, double frequency, int samplerate, int iterations) -{ - double Fc, Q, K, norm; - - if (iterations > 64) { - fprintf(stderr, "%s failed: too many iterations, please fix!\n", __func__); - abort(); - } - - memset(filter, 0, sizeof(*filter)); - filter->iter = iterations; - Q = pow(sqrt(0.5), 1.0 / (double)iterations); /* 0.7071 @ 1 iteration */ - Fc = frequency / (double)samplerate; - K = tan(PI * Fc); - norm = 1 / (1 + K / Q + K * K); - filter->a0 = K * K * norm; - filter->a1 = 2 * filter->a0; - filter->a2 = filter->a0; - filter->b1 = 2 * (K * K - 1) * norm; - filter->b2 = (1 - K / Q + K * K) * norm; -#ifdef DEBUG_NAN - printf("%p\n", filter); -#endif -} - -void iir_highpass_init(iir_filter_t *filter, double frequency, int samplerate, int iterations) -{ - double Fc, Q, K, norm; - - memset(filter, 0, sizeof(*filter)); - filter->iter = iterations; - Q = pow(sqrt(0.5), 1.0 / (double)iterations); /* 0.7071 @ 1 iteration */ - Fc = frequency / (double)samplerate; - K = tan(PI * Fc); - norm = 1 / (1 + K / Q + K * K); - filter->a0 = 1 * norm; - filter->a1 = -2 * filter->a0; - filter->a2 = filter->a0; - filter->b1 = 2 * (K * K - 1) * norm; - filter->b2 = (1 - K / Q + K * K) * norm; -} - -void iir_bandpass_init(iir_filter_t *filter, double frequency, int samplerate, int iterations) -{ - double Fc, Q, K, norm; - - memset(filter, 0, sizeof(*filter)); - filter->iter = iterations; - Q = pow(sqrt(0.5), 1.0 / (double)iterations); /* 0.7071 @ 1 iteration */ - Fc = frequency / (double)samplerate; - K = tan(PI * Fc); - norm = 1 / (1 + K / Q + K * K); - filter->a0 = K / Q * norm; - filter->a1 = 0; - filter->a2 = -filter->a0; - filter->b1 = 2 * (K * K - 1) * norm; - filter->b2 = (1 - K / Q + K * K) * norm; -} - -void iir_notch_init(iir_filter_t *filter, double frequency, int samplerate, int iterations) -{ - double Fc, Q, K, norm; - - memset(filter, 0, sizeof(*filter)); - filter->iter = iterations; - Q = pow(sqrt(0.5), 1.0 / (double)iterations); /* 0.7071 @ 1 iteration */ - Fc = frequency / (double)samplerate; - K = tan(PI * Fc); - norm = 1 / (1 + K / Q + K * K); - filter->a0 = (1 + K * K) * norm; - filter->a1 = 2 * (K * K - 1) * norm; - filter->a2 = filter->a0; - filter->b1 = filter->a1; - filter->b2 = (1 - K / Q + K * K) * norm; -} - -void iir_process(iir_filter_t *filter, sample_t *samples, int length) -{ - double a0, a1, a2, b1, b2; - double *z1, *z2; - double in, out; - int iterations = filter->iter; - int i, j; - - /* get states */ - a0 = filter->a0; - a1 = filter->a1; - a2 = filter->a2; - b1 = filter->b1; - b2 = filter->b2; - - /* these are state pointers, so no need to write back */ - z1 = filter->z1; - z2 = filter->z2; - - /* process filter */ - for (i = 0; i < length; i++) { - /* add a small value, otherwise this loop will perform really bad on my 'nuedel' machine!!! */ - in = *samples + 0.000000001; - for (j = 0; j < iterations; j++) { - out = in * a0 + z1[j]; - z1[j] = in * a1 + z2[j] - b1 * out; - z2[j] = in * a2 - b2 * out; - in = out; - } - *samples++ = in; - } -} - -#ifdef DEBUG_NAN -#pragma GCC push_options -//#pragma GCC optimize ("O0") -#endif - -void iir_process_baseband(iir_filter_t *filter, float *baseband, int length) -{ - double a0, a1, a2, b1, b2; - double *z1, *z2; - double in, out; - int iterations = filter->iter; - int i, j; - - /* get states */ - a0 = filter->a0; - a1 = filter->a1; - a2 = filter->a2; - b1 = filter->b1; - b2 = filter->b2; - - /* these are state pointers, so no need to write back */ - z1 = filter->z1; - z2 = filter->z2; - - /* process filter */ - for (i = 0; i < length; i++) { - /* add a small value, otherwise this loop will perform really bad on my 'nuedel' machine!!! */ - in = *baseband + 0.000000001; - for (j = 0; j < iterations; j++) { - out = in * a0 + z1[j]; -#ifdef DEBUG_NAN - if (!(out > -100 && out < 100)) { - printf("%p\n", filter); - printf("1. i=%d j=%d z=%.5f in=%.5f a0=%.5f out=%.5f\n", i, j, z1[j], in, a0, out); - abort(); - } -#endif - z1[j] = in * a1 + z2[j] - b1 * out; -#ifdef DEBUG_NAN - if (!(z1[j] > -100 && z1[j] < 100)) { - printf("%p\n", filter); - printf("2. i=%d j=%d z1=%.5f z2=%.5f in=%.5f a1=%.5f out=%.5f b1=%.5f\n", i, j, z1[j], z2[j], in, a1, out, b1); - abort(); - } -#endif - z2[j] = in * a2 - b2 * out; -#ifdef DEBUG_NAN - if (!(z2[j] > -100 && z2[j] < 100)) { - printf("%p\n", filter); - printf("%.5f\n", (in * a2) - (b2 * out)); - printf("3. i=%d j=%d z2=%.5f in=%.5f a2=%.5f b2=%.5f out=%.5f\n", i, j, z2[j], in, a2, b2, out); - abort(); - } -#endif - in = out; - } - *baseband = in; - baseband += 2; - } -} - -#ifdef DEBUG_NAN -#pragma GCC pop_options -#endif diff --git a/src/lib/libfilter/iir_filter.h b/src/lib/libfilter/iir_filter.h deleted file mode 100644 index a5956c8..0000000 --- a/src/lib/libfilter/iir_filter.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _FILTER_H -#define _FILTER_H - -typedef struct iir_filter { - int iter; - double a0, a1, a2, b1, b2; - double z1[64], z2[64]; -} iir_filter_t; - -void iir_lowpass_init(iir_filter_t *filter, double frequency, int samplerate, int iterations); -void iir_highpass_init(iir_filter_t *filter, double frequency, int samplerate, int iterations); -void iir_bandpass_init(iir_filter_t *filter, double frequency, int samplerate, int iterations); -void iir_notch_init(iir_filter_t *filter, double frequency, int samplerate, int iterations); -void iir_process(iir_filter_t *filter, sample_t *samples, int length); -void iir_process_baseband(iir_filter_t *filter, float *baseband, int length); - -#endif /* _FILTER_H */ diff --git a/src/lib/libg711/Makefile.am b/src/lib/libg711/Makefile.am deleted file mode 100644 index 15223bf..0000000 --- a/src/lib/libg711/Makefile.am +++ /dev/null @@ -1,7 +0,0 @@ -AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) - -noinst_LIBRARIES = libg711.a - -libg711_a_SOURCES = \ - g711.c - diff --git a/src/lib/libg711/g711.c b/src/lib/libg711/g711.c deleted file mode 100644 index cd195f9..0000000 --- a/src/lib/libg711/g711.c +++ /dev/null @@ -1,537 +0,0 @@ -/*****************************************************************************\ -** ** -** PBX4Linux ** -** ** -**---------------------------------------------------------------------------** -** Copyright: Andreas Eversberg (GPL) ** -** ** -** audio conversions for alaw and ulaw ** -** ** -\*****************************************************************************/ - -#include -#include -#include - -/* ulaw -> signed 16-bit */ -static int16_t g711_ulaw_flipped_to_linear[256] = -{ - 0x8284, 0x8684, 0x8a84, 0x8e84, 0x9284, 0x9684, 0x9a84, 0x9e84, - 0xa284, 0xa684, 0xaa84, 0xae84, 0xb284, 0xb684, 0xba84, 0xbe84, - 0xc184, 0xc384, 0xc584, 0xc784, 0xc984, 0xcb84, 0xcd84, 0xcf84, - 0xd184, 0xd384, 0xd584, 0xd784, 0xd984, 0xdb84, 0xdd84, 0xdf84, - 0xe104, 0xe204, 0xe304, 0xe404, 0xe504, 0xe604, 0xe704, 0xe804, - 0xe904, 0xea04, 0xeb04, 0xec04, 0xed04, 0xee04, 0xef04, 0xf004, - 0xf0c4, 0xf144, 0xf1c4, 0xf244, 0xf2c4, 0xf344, 0xf3c4, 0xf444, - 0xf4c4, 0xf544, 0xf5c4, 0xf644, 0xf6c4, 0xf744, 0xf7c4, 0xf844, - 0xf8a4, 0xf8e4, 0xf924, 0xf964, 0xf9a4, 0xf9e4, 0xfa24, 0xfa64, - 0xfaa4, 0xfae4, 0xfb24, 0xfb64, 0xfba4, 0xfbe4, 0xfc24, 0xfc64, - 0xfc94, 0xfcb4, 0xfcd4, 0xfcf4, 0xfd14, 0xfd34, 0xfd54, 0xfd74, - 0xfd94, 0xfdb4, 0xfdd4, 0xfdf4, 0xfe14, 0xfe34, 0xfe54, 0xfe74, - 0xfe8c, 0xfe9c, 0xfeac, 0xfebc, 0xfecc, 0xfedc, 0xfeec, 0xfefc, - 0xff0c, 0xff1c, 0xff2c, 0xff3c, 0xff4c, 0xff5c, 0xff6c, 0xff7c, - 0xff88, 0xff90, 0xff98, 0xffa0, 0xffa8, 0xffb0, 0xffb8, 0xffc0, - 0xffc8, 0xffd0, 0xffd8, 0xffe0, 0xffe8, 0xfff0, 0xfff8, 0xffff, - 0x7d7c, 0x797c, 0x757c, 0x717c, 0x6d7c, 0x697c, 0x657c, 0x617c, - 0x5d7c, 0x597c, 0x557c, 0x517c, 0x4d7c, 0x497c, 0x457c, 0x417c, - 0x3e7c, 0x3c7c, 0x3a7c, 0x387c, 0x367c, 0x347c, 0x327c, 0x307c, - 0x2e7c, 0x2c7c, 0x2a7c, 0x287c, 0x267c, 0x247c, 0x227c, 0x207c, - 0x1efc, 0x1dfc, 0x1cfc, 0x1bfc, 0x1afc, 0x19fc, 0x18fc, 0x17fc, - 0x16fc, 0x15fc, 0x14fc, 0x13fc, 0x12fc, 0x11fc, 0x10fc, 0x0ffc, - 0x0f3c, 0x0ebc, 0x0e3c, 0x0dbc, 0x0d3c, 0x0cbc, 0x0c3c, 0x0bbc, - 0x0b3c, 0x0abc, 0x0a3c, 0x09bc, 0x093c, 0x08bc, 0x083c, 0x07bc, - 0x075c, 0x071c, 0x06dc, 0x069c, 0x065c, 0x061c, 0x05dc, 0x059c, - 0x055c, 0x051c, 0x04dc, 0x049c, 0x045c, 0x041c, 0x03dc, 0x039c, - 0x036c, 0x034c, 0x032c, 0x030c, 0x02ec, 0x02cc, 0x02ac, 0x028c, - 0x026c, 0x024c, 0x022c, 0x020c, 0x01ec, 0x01cc, 0x01ac, 0x018c, - 0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104, - 0x00f4, 0x00e4, 0x00d4, 0x00c4, 0x00b4, 0x00a4, 0x0094, 0x0084, - 0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040, - 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000 -}; - -/* alaw -> signed 16-bit */ -static int16_t g711_alaw_flipped_to_linear[256] = -{ - 0x13fc, 0xec04, 0x0144, 0xfebc, 0x517c, 0xae84, 0x051c, 0xfae4, - 0x0a3c, 0xf5c4, 0x0048, 0xffb8, 0x287c, 0xd784, 0x028c, 0xfd74, - 0x1bfc, 0xe404, 0x01cc, 0xfe34, 0x717c, 0x8e84, 0x071c, 0xf8e4, - 0x0e3c, 0xf1c4, 0x00c4, 0xff3c, 0x387c, 0xc784, 0x039c, 0xfc64, - 0x0ffc, 0xf004, 0x0104, 0xfefc, 0x417c, 0xbe84, 0x041c, 0xfbe4, - 0x083c, 0xf7c4, 0x0008, 0xfff8, 0x207c, 0xdf84, 0x020c, 0xfdf4, - 0x17fc, 0xe804, 0x018c, 0xfe74, 0x617c, 0x9e84, 0x061c, 0xf9e4, - 0x0c3c, 0xf3c4, 0x0084, 0xff7c, 0x307c, 0xcf84, 0x030c, 0xfcf4, - 0x15fc, 0xea04, 0x0164, 0xfe9c, 0x597c, 0xa684, 0x059c, 0xfa64, - 0x0b3c, 0xf4c4, 0x0068, 0xff98, 0x2c7c, 0xd384, 0x02cc, 0xfd34, - 0x1dfc, 0xe204, 0x01ec, 0xfe14, 0x797c, 0x8684, 0x07bc, 0xf844, - 0x0f3c, 0xf0c4, 0x00e4, 0xff1c, 0x3c7c, 0xc384, 0x03dc, 0xfc24, - 0x11fc, 0xee04, 0x0124, 0xfedc, 0x497c, 0xb684, 0x049c, 0xfb64, - 0x093c, 0xf6c4, 0x0028, 0xffd8, 0x247c, 0xdb84, 0x024c, 0xfdb4, - 0x19fc, 0xe604, 0x01ac, 0xfe54, 0x697c, 0x9684, 0x069c, 0xf964, - 0x0d3c, 0xf2c4, 0x00a4, 0xff5c, 0x347c, 0xcb84, 0x034c, 0xfcb4, - 0x12fc, 0xed04, 0x0134, 0xfecc, 0x4d7c, 0xb284, 0x04dc, 0xfb24, - 0x09bc, 0xf644, 0x0038, 0xffc8, 0x267c, 0xd984, 0x026c, 0xfd94, - 0x1afc, 0xe504, 0x01ac, 0xfe54, 0x6d7c, 0x9284, 0x06dc, 0xf924, - 0x0dbc, 0xf244, 0x00b4, 0xff4c, 0x367c, 0xc984, 0x036c, 0xfc94, - 0x0f3c, 0xf0c4, 0x00f4, 0xff0c, 0x3e7c, 0xc184, 0x03dc, 0xfc24, - 0x07bc, 0xf844, 0x0008, 0xfff8, 0x1efc, 0xe104, 0x01ec, 0xfe14, - 0x16fc, 0xe904, 0x0174, 0xfe8c, 0x5d7c, 0xa284, 0x05dc, 0xfa24, - 0x0bbc, 0xf444, 0x0078, 0xff88, 0x2e7c, 0xd184, 0x02ec, 0xfd14, - 0x14fc, 0xeb04, 0x0154, 0xfeac, 0x557c, 0xaa84, 0x055c, 0xfaa4, - 0x0abc, 0xf544, 0x0058, 0xffa8, 0x2a7c, 0xd584, 0x02ac, 0xfd54, - 0x1cfc, 0xe304, 0x01cc, 0xfe34, 0x757c, 0x8a84, 0x075c, 0xf8a4, - 0x0ebc, 0xf144, 0x00d4, 0xff2c, 0x3a7c, 0xc584, 0x039c, 0xfc64, - 0x10fc, 0xef04, 0x0114, 0xfeec, 0x457c, 0xba84, 0x045c, 0xfba4, - 0x08bc, 0xf744, 0x0018, 0xffe8, 0x227c, 0xdd84, 0x022c, 0xfdd4, - 0x18fc, 0xe704, 0x018c, 0xfe74, 0x657c, 0x9a84, 0x065c, 0xf9a4, - 0x0cbc, 0xf344, 0x0094, 0xff6c, 0x327c, 0xcd84, 0x032c, 0xfcd4 -}; - -/* Xlaw -> signed 16-bit */ -static int16_t g711_alaw_to_linear[256]; -static int16_t g711_ulaw_to_linear[256]; - -/* signed 16-bit -> Xlaw */ -static uint8_t g711_linear_to_alaw_flipped[65536]; -static uint8_t g711_linear_to_ulaw_flipped[65536]; -static uint8_t g711_linear_to_alaw[65536]; -static uint8_t g711_linear_to_ulaw[65536]; - -/* transcode */ -static uint8_t g711_alaw_to_ulaw[256]; -static uint8_t g711_ulaw_to_alaw[256]; -static uint8_t g711_alaw_flipped_to_ulaw[256]; -static uint8_t g711_ulaw_flipped_to_alaw[256]; -static uint8_t g711_alaw_to_ulaw_flipped[256]; -static uint8_t g711_ulaw_to_alaw_flipped[256]; - -/* table is used to generate linear_to_alaw */ -static int16_t g711_alaw_relations[] = -{ - 0x8684, 0x55, 0x8a84, 0xd5, 0x8e84, 0x15, 0x9284, 0x95, - 0x9684, 0x75, 0x9a84, 0xf5, 0x9e84, 0x35, 0xa284, 0xb5, - 0xa684, 0x45, 0xaa84, 0xc5, 0xae84, 0x05, 0xb284, 0x85, - 0xb684, 0x65, 0xba84, 0xe5, 0xbe84, 0x25, 0xc184, 0xa5, - 0xc384, 0x5d, 0xc584, 0xdd, 0xc784, 0x1d, 0xc984, 0x9d, - 0xcb84, 0x7d, 0xcd84, 0xfd, 0xcf84, 0x3d, 0xd184, 0xbd, - 0xd384, 0x4d, 0xd584, 0xcd, 0xd784, 0x0d, 0xd984, 0x8d, - 0xdb84, 0x6d, 0xdd84, 0xed, 0xdf84, 0x2d, 0xe104, 0xad, - 0xe204, 0x51, 0xe304, 0xd1, 0xe404, 0x11, 0xe504, 0x91, - 0xe604, 0x71, 0xe704, 0xf1, 0xe804, 0x31, 0xe904, 0xb1, - 0xea04, 0x41, 0xeb04, 0xc1, 0xec04, 0x01, 0xed04, 0x81, - 0xee04, 0x61, 0xef04, 0xe1, 0xf004, 0x21, 0xf0c4, 0x59, - 0xf0c4, 0xa1, 0xf144, 0xd9, 0xf1c4, 0x19, 0xf244, 0x99, - 0xf2c4, 0x79, 0xf344, 0xf9, 0xf3c4, 0x39, 0xf444, 0xb9, - 0xf4c4, 0x49, 0xf544, 0xc9, 0xf5c4, 0x09, 0xf644, 0x89, - 0xf6c4, 0x69, 0xf744, 0xe9, 0xf7c4, 0x29, 0xf844, 0x57, - 0xf844, 0xa9, 0xf8a4, 0xd7, 0xf8e4, 0x17, 0xf924, 0x97, - 0xf964, 0x77, 0xf9a4, 0xf7, 0xf9e4, 0x37, 0xfa24, 0xb7, - 0xfa64, 0x47, 0xfaa4, 0xc7, 0xfae4, 0x07, 0xfb24, 0x87, - 0xfb64, 0x67, 0xfba4, 0xe7, 0xfbe4, 0x27, 0xfc24, 0x5f, - 0xfc24, 0xa7, 0xfc64, 0x1f, 0xfc64, 0xdf, 0xfc94, 0x9f, - 0xfcb4, 0x7f, 0xfcd4, 0xff, 0xfcf4, 0x3f, 0xfd14, 0xbf, - 0xfd34, 0x4f, 0xfd54, 0xcf, 0xfd74, 0x0f, 0xfd94, 0x8f, - 0xfdb4, 0x6f, 0xfdd4, 0xef, 0xfdf4, 0x2f, 0xfe14, 0x53, - 0xfe14, 0xaf, 0xfe34, 0x13, 0xfe34, 0xd3, 0xfe54, 0x73, - 0xfe54, 0x93, 0xfe74, 0x33, 0xfe74, 0xf3, 0xfe8c, 0xb3, - 0xfe9c, 0x43, 0xfeac, 0xc3, 0xfebc, 0x03, 0xfecc, 0x83, - 0xfedc, 0x63, 0xfeec, 0xe3, 0xfefc, 0x23, 0xff0c, 0xa3, - 0xff1c, 0x5b, 0xff2c, 0xdb, 0xff3c, 0x1b, 0xff4c, 0x9b, - 0xff5c, 0x7b, 0xff6c, 0xfb, 0xff7c, 0x3b, 0xff88, 0xbb, - 0xff98, 0x4b, 0xffa8, 0xcb, 0xffb8, 0x0b, 0xffc8, 0x8b, - 0xffd8, 0x6b, 0xffe8, 0xeb, 0xfff8, 0x2b, 0xfff8, 0xab, - 0x0008, 0x2a, 0x0008, 0xaa, 0x0018, 0xea, 0x0028, 0x6a, - 0x0038, 0x8a, 0x0048, 0x0a, 0x0058, 0xca, 0x0068, 0x4a, - 0x0078, 0xba, 0x0084, 0x3a, 0x0094, 0xfa, 0x00a4, 0x7a, - 0x00b4, 0x9a, 0x00c4, 0x1a, 0x00d4, 0xda, 0x00e4, 0x5a, - 0x00f4, 0xa2, 0x0104, 0x22, 0x0114, 0xe2, 0x0124, 0x62, - 0x0134, 0x82, 0x0144, 0x02, 0x0154, 0xc2, 0x0164, 0x42, - 0x0174, 0xb2, 0x018c, 0x32, 0x018c, 0xf2, 0x01ac, 0x72, - 0x01ac, 0x92, 0x01cc, 0x12, 0x01cc, 0xd2, 0x01ec, 0x52, - 0x01ec, 0xae, 0x020c, 0x2e, 0x022c, 0xee, 0x024c, 0x6e, - 0x026c, 0x8e, 0x028c, 0x0e, 0x02ac, 0xce, 0x02cc, 0x4e, - 0x02ec, 0xbe, 0x030c, 0x3e, 0x032c, 0xfe, 0x034c, 0x7e, - 0x036c, 0x9e, 0x039c, 0x1e, 0x039c, 0xde, 0x03dc, 0x5e, - 0x03dc, 0xa6, 0x041c, 0x26, 0x045c, 0xe6, 0x049c, 0x66, - 0x04dc, 0x86, 0x051c, 0x06, 0x055c, 0xc6, 0x059c, 0x46, - 0x05dc, 0xb6, 0x061c, 0x36, 0x065c, 0xf6, 0x069c, 0x76, - 0x06dc, 0x96, 0x071c, 0x16, 0x075c, 0xd6, 0x07bc, 0x56, - 0x07bc, 0xa8, 0x083c, 0x28, 0x08bc, 0xe8, 0x093c, 0x68, - 0x09bc, 0x88, 0x0a3c, 0x08, 0x0abc, 0xc8, 0x0b3c, 0x48, - 0x0bbc, 0xb8, 0x0c3c, 0x38, 0x0cbc, 0xf8, 0x0d3c, 0x78, - 0x0dbc, 0x98, 0x0e3c, 0x18, 0x0ebc, 0xd8, 0x0f3c, 0x58, - 0x0f3c, 0xa0, 0x0ffc, 0x20, 0x10fc, 0xe0, 0x11fc, 0x60, - 0x12fc, 0x80, 0x13fc, 0x00, 0x14fc, 0xc0, 0x15fc, 0x40, - 0x16fc, 0xb0, 0x17fc, 0x30, 0x18fc, 0xf0, 0x19fc, 0x70, - 0x1afc, 0x90, 0x1bfc, 0x10, 0x1cfc, 0xd0, 0x1dfc, 0x50, - 0x1efc, 0xac, 0x207c, 0x2c, 0x227c, 0xec, 0x247c, 0x6c, - 0x267c, 0x8c, 0x287c, 0x0c, 0x2a7c, 0xcc, 0x2c7c, 0x4c, - 0x2e7c, 0xbc, 0x307c, 0x3c, 0x327c, 0xfc, 0x347c, 0x7c, - 0x367c, 0x9c, 0x387c, 0x1c, 0x3a7c, 0xdc, 0x3c7c, 0x5c, - 0x3e7c, 0xa4, 0x417c, 0x24, 0x457c, 0xe4, 0x497c, 0x64, - 0x4d7c, 0x84, 0x517c, 0x04, 0x557c, 0xc4, 0x597c, 0x44, - 0x5d7c, 0xb4, 0x617c, 0x34, 0x657c, 0xf4, 0x697c, 0x74, - 0x6d7c, 0x94, 0x717c, 0x14, 0x757c, 0xd4, 0x797c, 0x54 -}; - -uint8_t g711_flip[256]; - -static int g711_initialized = 0; - -/* generate tables - */ -void g711_init(void) -{ - int i, j; - - /* flip tables */ - for (i = 0; i < 256; i++) { - g711_flip[i] - = ((i & 1) << 7) - + ((i & 2) << 5) - + ((i & 4) << 3) - + ((i & 8) << 1) - + ((i & 16) >> 1) - + ((i & 32) >> 3) - + ((i & 64) >> 5) - + ((i & 128) >> 7); - g711_alaw_to_linear[i] = g711_alaw_flipped_to_linear[g711_flip[i]]; - g711_ulaw_to_linear[i] = g711_ulaw_flipped_to_linear[g711_flip[i]]; - } - - /* linear to alaw tables */ - i = j = 0; - while(i < 65536) { - if (i - 32768 > g711_alaw_relations[j << 1]) - j++; - if (j > 255) - j = 255; - g711_linear_to_alaw_flipped[(i - 32768) & 0xffff] = g711_alaw_relations[(j << 1) | 1]; - g711_linear_to_alaw[(i - 32768) & 0xffff] = g711_flip[g711_alaw_relations[(j << 1) | 1]]; - i++; - } - - /* linear to ulaw tables */ - i = j = 0; - while(i < 32768) { - if (i - 32768 > g711_ulaw_flipped_to_linear[j]) - j++; - g711_linear_to_ulaw_flipped[(i - 32768) & 0xffff] = j; - g711_linear_to_ulaw[(i - 32768) & 0xffff] = g711_flip[j]; - i++; - } - j = 255; - while(i < 65536) { - if (i - 32768 > g711_alaw_flipped_to_linear[j]) - j--; - g711_linear_to_ulaw_flipped[(i - 32768) & 0xffff] = j; - g711_linear_to_ulaw[(i - 32768) & 0xffff] = g711_flip[j]; - i++; - } - - /* transcode */ - for (i = 0; i < 256; i++) { - g711_alaw_to_ulaw[i] = g711_linear_to_ulaw[(uint16_t)g711_alaw_to_linear[i]]; - g711_ulaw_to_alaw[i] = g711_linear_to_alaw[(uint16_t)g711_ulaw_to_linear[i]]; - g711_alaw_flipped_to_ulaw[i] = g711_linear_to_ulaw[(uint16_t)g711_alaw_to_linear[g711_flip[i]]]; - g711_ulaw_flipped_to_alaw[i] = g711_linear_to_alaw[(uint16_t)g711_ulaw_to_linear[g711_flip[i]]]; - g711_alaw_to_ulaw_flipped[i] = g711_flip[g711_linear_to_ulaw[(uint16_t)g711_alaw_to_linear[i]]]; - g711_ulaw_to_alaw_flipped[i] = g711_flip[g711_linear_to_alaw[(uint16_t)g711_ulaw_to_linear[i]]]; - } - - g711_initialized = 1; -} - -void g711_encode_alaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) -{ - int16_t *src = (int16_t *)src_data; - uint8_t *dst; - int len = src_len / 2, i; - - if (!g711_initialized) { - fprintf(stderr, "G711 codec not initialized! Please fix!\n"); - abort(); - } - - dst = malloc(len); - if (!dst) - return; - for (i = 0; i < len; i++) - dst[i] = g711_linear_to_alaw_flipped[(uint16_t)src[i]]; - *dst_data = dst; - *dst_len = len; -} - -void g711_encode_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) -{ - int16_t *src = (int16_t *)src_data; - uint8_t *dst; - int len = src_len / 2, i; - - if (!g711_initialized) { - fprintf(stderr, "G711 codec not initialized! Please fix!\n"); - abort(); - } - - dst = malloc(len); - if (!dst) - return; - for (i = 0; i < len; i++) - dst[i] = g711_linear_to_ulaw_flipped[(uint16_t)src[i]]; - *dst_data = dst; - *dst_len = len; -} - -void g711_decode_alaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) -{ - uint8_t *src = src_data; - int16_t *dst; - int len = src_len, i; - - if (!g711_initialized) { - fprintf(stderr, "G711 codec not initialized! Please fix!\n"); - abort(); - } - - dst = malloc(len * 2); - if (!dst) - return; - for (i = 0; i < len; i++) - dst[i] = g711_alaw_flipped_to_linear[src[i]]; - *dst_data = (uint8_t *)dst; - *dst_len = len * 2; -} - -void g711_decode_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) -{ - uint8_t *src = src_data; - int16_t *dst; - int len = src_len, i; - - if (!g711_initialized) { - fprintf(stderr, "G711 codec not initialized! Please fix!\n"); - abort(); - } - - dst = malloc(len * 2); - if (!dst) - return; - for (i = 0; i < len; i++) - dst[i] = g711_ulaw_flipped_to_linear[src[i]]; - *dst_data = (uint8_t *)dst; - *dst_len = len * 2; -} - -void g711_encode_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) -{ - int16_t *src = (int16_t *)src_data; - uint8_t *dst; - int len = src_len / 2, i; - - if (!g711_initialized) { - fprintf(stderr, "G711 codec not initialized! Please fix!\n"); - abort(); - } - - dst = malloc(len); - if (!dst) - return; - for (i = 0; i < len; i++) - dst[i] = g711_linear_to_alaw[(uint16_t)src[i]]; - *dst_data = dst; - *dst_len = len; -} - -void g711_encode_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) -{ - int16_t *src = (int16_t *)src_data; - uint8_t *dst; - int len = src_len / 2, i; - - if (!g711_initialized) { - fprintf(stderr, "G711 codec not initialized! Please fix!\n"); - abort(); - } - - dst = malloc(len); - if (!dst) - return; - for (i = 0; i < len; i++) - dst[i] = g711_linear_to_ulaw[(uint16_t)src[i]]; - *dst_data = dst; - *dst_len = len; -} - -void g711_decode_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) -{ - uint8_t *src = src_data; - int16_t *dst; - int len = src_len, i; - - if (!g711_initialized) { - fprintf(stderr, "G711 codec not initialized! Please fix!\n"); - abort(); - } - - dst = malloc(len * 2); - if (!dst) - return; - for (i = 0; i < len; i++) - dst[i] = g711_alaw_to_linear[src[i]]; - *dst_data = (uint8_t *)dst; - *dst_len = len * 2; -} - -void g711_decode_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) -{ - uint8_t *src = src_data; - int16_t *dst; - int len = src_len, i; - - if (!g711_initialized) { - fprintf(stderr, "G711 codec not initialized! Please fix!\n"); - abort(); - } - - dst = malloc(len * 2); - if (!dst) - return; - for (i = 0; i < len; i++) - dst[i] = g711_ulaw_to_linear[src[i]]; - *dst_data = (uint8_t *)dst; - *dst_len = len * 2; -} - -void g711_transcode_alaw_to_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) -{ - uint8_t *src = src_data, *dst; - int len = src_len, i; - - if (!g711_initialized) { - fprintf(stderr, "G711 codec not initialized! Please fix!\n"); - abort(); - } - - dst = malloc(len); - if (!dst) - return; - for (i = 0; i < len; i++) - dst[i] = g711_alaw_to_ulaw[src[i]]; - *dst_data = dst; - *dst_len = len; -} - -void g711_transcode_alaw_flipped_to_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) -{ - uint8_t *src = src_data, *dst; - int len = src_len, i; - - if (!g711_initialized) { - fprintf(stderr, "G711 codec not initialized! Please fix!\n"); - abort(); - } - - dst = malloc(len); - if (!dst) - return; - for (i = 0; i < len; i++) - dst[i] = g711_alaw_flipped_to_ulaw[src[i]]; - *dst_data = dst; - *dst_len = len; -} - -void g711_transcode_alaw_to_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) -{ - uint8_t *src = src_data, *dst; - int len = src_len, i; - - if (!g711_initialized) { - fprintf(stderr, "G711 codec not initialized! Please fix!\n"); - abort(); - } - - dst = malloc(len); - if (!dst) - return; - for (i = 0; i < len; i++) - dst[i] = g711_alaw_to_ulaw_flipped[src[i]]; - *dst_data = dst; - *dst_len = len; -} - -void g711_transcode_ulaw_to_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) -{ - uint8_t *src = src_data, *dst; - int len = src_len, i; - - if (!g711_initialized) { - fprintf(stderr, "G711 codec not initialized! Please fix!\n"); - abort(); - } - - dst = malloc(len); - if (!dst) - return; - for (i = 0; i < len; i++) - dst[i] = g711_ulaw_to_alaw[src[i]]; - *dst_data = dst; - *dst_len = len; -} - -void g711_transcode_ulaw_flipped_to_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) -{ - uint8_t *src = src_data, *dst; - int len = src_len, i; - - if (!g711_initialized) { - fprintf(stderr, "G711 codec not initialized! Please fix!\n"); - abort(); - } - - dst = malloc(len); - if (!dst) - return; - for (i = 0; i < len; i++) - dst[i] = g711_ulaw_flipped_to_alaw[src[i]]; - *dst_data = dst; - *dst_len = len; -} - -void g711_transcode_ulaw_to_alaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) -{ - uint8_t *src = src_data, *dst; - int len = src_len, i; - - if (!g711_initialized) { - fprintf(stderr, "G711 codec not initialized! Please fix!\n"); - abort(); - } - - dst = malloc(len); - if (!dst) - return; - for (i = 0; i < len; i++) - dst[i] = g711_ulaw_to_alaw_flipped[src[i]]; - *dst_data = dst; - *dst_len = len; -} - -void g711_transcode_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) -{ - uint8_t *src = src_data, *dst; - int len = src_len, i; - - if (!g711_initialized) { - fprintf(stderr, "G711 codec not initialized! Please fix!\n"); - abort(); - } - - dst = malloc(len); - if (!dst) - return; - for (i = 0; i < len; i++) - dst[i] = g711_flip[src[i]]; - *dst_data = dst; - *dst_len = len; -} - diff --git a/src/lib/libg711/g711.h b/src/lib/libg711/g711.h deleted file mode 100644 index 795f60b..0000000 --- a/src/lib/libg711/g711.h +++ /dev/null @@ -1,17 +0,0 @@ -void g711_init(void); -void g711_encode_alaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); -void g711_encode_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); -void g711_decode_alaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); -void g711_decode_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); -void g711_encode_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); -void g711_encode_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); -void g711_decode_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); -void g711_decode_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); -void g711_transcode_alaw_to_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); -void g711_transcode_alaw_flipped_to_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); -void g711_transcode_alaw_to_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); -void g711_transcode_ulaw_to_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); -void g711_transcode_ulaw_flipped_to_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); -void g711_transcode_ulaw_to_alaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); -void g711_transcode_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); - diff --git a/src/lib/libjitter/Makefile.am b/src/lib/libjitter/Makefile.am deleted file mode 100644 index 506ef87..0000000 --- a/src/lib/libjitter/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) - -noinst_LIBRARIES = libjitter.a - -libjitter_a_SOURCES = \ - jitter.c diff --git a/src/lib/libjitter/jitter.c b/src/lib/libjitter/jitter.c deleted file mode 100644 index c3af715..0000000 --- a/src/lib/libjitter/jitter.c +++ /dev/null @@ -1,125 +0,0 @@ -/* Jitter buffering functions - * - * (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 "../libsample/sample.h" -#include "../libdebug/debug.h" -#include "jitter.h" - -/* create jitter buffer */ -int jitter_create(jitter_t *jitter, int length) -{ - memset(jitter, 0, sizeof(*jitter)); - jitter->spl = malloc(length * sizeof(sample_t)); - if (!jitter->spl) { - PDEBUG(DDSP, DEBUG_ERROR, "No memory for jitter buffer.\n"); - return -ENOMEM; - } - jitter->len = length; - - jitter_reset(jitter); - - return 0; -} - -void jitter_reset(jitter_t *jitter) -{ - memset(jitter->spl, 0, jitter->len * sizeof(sample_t)); - - /* put write pointer ahead by half of the buffer length */ - jitter->inptr = jitter->len / 2; -} - -void jitter_destroy(jitter_t *jitter) -{ - if (jitter->spl) { - free(jitter->spl); - jitter->spl = NULL; - } -} - -/* store audio in jitterbuffer - * - * stop if buffer is completely filled - */ -void jitter_save(jitter_t *jb, sample_t *samples, int length) -{ - sample_t *spl; - int inptr, outptr, len, space; - int i; - - spl = jb->spl; - inptr = jb->inptr; - outptr = jb->outptr; - len = jb->len; - space = (outptr - inptr + len - 1) % len; - - if (space < length) - length = space; - for (i = 0; i < length; i++) { - spl[inptr++] = *samples++; - if (inptr == len) - inptr = 0; - } - - jb->inptr = inptr; -} - -/* get audio from jitterbuffer - */ -void jitter_load(jitter_t *jb, sample_t *samples, int length) -{ - sample_t *spl; - int inptr, outptr, len, fill; - int i, ii; - - spl = jb->spl; - inptr = jb->inptr; - outptr = jb->outptr; - len = jb->len; - fill = (inptr - outptr + len) % len; - - if (fill < length) - ii = fill; - else - ii = length; - - /* fill what we got */ - for (i = 0; i < ii; i++) { - *samples++ = spl[outptr++]; - if (outptr == len) - outptr = 0; - } - /* on underrun, fill with silence */ - for (; i < length; i++) { - *samples++ = 0; - } - - jb->outptr = outptr; -} - -void jitter_clear(jitter_t *jb) -{ - jb->inptr = jb->outptr = 0; -} - diff --git a/src/lib/libjitter/jitter.h b/src/lib/libjitter/jitter.h deleted file mode 100644 index e344d8a..0000000 --- a/src/lib/libjitter/jitter.h +++ /dev/null @@ -1,14 +0,0 @@ - -typedef struct jitter { - sample_t *spl; /* pointer to sample buffer */ - int len; /* buffer size: number of samples */ - int inptr, outptr; /* write pointer and read pointer */ -} jitter_t; - -int jitter_create(jitter_t *jitter, int length); -void jitter_reset(jitter_t *jitter); -void jitter_destroy(jitter_t *jitter); -void jitter_save(jitter_t *jb, sample_t *samples, int length); -void jitter_load(jitter_t *jb, sample_t *samples, int length); -void jitter_clear(jitter_t *jb); - diff --git a/src/lib/liboptions/Makefile.am b/src/lib/liboptions/Makefile.am deleted file mode 100644 index 0d10fa7..0000000 --- a/src/lib/liboptions/Makefile.am +++ /dev/null @@ -1,7 +0,0 @@ -AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) - -noinst_LIBRARIES = liboptions.a - -liboptions_a_SOURCES = \ - options.c - diff --git a/src/lib/liboptions/options.c b/src/lib/liboptions/options.c deleted file mode 100644 index d49e698..0000000 --- a/src/lib/liboptions/options.c +++ /dev/null @@ -1,339 +0,0 @@ -/* command line options and config file parsing - * - * (C) 2018 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 "options.h" -#include "../libdebug/debug.h" - -typedef struct option { - struct option *next; - int short_option; - const char *long_option; - int parameter_count; -} option_t; - -static option_t *option_head = NULL; -static option_t **option_tailp = &option_head; -static int first_option = 1; - -static struct options_strdup_entry { - struct options_strdup_entry *next; - char s[1]; -} *options_strdup_list = NULL; - -char *options_strdup(const char *s) -{ - struct options_strdup_entry *o; - - o = malloc(sizeof(struct options_strdup_entry) + strlen(s)); - if (!o) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "No mem!\n"); - abort(); - } - o->next = options_strdup_list; - options_strdup_list = o; - strcpy(o->s, s); - - return o->s; -} - -void option_add(int short_option, const char *long_option, int parameter_count) -{ - option_t *option; - - /* 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); - 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); - abort(); - } - } - - option = calloc(1, sizeof(*option)); - if (!option) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "No mem!\n"); - abort(); - } - - option->short_option = short_option; - option->long_option = long_option; - option->parameter_count = parameter_count; - *option_tailp = option; - option_tailp = &(option->next); -} - -int options_config_file(int argc, char *argv[], const char *config_file, int (*handle_options)(int short_option, int argi, char *argv[])) -{ - static const char *home; - char config[256]; - FILE *fp; - char buffer[256], opt[256], param[256], *p, *args[16]; - char params[1024]; - int line; - int rc = 1; - int i, j, quote; - option_t *option; - - /* select for alternative config file */ - if (argc > 2 && !strcmp(argv[1], "--config")) - config_file = argv[2]; - - /* add home directory */ - if (config_file[0] == '~' && config_file[1] == '/') { - home = getenv("HOME"); - if (home == NULL) - return 1; - sprintf(config, "%s/%s", home, config_file + 2); - } else - strcpy(config, config_file); - - /* 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); - return 1; - } - - /* parse config file */ - line = 0; - while((fgets(buffer, sizeof(buffer), fp))) { - line++; - /* prevent buffer overflow */ - buffer[sizeof(buffer) - 1] = '\0'; - /* cut away new-line and white spaces */ - while (buffer[0] && buffer[strlen(buffer) - 1] <= ' ') - buffer[strlen(buffer) - 1] = '\0'; - p = buffer; - /* remove white spaces in front of first keyword */ - while (*p > '\0' && *p <= ' ') - p++; - /* ignore '#' lines */ - if (*p == '#') - continue; - /* get option form line */ - i = 0; - while (*p > ' ') - opt[i++] = *p++; - opt[i] = '\0'; - if (opt[0] == '\0') - continue; - /* skip white spaces behind option */ - while (*p > '\0' && *p <= ' ') - p++; - /* get param from line */ - params[0] = '\0'; - i = 0; - while (*p) { - /* copy parameter */ - j = 0; - quote = 0; - while (*p) { - /* escape allows all following characters */ - if (*p == '\\') { - p++; - if (*p) - param[j++] = *p++; - continue; - } - /* no quote, check for them or break on white space */ - if (quote == 0) { - if (*p == '\'') { - quote = 1; - p++; - continue; - } - if (*p == '\"') { - quote = 2; - p++; - continue; - } - if (*p <= ' ') - break; - } - /* single quote, check for unquote */ - if (quote == 1 && *p == '\'') { - quote = 0; - p++; - continue; - } - /* double quote, check for unquote */ - if (quote == 2 && *p == '\"') { - quote = 0; - p++; - continue; - } - /* copy character */ - param[j++] = *p++; - } - param[j] = '\0'; - args[i] = options_strdup(param); - sprintf(strchr(params, '\0'), " '%s'", param); - /* skip white spaces behind option */ - while (*p > '\0' && *p <= ' ') - p++; - i++; - } - /* 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); - break; - } - if (!strcmp(opt, option->long_option)) { - PDEBUG(DOPTIONS, DEBUG_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); - 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); - return -EINVAL; - } - rc = handle_options(option->short_option, 0, args); - if (rc <= 0) - goto done; - first_option = 0; - } - -done: - /* close config file */ - fclose(fp); - - return rc; -} - -int options_command_line(int argc, char *argv[], int (*handle_options)(int short_option, int argi, char *argv[])) -{ - option_t *option; - char params[1024]; - int argi, i; - int rc; - - for (argi = 1; argi < argc; argi++) { - /* --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]); - return -EINVAL; - } - if (argc <= 2) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given command line option '%s' requires 1 parameter, use '-h' for help!\n", argv[argi]); - return -EINVAL; - } - argi += 1; - continue; - } - 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]); - return -EINVAL; - } - /* -x */ - for (option = option_head; option; option = option->next) { - if (argv[argi][1] == option->short_option) { - if (option->parameter_count && argi + option->parameter_count < argc) { - 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); - } else - PDEBUG(DOPTIONS, DEBUG_INFO, "Command line option '%s' ('--%s')\n", argv[argi], option->long_option); - break; - } - } - } else { - /* --xxxxxx */ - for (option = option_head; option; option = option->next) { - if (!strcmp(argv[argi] + 2, option->long_option)) { - if (option->parameter_count && argi + option->parameter_count < argc) { - 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); - } else - PDEBUG(DOPTIONS, DEBUG_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]); - 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); - return -EINVAL; - } - rc = handle_options(option->short_option, argi + 1, argv); - if (rc <= 0) - return rc; - first_option = 0; - argi += option->parameter_count; - } else - break; - } - - /* 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]); - return -EINVAL; - } - } - - return argi; -} - -int option_is_first(void) -{ - return first_option; -} - -void options_free(void) -{ - while (options_strdup_list) { - struct options_strdup_entry *o; - o = options_strdup_list; - options_strdup_list = o->next; - free(o); - } - - while (option_head) { - option_t *o; - o = option_head; - option_head = o->next; - free(o); - } - option_tailp = &option_head; -} - diff --git a/src/lib/liboptions/options.h b/src/lib/liboptions/options.h deleted file mode 100644 index 5f494e0..0000000 --- a/src/lib/liboptions/options.h +++ /dev/null @@ -1,8 +0,0 @@ - -char *options_strdup(const char *s); -void option_add(int short_option, const char *long_option, int parameter_count); -int options_config_file(int argc, char *argv[], const char *config_file, int (*handle_options)(int short_option, int argi, char *argv[])); -int options_command_line(int argc, char *argv[], int (*handle_options)(int short_option, int argi, char *argv[])); -int option_is_first(void); -void options_free(void); - diff --git a/src/lib/libosmocc/Makefile.am b/src/lib/libosmocc/Makefile.am deleted file mode 100644 index 27c0f6c..0000000 --- a/src/lib/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/lib/libosmocc/cause.c b/src/lib/libosmocc/cause.c deleted file mode 100644 index 4a3a41e..0000000 --- a/src/lib/libosmocc/cause.c +++ /dev/null @@ -1,252 +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 */ -/* 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: - return 1; //SWITCH_CAUSE_UNALLOCATED_NUMBER; - case 485: - case 604: - return 3; //SWITCH_CAUSE_NO_ROUTE_DESTINATION; - 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 180; //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 88; //SWITCH_CAUSE_INCOMPATIBLE_DESTINATION; - 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; - 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/lib/libosmocc/cause.h b/src/lib/libosmocc/cause.h deleted file mode 100644 index 22319f4..0000000 --- a/src/lib/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/lib/libosmocc/endpoint.c b/src/lib/libosmocc/endpoint.c deleted file mode 100644 index 120b53c..0000000 --- a/src/lib/libosmocc/endpoint.c +++ /dev/null @@ -1,1503 +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 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}, - - /* 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_address(void) -{ - printf("Address options:\n\n"); - - printf("local :\n"); - printf("local []:\n"); - printf("remote :\n"); - printf("remote []:\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"); -} - -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; - } - 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'; - } - - /* 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; - } - from = from * 10 + *text - '0'; - } - - osmo_cc_set_rtp_ports(&ep->session_config, from, to); - return 0; - } - - return -EINVAL; -} - -void osmo_cc_help(void) -{ - osmo_cc_help_screen(); - osmo_cc_help_address(); - osmo_cc_help_rtp(); -} - -/* 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], "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/lib/libosmocc/endpoint.h b/src/lib/libosmocc/endpoint.h deleted file mode 100644 index 4425532..0000000 --- a/src/lib/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/lib/libosmocc/helper.c b/src/lib/libosmocc/helper.c deleted file mode 100644 index 807542e..0000000 --- a/src/lib/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, uint16_t sequence_number, uint32_t timestamp, 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, uint16_t sequence_number, uint32_t timestamp, 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/lib/libosmocc/helper.h b/src/lib/libosmocc/helper.h deleted file mode 100644 index c12a50a..0000000 --- a/src/lib/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, uint16_t sequence_number, uint32_t timestamp, 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, uint16_t sequence_number, uint32_t timestamp, 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/lib/libosmocc/message.c b/src/lib/libosmocc/message.c deleted file mode 100644 index 5b069dd..0000000 --- a/src/lib/libosmocc/message.c +++ /dev/null @@ -1,1290 +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) { \ - for (int 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/lib/libosmocc/message.h b/src/lib/libosmocc/message.h deleted file mode 100644 index 2bb299a..0000000 --- a/src/lib/libosmocc/message.h +++ /dev/null @@ -1,508 +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_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/lib/libosmocc/rtp.c b/src/lib/libosmocc/rtp.c deleted file mode 100644 index afaf22d..0000000 --- a/src/lib/libosmocc/rtp.c +++ /dev/null @@ -1,396 +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) -{ - 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); - - 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 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; - 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->rtp_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; - sa4->sin_addr.s_addr = INADDR_ANY; - 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; - sa6->sin6_addr = in6addr_any; - 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, 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, codec->payload_type_remote, codec->media->tx_sequence, codec->media->tx_timestamp, codec->media->rtp_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); - 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, media->rx_sequence, media->rx_timestamp, 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/lib/libosmocc/rtp.h b/src/lib/libosmocc/rtp.h deleted file mode 100644 index e309f56..0000000 --- a/src/lib/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, 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/lib/libosmocc/screen.c b/src/lib/libosmocc/screen.c deleted file mode 100644 index 5040ce6..0000000 --- a/src/lib/libosmocc/screen.c +++ /dev/null @@ -1,684 +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"); -} - -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; - } 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 { - 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'; - } - - star_used = 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 { - 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) { - *routing_p = &list->to[i]; - 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; - } - - 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, NULL); - 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), "", NULL); - 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/lib/libosmocc/screen.h b/src/lib/libosmocc/screen.h deleted file mode 100644 index 29f4515..0000000 --- a/src/lib/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/lib/libosmocc/sdp.c b/src/lib/libosmocc/sdp.c deleted file mode 100644 index 8e44117..0000000 --- a/src/lib/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, osmo_cc_session_nettype_inet, osmo_cc_session_addrtype_ipv4, "127.0.0.1", NULL, 0); // values will be replaced by local definitions during negotiation - - /* 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/lib/libosmocc/sdp.h b/src/lib/libosmocc/sdp.h deleted file mode 100644 index c9bc721..0000000 --- a/src/lib/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/lib/libosmocc/session.c b/src/lib/libosmocc/session.c deleted file mode 100644 index 50a4a92..0000000 --- a/src/lib/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 2208988800 - -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, uint16_t sequence_number, uint32_t timestamp, 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, uint16_t sequence_number, uint32_t timestamp, 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/lib/libosmocc/session.h b/src/lib/libosmocc/session.h deleted file mode 100644 index c0717c0..0000000 --- a/src/lib/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, uint16_t sequence_number, uint32_t timestamp, uint8_t *data, int len); - int rtp_socket; - int rtcp_socket; - uint32_t rtp_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, uint16_t sequence_number, uint32_t timestamp, 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, uint16_t sequence_number, uint32_t timestamp, 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/lib/libosmocc/socket.c b/src/lib/libosmocc/socket.c deleted file mode 100644 index d25e1f1..0000000 --- a/src/lib/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/lib/libosmocc/socket.h b/src/lib/libosmocc/socket.h deleted file mode 100644 index bcd8b7c..0000000 --- a/src/lib/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/lib/libsample/Makefile.am b/src/lib/libsample/Makefile.am deleted file mode 100644 index 5ae865c..0000000 --- a/src/lib/libsample/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) - -noinst_LIBRARIES = libsample.a - -libsample_a_SOURCES = \ - sample.c diff --git a/src/lib/libsample/sample.c b/src/lib/libsample/sample.c deleted file mode 100644 index a084b66..0000000 --- a/src/lib/libsample/sample.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Sample definition - * - * (C) 2017 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 "sample.h" - -/* - * A regular voice conversation takes place at this factor below the full range - * of 16 bits signed value: - */ -static double int_16_speech_level = SPEECH_LEVEL * 0.7079; /* 16 dBm below dBm0, which is about 3dBm below full 16 bit range */ - -/* A sample_t is a value that has virtually infinite precision but will also - * support high numbers. 'double' or 'float' types are sufficient. - * - * When using sample_t inside signal processing of each base station, the - * level of +- 1 is relative to the normal speech evenlope. - * - * When converting sample_t to int16_t, the level of +- 1 is reduced by factor. - * This way the speech may be louder before clipping happens. - * - * When using sample_t to modulate (SDR or sound card), the level is changed, - * so it represents the frequency deviation in Hz. The deviation of speech - * envelope is network dependent. - */ - -void samples_to_int16(int16_t *spl, sample_t *samples, int length) -{ - int32_t value; - - while (length--) { - value = *samples++ * int_16_speech_level * 32768.0; - if (value > 32767.0) - *spl++ = 32767; - else if (value < -32767.0) - *spl++ = -32767; - else - *spl++ = (uint16_t)value; - } -} - -void int16_to_samples(sample_t *samples, int16_t *spl, int length) -{ - while (length--) { - *samples++ = (double)(*spl++) / 32767.0 / int_16_speech_level; - } -} - diff --git a/src/lib/libsample/sample.h b/src/lib/libsample/sample.h deleted file mode 100644 index 01a17df..0000000 --- a/src/lib/libsample/sample.h +++ /dev/null @@ -1,8 +0,0 @@ - -typedef double sample_t; - -#define SPEECH_LEVEL 0.1585 - -void samples_to_int16(int16_t *spl, sample_t *samples, int length); -void int16_to_samples(sample_t *samples, int16_t *spl, int length); - diff --git a/src/lib/libsamplerate/Makefile.am b/src/lib/libsamplerate/Makefile.am deleted file mode 100644 index bd2319f..0000000 --- a/src/lib/libsamplerate/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) - -noinst_LIBRARIES = libsamplerate.a - -libsamplerate_a_SOURCES = \ - samplerate.c diff --git a/src/lib/libsamplerate/samplerate.c b/src/lib/libsamplerate/samplerate.c deleted file mode 100644 index 7076366..0000000 --- a/src/lib/libsamplerate/samplerate.c +++ /dev/null @@ -1,157 +0,0 @@ -/* Sample rate conversion - * - * (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 "../libsample/sample.h" -#include "samplerate.h" - -int init_samplerate(samplerate_t *state, double low_samplerate, double high_samplerate, double filter_cutoff) -{ - memset(state, 0, sizeof(*state)); - state->factor = high_samplerate / low_samplerate; - if (state->factor < 1.0) { - fprintf(stderr, "Software error: Low sample rate must be lower than high sample rate, aborting!\n"); - abort(); - } - - iir_lowpass_init(&state->up.lp, filter_cutoff, high_samplerate, 2); - iir_lowpass_init(&state->down.lp, filter_cutoff, high_samplerate, 2); - - return 0; -} - -/* convert high sample rate to low sample rate */ -int samplerate_downsample(samplerate_t *state, sample_t *samples, int input_num) -{ - int output_num = 0, i, idx; - double factor = state->factor, in_index, diff; - sample_t output[(int)((double)input_num / factor + 0.5) + 10]; /* add some safety */ - sample_t last_sample; - - /* filter down */ - iir_process(&state->down.lp, samples, input_num); - - /* get last sample for interpolation */ - last_sample = state->down.last_sample; - - /* resample filtered result */ - in_index = state->down.in_index; - - for (i = 0; ; i++) { - /* convert index to int */ - idx = (int)in_index; - /* if index is outside input sample range, we are done */ - if (idx >= input_num) - break; - /* linear interpolation */ - diff = in_index - (double)idx; - if (idx) - output[i] = samples[idx - 1] * (1.0 - diff) + samples[idx] * diff; - else - output[i] = last_sample * (1.0 - diff) + samples[idx] * diff; - /* count output number */ - output_num++; - /* increment input index */ - in_index += factor; - } - - /* store last sample for interpolation */ - if (input_num) - state->down.last_sample = samples[input_num - 1]; - - /* remove number of input samples from index */ - in_index -= (double)input_num; - /* in_index cannot be negative, except due to rounding error, so... */ - if ((int)in_index < 0) - in_index = 0.0; - - state->down.in_index = in_index; - - /* copy samples */ - for (i = 0; i < output_num; i++) - *samples++ = output[i]; - - return output_num; -} - -/* convert low sample rate to high sample rate */ -int samplerate_upsample(samplerate_t *state, sample_t *input, int input_num, sample_t *output) -{ - int output_num = 0, i, idx; - double factor = 1.0 / state->factor, in_index, diff; - sample_t buff[(int)((double)input_num / factor + 0.5) + 10]; /* add some safety */ - sample_t *samples, last_sample; - - /* get last sample for interpolation */ - last_sample = state->up.last_sample; - - if (input == output) - samples = buff; - else - samples = output; - - /* resample input */ - in_index = state->up.in_index; - - for (i = 0; ; i++) { - /* convert index to int */ - idx = (int)in_index; - /* if index is outside input sample range, we are done */ - if (idx >= input_num) - break; - /* linear interpolation */ - diff = in_index - (double)idx; - if (idx) - samples[i] = input[idx - 1] * (1.0 - diff) + input[idx] * diff; - else - samples[i] = last_sample * (1.0 - diff) + input[idx] * diff; - /* count output number */ - output_num++; - /* increment input index */ - in_index += factor; - } - - /* store last sample for interpolation */ - if (input_num) - state->up.last_sample = input[input_num - 1]; - - /* remove number of input samples from index */ - in_index -= (double)input_num; - /* in_index cannot be negative, except due to rounding error, so... */ - if ((int)in_index < 0) - in_index = 0.0; - - state->up.in_index = in_index; - - /* filter up */ - iir_process(&state->up.lp, samples, output_num); - - if (input == output) { - /* copy samples */ - for (i = 0; i < output_num; i++) - *output++ = samples[i]; - } - - return output_num; -} - diff --git a/src/lib/libsamplerate/samplerate.h b/src/lib/libsamplerate/samplerate.h deleted file mode 100644 index 8f8ea87..0000000 --- a/src/lib/libsamplerate/samplerate.h +++ /dev/null @@ -1,19 +0,0 @@ -#include "../libfilter/iir_filter.h" - -typedef struct samplerate { - double factor; - struct { - iir_filter_t lp; - sample_t last_sample; - double in_index; - } down; - struct { - iir_filter_t lp; - sample_t last_sample; - double in_index; - } up; -} samplerate_t; - -int init_samplerate(samplerate_t *state, double low_samplerate, double high_samplerate, double filter_cutoff); -int samplerate_downsample(samplerate_t *state, sample_t *samples, int input_num); -int samplerate_upsample(samplerate_t *state, sample_t *input, int input_num, sample_t *output); diff --git a/src/lib/libsound/Makefile.am b/src/lib/libsound/Makefile.am deleted file mode 100644 index afbbb0a..0000000 --- a/src/lib/libsound/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) - -noinst_LIBRARIES = libsound.a - -libsound_a_SOURCES = \ - sound_alsa.c - -AM_CPPFLAGS += -DHAVE_ALSA diff --git a/src/lib/libsound/sound.h b/src/lib/libsound/sound.h deleted file mode 100644 index 173dfd3..0000000 --- a/src/lib/libsound/sound.h +++ /dev/null @@ -1,10 +0,0 @@ - -enum paging_signal; - -void *sound_open(const char *audiodev, double *tx_frequency, double *rx_frequency, int *am, int channels, double paging_frequency, int samplerate, int buffer_size, double interval, double max_deviation, double max_modulation, double modulation_index); -int sound_start(void *inst); -void sound_close(void *inst); -int sound_write(void *inst, sample_t **samples, uint8_t **power, int num, enum paging_signal *paging_signal, int *on, int channels); -int sound_read(void *inst, sample_t **samples, int num, int channels, double *rf_level_db); -int sound_get_tosend(void *inst, int buffer_size); - diff --git a/src/lib/libsound/sound_alsa.c b/src/lib/libsound/sound_alsa.c deleted file mode 100644 index 20a4a31..0000000 --- a/src/lib/libsound/sound_alsa.c +++ /dev/null @@ -1,535 +0,0 @@ -/* Sound device access - * - * (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 "../libsample/sample.h" -#include "../libdebug/debug.h" -#ifdef HAVE_MOBILE -#include "../libmobile/sender.h" -#else -#include "sound.h" -#endif - -typedef struct sound { - snd_pcm_t *phandle, *chandle; - int pchannels, cchannels; - int channels; /* required number of channels */ - int samplerate; /* required sample rate */ - char *audiodev; /* required device */ - double spl_deviation; /* how much deviation is one sample step */ -#ifdef HAVE_MOBILE - double paging_phaseshift; /* phase to shift every sample */ - double paging_phase; /* current phase */ - double rx_frequency[2]; /* rx frequency of radio connected to channel */ - dispmeasparam_t *dmp[2]; -#endif -} sound_t; - -static int set_hw_params(snd_pcm_t *handle, int samplerate, int *channels) -{ - snd_pcm_hw_params_t *hw_params = NULL; - int rc; - unsigned int rrate; - - rc = snd_pcm_hw_params_malloc(&hw_params); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "Failed to allocate hw_params! (%s)\n", snd_strerror(rc)); - goto error; - } - - rc = snd_pcm_hw_params_any(handle, hw_params); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "cannot initialize hardware parameter structure (%s)\n", snd_strerror(rc)); - goto error; - } - - rc = snd_pcm_hw_params_set_rate_resample(handle, hw_params, 0); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "cannot set real hardware rate (%s)\n", snd_strerror(rc)); - goto error; - } - - rc = snd_pcm_hw_params_set_access (handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "cannot set access to interleaved (%s)\n", snd_strerror(rc)); - goto error; - } - - rc = snd_pcm_hw_params_set_format(handle, hw_params, SND_PCM_FORMAT_S16); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "cannot set sample format (%s)\n", snd_strerror(rc)); - goto error; - } - - rrate = samplerate; - rc = snd_pcm_hw_params_set_rate_near(handle, hw_params, &rrate, 0); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "cannot set sample rate (%s)\n", snd_strerror(rc)); - goto error; - } - if ((int)rrate != samplerate) { - PDEBUG(DSOUND, DEBUG_ERROR, "Rate doesn't match (requested %dHz, get %dHz)\n", samplerate, rrate); - rc = -EIO; - goto error; - } - - *channels = 1; - rc = snd_pcm_hw_params_set_channels(handle, hw_params, *channels); - if (rc < 0) { - *channels = 2; - rc = snd_pcm_hw_params_set_channels(handle, hw_params, *channels); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "cannot set channel count to 1 nor 2 (%s)\n", snd_strerror(rc)); - goto error; - } - } - - rc = snd_pcm_hw_params(handle, hw_params); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "cannot set parameters (%s)\n", snd_strerror(rc)); - goto error; - } - - snd_pcm_hw_params_free(hw_params); - - return 0; - -error: - if (hw_params) { - snd_pcm_hw_params_free(hw_params); - } - - return rc; -} - -static int dev_open(sound_t *sound) -{ - int rc, rc_rec, rc_play; - - rc_play = snd_pcm_open(&sound->phandle, sound->audiodev, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); - rc_rec = snd_pcm_open(&sound->chandle, sound->audiodev, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK); - if (rc_play < 0 && rc_rec < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "Failed to open '%s'! (%s)\n", sound->audiodev, snd_strerror(rc_play)); - PDEBUG(DSOUND, DEBUG_ERROR, "Run 'aplay -l' to get a list of available cards and devices.\n"); - PDEBUG(DSOUND, DEBUG_ERROR, "Then use 'hw::' for audio device.\n"); - return rc_play; - } - if (rc_play < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "Failed to open '%s' for playback! (%s) Please select a device that supports both direction audio.\n", sound->audiodev, snd_strerror(rc_play)); - return rc_play; - } - if (rc_rec < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "Failed to open '%s' for capture! (%s) Please select a device that supports both direction audio.\n", sound->audiodev, snd_strerror(rc_rec)); - return rc_rec; - } - - rc = set_hw_params(sound->phandle, sound->samplerate, &sound->pchannels); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "Failed to set playback hw params\n"); - return rc; - } - if (sound->pchannels < sound->channels) { - PDEBUG(DSOUND, DEBUG_ERROR, "Sound card only supports %d channel for playback.\n", sound->pchannels); - return rc; - } - PDEBUG(DSOUND, DEBUG_DEBUG, "Playback with %d channels.\n", sound->pchannels); - - rc = set_hw_params(sound->chandle, sound->samplerate, &sound->cchannels); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "Failed to set capture hw params\n"); - return rc; - } - if (sound->cchannels < sound->channels) { - PDEBUG(DSOUND, DEBUG_ERROR, "Sound card only supports %d channel for capture.\n", sound->cchannels); - return -EIO; - } - PDEBUG(DSOUND, DEBUG_DEBUG, "Capture with %d channels.\n", sound->cchannels); - - rc = snd_pcm_prepare(sound->phandle); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "cannot prepare audio interface for use (%s)\n", snd_strerror(rc)); - return rc; - } - - rc = snd_pcm_prepare(sound->chandle); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "cannot prepare audio interface for use (%s)\n", snd_strerror(rc)); - return rc; - } - - return 0; -} - -static void dev_close(sound_t *sound) -{ - if (sound->phandle != NULL) - snd_pcm_close(sound->phandle); - if (sound->chandle != NULL) - snd_pcm_close(sound->chandle); -} - -void *sound_open(const char *audiodev, double __attribute__((unused)) *tx_frequency, double __attribute__((unused)) *rx_frequency, int __attribute__((unused)) *am, int channels, double __attribute__((unused)) paging_frequency, int samplerate, int __attribute((unused)) buffer_size, double __attribute__((unused)) interval, double max_deviation, double __attribute__((unused)) max_modulation, double __attribute__((unused)) modulation_index) -{ - sound_t *sound; - int rc; - - if (channels < 1 || channels > 2) { - PDEBUG(DSOUND, DEBUG_ERROR, "Cannot use more than two channels with the same sound card!\n"); - return NULL; - } - - sound = calloc(1, sizeof(sound_t)); - if (!sound) { - PDEBUG(DSOUND, DEBUG_ERROR, "Failed to alloc memory!\n"); - return NULL; - } - - sound->audiodev = strdup(audiodev); // is feed when closed - sound->channels = channels; - sound->samplerate = samplerate; - sound->spl_deviation = max_deviation / 32767.0; -#ifdef HAVE_MOBILE - sound->paging_phaseshift = 1.0 / ((double)samplerate / 1000.0); -#endif - - rc = dev_open(sound); - if (rc < 0) - goto error; - -#ifdef HAVE_MOBILE - if (rx_frequency) { - sender_t *sender; - int i; - for (i = 0; i < channels; i++) { - sound->rx_frequency[i] = rx_frequency[i]; - sender = get_sender_by_empfangsfrequenz(sound->rx_frequency[i]); - if (!sender) - continue; - sound->dmp[i] = display_measurements_add(&sender->dispmeas, "RX Level", "%.1f dB", DISPLAY_MEAS_PEAK, DISPLAY_MEAS_LEFT, -96.0, 0.0, -INFINITY); - } - } -#endif - - return sound; - -error: - sound_close(sound); - return NULL; -} - -/* start streaming */ -int sound_start(void *inst) -{ - sound_t *sound = (sound_t *)inst; - int16_t buff[2]; - - /* trigger capturing */ - snd_pcm_readi(sound->chandle, buff, 1); - - return 0; -} - -void sound_close(void *inst) -{ - sound_t *sound = (sound_t *)inst; - - dev_close(sound); - free(sound->audiodev); - free(sound); -} - -#ifdef HAVE_MOBILE -static void gen_paging_tone(sound_t *sound, int16_t *samples, int length, enum paging_signal paging_signal, int on) -{ - double phaseshift, phase; - int i; - - switch (paging_signal) { - case PAGING_SIGNAL_NOTONE: - /* no tone if paging signal is on */ - on = !on; - /* FALLTHRU */ - case PAGING_SIGNAL_TONE: - /* tone if paging signal is on */ - if (on) { - phaseshift = sound->paging_phaseshift; - phase = sound->paging_phase; - for (i = 0; i < length; i++) { - if (phase < 0.5) - *samples++ = 30000; - else - *samples++ = -30000; - phase += phaseshift; - if (phase >= 1.0) - phase -= 1.0; - } - sound->paging_phase = phase; - } else - memset(samples, 0, length << 1); - break; - case PAGING_SIGNAL_NEGATIVE: - /* negative signal if paging signal is on */ - on = !on; - /* FALLTHRU */ - case PAGING_SIGNAL_POSITIVE: - /* positive signal if paging signal is on */ - if (on) - memset(samples, 127, length << 1); - else - memset(samples, 128, length << 1); - break; - case PAGING_SIGNAL_NONE: - break; - } -} -#endif - -int sound_write(void *inst, sample_t **samples, uint8_t __attribute__((unused)) **power, int num, enum paging_signal __attribute__((unused)) *paging_signal, int __attribute__((unused)) *on, int channels) -{ - sound_t *sound = (sound_t *)inst; - double spl_deviation = sound->spl_deviation; - int32_t value; - int16_t buff[num << 1]; - int rc; - int i, ii; - - if (sound->pchannels == 2) { - /* two channels */ -#ifdef HAVE_MOBILE - if (paging_signal && on && paging_signal[0] != PAGING_SIGNAL_NONE) { - int16_t paging[num << 1]; - gen_paging_tone(sound, paging, num, paging_signal[0], on[0]); - for (i = 0, ii = 0; i < num; i++) { - value = samples[0][i] / spl_deviation; - if (value > 32767) - value = 32767; - else if (value < -32767) - value = -32767; - buff[ii++] = value; - buff[ii++] = paging[i]; - } - } else -#endif - if (channels == 2) { - for (i = 0, ii = 0; i < num; i++) { - value = samples[0][i] / spl_deviation; - if (value > 32767) - value = 32767; - else if (value < -32767) - value = -32767; - buff[ii++] = value; - value = samples[1][i] / spl_deviation; - if (value > 32767) - value = 32767; - else if (value < -32767) - value = -32767; - buff[ii++] = value; - } - } else { - for (i = 0, ii = 0; i < num; i++) { - value = samples[0][i] / spl_deviation; - if (value > 32767) - value = 32767; - else if (value < -32767) - value = -32767; - buff[ii++] = value; - buff[ii++] = value; - } - } - } else { - /* one channel */ - for (i = 0, ii = 0; i < num; i++) { - value = samples[0][i] / spl_deviation; - if (value > 32767) - value = 32767; - else if (value < -32767) - value = -32767; - buff[ii++] = value; - } - } - rc = snd_pcm_writei(sound->phandle, buff, num); - - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "failed to write audio to interface (%s)\n", snd_strerror(rc)); - if (rc == -EPIPE) { - dev_close(sound); - rc = dev_open(sound); - if (rc < 0) - return rc; - sound_start(sound); - return -EPIPE; /* indicate what happened */ - } - return rc; - } - - if (rc != num) - PDEBUG(DSOUND, DEBUG_ERROR, "short write to audio interface, written %d bytes, got %d bytes\n", num, rc); - - return rc; -} - -#define KEEP_FRAMES 8 /* minimum frames not to read, due to bug in ALSA */ - -int sound_read(void *inst, sample_t **samples, int num, int channels, double __attribute__((unused)) *rf_level_db) -{ - sound_t *sound = (sound_t *)inst; - double spl_deviation = sound->spl_deviation; - int16_t buff[num << 1]; - int32_t spl; - int32_t max[2], a; - int in, rc; - int i, ii; - - /* make valgrind happy, because snd_pcm_readi() does not seem to initially fill buffer with values */ - memset(buff, 0, sizeof(buff)); - - /* get samples in rx buffer */ - in = snd_pcm_avail(sound->chandle); - /* if not more than KEEP_FRAMES frames available, try next time */ - if (in <= KEEP_FRAMES) - return 0; - /* read some frames less than in buffer, because snd_pcm_readi() seems - * to corrupt last frames */ - in -= KEEP_FRAMES; - if (in > num) - in = num; - - rc = snd_pcm_readi(sound->chandle, buff, in); - - if (rc < 0) { - if (errno == EAGAIN) - return 0; - PDEBUG(DSOUND, DEBUG_ERROR, "failed to read audio from interface (%s)\n", snd_strerror(rc)); - /* recover read */ - if (rc == -EPIPE) { - dev_close(sound); - rc = dev_open(sound); - if (rc < 0) - return rc; - sound_start(sound); - return -EPIPE; /* indicate what happened */ - } - return rc; - } - - if (rc == 0) - return rc; - - if (sound->cchannels == 2) { - if (channels < 2) { - for (i = 0, ii = 0; i < rc; i++) { - spl = buff[ii++]; - spl += buff[ii++]; - a = (spl >= 0) ? spl : -spl; - if (i == 0 || a > max[0]) - max[0] = a; - samples[0][i] = (double)spl * spl_deviation; - } - } else { - for (i = 0, ii = 0; i < rc; i++) { - spl = buff[ii++]; - a = (spl >= 0) ? spl : -spl; - if (i == 0 || a > max[0]) - max[0] = a; - samples[0][i] = (double)spl * spl_deviation; - spl = buff[ii++]; - a = (spl >= 0) ? spl : -spl; - if (i == 0 || a > max[1]) - max[1] = a; - samples[1][i] = (double)spl * spl_deviation; - } - } - } else { - for (i = 0, ii = 0; i < rc; i++) { - spl = buff[ii++]; - a = (spl >= 0) ? spl : -spl; - if (i == 0 || a > max[0]) - max[0] = a; - samples[0][i] = (double)spl * spl_deviation; - } - } - -#ifdef HAVE_MOBILE - sender_t *sender; - for (i = 0; i < channels; i++) { - sender = get_sender_by_empfangsfrequenz(sound->rx_frequency[i]); - if (!sender) - continue; - display_measurements_update(sound->dmp[i], log10((double)max[i] / 32768.0) * 20, 0.0); - if (rf_level_db) - rf_level_db[i] = 0.0; - } -#endif - - return rc; -} - -/* - * get playback buffer space - * - * return number of samples to be sent */ -int sound_get_tosend(void *inst, int buffer_size) -{ - sound_t *sound = (sound_t *)inst; - int rc; - snd_pcm_sframes_t delay; - int tosend; - - rc = snd_pcm_delay(sound->phandle, &delay); - if (rc < 0) { - if (rc == -32) - PDEBUG(DSOUND, DEBUG_ERROR, "Buffer underrun: Please use higher buffer and enable real time scheduling\n"); - else - PDEBUG(DSOUND, DEBUG_ERROR, "failed to get delay from interface (%s)\n", snd_strerror(rc)); - if (rc == -EPIPE) { - dev_close(sound); - rc = dev_open(sound); - if (rc < 0) - return rc; - sound_start(sound); - return -EPIPE; /* indicate what happened */ - } - return rc; - } - - tosend = buffer_size - delay; - return tosend; -} - -int sound_is_stereo_capture(void *inst) -{ - sound_t *sound = (sound_t *)inst; - - if (sound->cchannels == 2) - return 1; - return 0; -} - -int sound_is_stereo_playback(void *inst) -{ - sound_t *sound = (sound_t *)inst; - - if (sound->pchannels == 2) - return 1; - return 0; -} - diff --git a/src/lib/libtimer/Makefile.am b/src/lib/libtimer/Makefile.am deleted file mode 100644 index 538670a..0000000 --- a/src/lib/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/lib/libtimer/timer.c b/src/lib/libtimer/timer.c deleted file mode 100644 index 174533f..0000000 --- a/src/lib/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/lib/libtimer/timer.h b/src/lib/libtimer/timer.h deleted file mode 100644 index 2073a8f..0000000 --- a/src/lib/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); -