Inital GIT import

This commit is contained in:
Andreas Eversberg 2020-09-12 13:10:46 +02:00
commit ec0042ae70
9 changed files with 2711 additions and 0 deletions

41
.gitignore vendored Normal file
View File

@ -0,0 +1,41 @@
Makefile
Makefile.in
.deps
.libs
*.o
*.lo
*.la
*.pc
aclocal.m4
acinclude.m4
aminclude.am
m4/*.m4
autom4te.cache
compile
config.h*
config.sub
config.log
config.status
config.guess
configure
depcomp
missing
ltmain.sh
install-sh
stamp-h1
libtool
tests/
.tarball-version
.version
.dirstamp
Doxyfile
.*.sw?
src/libdebug/libdebug.a
src/liboptions/liboptions.a
src/libosmocc/libosmocc.a
src/libtimer/libtimer.a
src/sip/osmo-cc-sip-endpoint

5
Makefile.am Normal file
View File

@ -0,0 +1,5 @@
AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src

97
configure.ac Normal file
View File

@ -0,0 +1,97 @@
AC_INIT([osmo-cc-sip-endpoint],
m4_esyscmd([./git-version-gen .tarball-version]),
[jolly@eversberg.eu])
dnl *This* is the root dir, even if an install-sh exists in ../ or ../../
AC_CONFIG_AUX_DIR([.])
AM_INIT_AUTOMAKE([subdir-objects dist-bzip2])
AC_CONFIG_TESTDIR(tests)
dnl kernel style compile messages
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
dnl include release helper
RELMAKE='-include osmo-release.mk'
AC_SUBST([RELMAKE])
dnl checks for programs
AC_PROG_MAKE_SET
AC_PROG_CC
AC_PROG_INSTALL
LT_INIT
AC_PROG_LIBTOOL
dnl check for pkg-config (explained in detail in libosmocore/configure.ac)
AC_PATH_PROG(PKG_CONFIG_INSTALLED, pkg-config, no)
if test "x$PKG_CONFIG_INSTALLED" = "xno"; then
AC_MSG_ERROR([You need to install pkg-config])
fi
AC_CONFIG_MACRO_DIRS([m4])
AC_CONFIG_MACRO_DIR([m4])
AC_ARG_ENABLE(sanitize,
[AS_HELP_STRING(
[--enable-sanitize],
[Compile with address sanitizer enabled],
)],
[sanitize=$enableval], [sanitize="no"])
if test x"$sanitize" = x"yes"
then
CFLAGS="$CFLAGS -fsanitize=address -fsanitize=undefined"
CPPFLAGS="$CPPFLAGS -fsanitize=address -fsanitize=undefined"
fi
AC_ARG_ENABLE(werror,
[AS_HELP_STRING(
[--enable-werror],
[Turn all compiler warnings into errors, with exceptions:
a) deprecation (allow upstream to mark deprecation without breaking builds);
b) "#warning" pragmas (allow to remind ourselves of errors without breaking builds)
]
)],
[werror=$enableval], [werror="no"])
if test x"$werror" = x"yes"
then
WERROR_FLAGS="-Werror"
WERROR_FLAGS+=" -Wno-error=deprecated -Wno-error=deprecated-declarations"
WERROR_FLAGS+=" -Wno-error=cpp" # "#warning"
CFLAGS="$CFLAGS $WERROR_FLAGS"
CPPFLAGS="$CPPFLAGS $WERROR_FLAGS"
fi
CFLAGS="$CFLAGS -Wall"
CPPFLAGS="$CPPFLAGS -Wall"
dnl checks for header files
AC_HEADER_STDC
AC_CHECK_HEADERS(execinfo.h sys/select.h sys/socket.h syslog.h ctype.h)
# The following test is taken from WebKit's webkit.m4
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -fvisibility=hidden "
AC_MSG_CHECKING([if ${CC} supports -fvisibility=hidden])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([char foo;])],
[ AC_MSG_RESULT([yes])
SYMBOL_VISIBILITY="-fvisibility=hidden"],
AC_MSG_RESULT([no]))
CFLAGS="$saved_CFLAGS"
AC_SUBST(SYMBOL_VISIBILITY)
dnl Generate the output
AM_CONFIG_HEADER(config.h)
PKG_CHECK_MODULES(SOFIA, sofia-sip-ua >= 1.12)
AC_CHECK_LIB([m], [main])
AC_CHECK_LIB([pthread], [main])
AC_OUTPUT(
src/liboptions/Makefile
src/libdebug/Makefile
src/libtimer/Makefile
src/libosmocc/Makefile
src/sip/Makefile
src/Makefile
Makefile)

151
git-version-gen Executable file
View File

@ -0,0 +1,151 @@
#!/bin/sh
# Print a version string.
scriptversion=2010-01-28.01
# Copyright (C) 2007-2010 Free Software Foundation, Inc.
#
# 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 <http://www.gnu.org/licenses/>.
# This script is derived from GIT-VERSION-GEN from GIT: http://git.or.cz/.
# It may be run two ways:
# - from a git repository in which the "git describe" command below
# produces useful output (thus requiring at least one signed tag)
# - from a non-git-repo directory containing a .tarball-version file, which
# presumes this script is invoked like "./git-version-gen .tarball-version".
# In order to use intra-version strings in your project, you will need two
# separate generated version string files:
#
# .tarball-version - present only in a distribution tarball, and not in
# a checked-out repository. Created with contents that were learned at
# the last time autoconf was run, and used by git-version-gen. Must not
# be present in either $(srcdir) or $(builddir) for git-version-gen to
# give accurate answers during normal development with a checked out tree,
# but must be present in a tarball when there is no version control system.
# Therefore, it cannot be used in any dependencies. GNUmakefile has
# hooks to force a reconfigure at distribution time to get the value
# correct, without penalizing normal development with extra reconfigures.
#
# .version - present in a checked-out repository and in a distribution
# tarball. Usable in dependencies, particularly for files that don't
# want to depend on config.h but do want to track version changes.
# Delete this file prior to any autoconf run where you want to rebuild
# files to pick up a version string change; and leave it stale to
# minimize rebuild time after unrelated changes to configure sources.
#
# It is probably wise to add these two files to .gitignore, so that you
# don't accidentally commit either generated file.
#
# Use the following line in your configure.ac, so that $(VERSION) will
# automatically be up-to-date each time configure is run (and note that
# since configure.ac no longer includes a version string, Makefile rules
# should not depend on configure.ac for version updates).
#
# AC_INIT([GNU project],
# m4_esyscmd([build-aux/git-version-gen .tarball-version]),
# [bug-project@example])
#
# Then use the following lines in your Makefile.am, so that .version
# will be present for dependencies, and so that .tarball-version will
# exist in distribution tarballs.
#
# BUILT_SOURCES = $(top_srcdir)/.version
# $(top_srcdir)/.version:
# echo $(VERSION) > $@-t && mv $@-t $@
# dist-hook:
# echo $(VERSION) > $(distdir)/.tarball-version
case $# in
1) ;;
*) echo 1>&2 "Usage: $0 \$srcdir/.tarball-version"; exit 1;;
esac
tarball_version_file=$1
nl='
'
# First see if there is a tarball-only version file.
# then try "git describe", then default.
if test -f $tarball_version_file
then
v=`cat $tarball_version_file` || exit 1
case $v in
*$nl*) v= ;; # reject multi-line output
[0-9]*) ;;
*) v= ;;
esac
test -z "$v" \
&& echo "$0: WARNING: $tarball_version_file seems to be damaged" 1>&2
fi
if test -n "$v"
then
: # use $v
elif
v=`git describe --abbrev=4 --match='v*' HEAD 2>/dev/null \
|| git describe --abbrev=4 HEAD 2>/dev/null` \
&& case $v in
[0-9]*) ;;
v[0-9]*) ;;
*) (exit 1) ;;
esac
then
# Is this a new git that lists number of commits since the last
# tag or the previous older version that did not?
# Newer: v6.10-77-g0f8faeb
# Older: v6.10-g0f8faeb
case $v in
*-*-*) : git describe is okay three part flavor ;;
*-*)
: git describe is older two part flavor
# Recreate the number of commits and rewrite such that the
# result is the same as if we were using the newer version
# of git describe.
vtag=`echo "$v" | sed 's/-.*//'`
numcommits=`git rev-list "$vtag"..HEAD | wc -l`
v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`;
;;
esac
# Change the first '-' to a '.', so version-comparing tools work properly.
# Remove the "g" in git describe's output string, to save a byte.
v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/'`;
else
v=UNKNOWN
fi
v=`echo "$v" |sed 's/^v//'`
# Don't declare a version "dirty" merely because a time stamp has changed.
git status > /dev/null 2>&1
dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty=
case "$dirty" in
'') ;;
*) # Append the suffix only if there isn't one already.
case $v in
*-dirty) ;;
*) v="$v-dirty" ;;
esac ;;
esac
# Omit the trailing newline, so that m4_esyscmd can use the result directly.
echo "$v" | tr -d '\012'
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-end: "$"
# End:

9
src/Makefile.am Normal file
View File

@ -0,0 +1,9 @@
AUTOMAKE_OPTIONS = foreign
SUBDIRS = \
liboptions \
libdebug \
libtimer \
libosmocc \
sip

17
src/sip/Makefile.am Normal file
View File

@ -0,0 +1,17 @@
AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) $(SOFIA_CFLAGS)
bin_PROGRAMS = \
osmo-cc-sip-endpoint
osmo_cc_sip_endpoint_SOURCES = \
sip.c \
main.c
osmo_cc_sip_endpoint_LDADD = \
$(COMMON_LA) \
../libdebug/libdebug.a \
../liboptions/liboptions.a \
../libtimer/libtimer.a \
../libosmocc/libosmocc.a \
$(SOFIA_LIBS)

371
src/sip/main.c Normal file
View File

@ -0,0 +1,371 @@
/* osmo-cc-sip-endpoint main
*
* (C) 2020 by Andreas Eversberg <jolly@eversberg.eu>
* 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 <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include "../libdebug/debug.h"
#include "../liboptions/options.h"
#include "sip.h"
sip_endpoint_t *sip_ep = NULL;
int num_kanal = 1;
int sofia_debug = 0;
int send_no_ringing_after_progress = 0;
int receive_no_ringing_after_progress = 0;
const char *name = "sip";
const char *local_user = NULL;
const char *local_peer = NULL;
const char *remote_user = NULL;
const char *remote_peer = NULL;
const char *asserted_id = NULL;
int local_register = 0;
int remote_register = 0;
const char *register_user = NULL;
const char *register_peer = NULL;
int local_auth = 0;
int remote_auth = 0;
const char *auth_user = NULL;
const char *auth_password = NULL;
const char *auth_realm = NULL;
const char *public_ip = NULL;
const char *stun_server = NULL;
int register_interval = 600;
int options_interval = 60;
int stun_interval = 60;
int expires = 0;
#define MAX_CC_ARGS 1024
static int cc_argc = 0;
static const char *cc_argv[MAX_CC_ARGS];
static void print_usage(const char *app)
{
printf("Usage: %s --local [<user>@]<address> --remote [<user>@]<address> [<options>]\n", app);
}
static void print_help()
{
/* - - */
printf(" -h --help\n");
printf(" This help\n");
printf(" -v --verbose <level> | <level>,<category>[,<category>[,...]] | 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(" -D --sofia-debug <level>\n");
printf(" A level of 0 is off, a level of 9 is full debugging. (default = %d)\n", sofia_debug);
printf(" --send-ner\n");
printf(" Do not send extra ringing response (180), after progress response (183)\n");
printf(" was sent.\n");
printf(" --receive-ner\n");
printf(" Do not expect to receive extra ringing response (180), after progress\n");
printf(" response (183) was received.\n");
printf(" -n --name <interface name>\n");
printf(" Give name of this interface. It will be sent in each call towards\n");
printf(" remote interface. (default = '%s')\n", name);
printf(" -l --local [<user>@]<address>\n");
printf(" Give local SIP peer. It will be used for local URI.\n");
printf(" If user is not given, the caller ID is used as user.\n");
printf(" -r --remote [<user>@]<address>\n");
printf(" Give remote SIP peer. It will be used for remote URI.\n");
printf(" If user is not given, the dialed number is used as user.\n");
printf(" -a --asserted-id <user>\n");
printf(" The asserted ID is used to idenitfy the actual SIP user, if the local\n");
printf(" and remote user in their URI are replaced by caller ID and dialed\n");
printf(" number. To send caller ID, you must not specify user at local SIP peer.\n");
printf(" To send dialed number, you must not specify user at remote SIP peer.\n");
printf(" -R --register <user>@<address>\n");
printf(" Give user and address to register at a remote SIP registrar.\n");
printf(" --local-register\n");
printf(" Define, if the remote must register to us, so that we know the remote\n");
printf(" address.\n");
printf(" --remote-register\n");
printf(" Define, if we must register to a registrar.\n");
printf(" If '--register' was given, but not any of '--local-register' or\n");
printf(" '--remote-register', remote registration automatically used.\n");
printf(" -A --auth <user> <password> <realm>\n");
printf(" Define, if we must perform authentication.\n");
printf(" Realm can be set to anything. It is relevant for local authentication.\n");
printf(" --local-auth\n");
printf(" Define, if the remote must authenticate when calling (or registering)\n");
printf(" to us.\n");
printf(" --remote-auth\n");
printf(" Define, if we must authenticate when calling (or registering) towards\n");
printf(" remote.\n");
printf(" If '--auth' was given, but not any of '--local-auth' or\n");
printf(" '--remote-auth', remote authentication automatically used.\n");
printf(" -P --public-ip <ip>\n");
printf(" If our local IP is changed by NAT, give the actual public IP.\n");
printf(" -S --stun-server <address>\n");
printf(" Instead of dynamic public IP, a STUN server can be given.\n");
printf(" --register-interval <seconds> (default = %d seconds)\n", register_interval);
printf(" --options-interval <seconds> (default = %d seconds)\n", options_interval);
printf(" --stun-interval <seconds> (default = %d seconds)\n", stun_interval);
printf(" --expires <seconds> | 0 (default = %d seconds)\n", expires);
printf(" Alter intervals, if needed.\n");
printf(" -C --cc \"<osmo-cc arg>\" [--cc ...]\n");
printf(" Pass arguments to Osmo-CC endpoint. Use '-cc help' for description.\n");
}
#define OPT_SEND_NER 256
#define OPT_RECEIVE_NER 257
#define OPT_LOCAL_REG 258
#define OPT_REMOTE_REG 259
#define OPT_LOCAL_AUTH 260
#define OPT_REMOTE_AUTH 261
#define OPT_REG_INTER 262
#define OPT_OPT_INTER 263
#define OPT_STUN_INTER 264
#define OPT_EXPIRES 265
static void add_options(void)
{
option_add('h', "help", 0);
option_add('v', "verbose", 1);
option_add('D', "sofia-debug", 1);
option_add(OPT_SEND_NER, "send-ner", 0);
option_add(OPT_RECEIVE_NER, "receive-ner", 0);
option_add('n', "name", 1);
option_add('l', "local", 1);
option_add('r', "remote", 1);
option_add('a', "asserted-id", 1);
option_add('R', "register", 1);
option_add(OPT_LOCAL_REG, "local-register", 0);
option_add(OPT_REMOTE_REG, "remote-register", 0);
option_add('A', "auth", 3);
option_add(OPT_LOCAL_AUTH, "local-auth", 0);
option_add(OPT_REMOTE_AUTH, "remote-auth", 0);
option_add('P', "public-ip", 1);
option_add('S', "stun-server", 1);
option_add(OPT_REG_INTER, "register-interval", 1);
option_add(OPT_OPT_INTER, "options-interval", 1);
option_add(OPT_STUN_INTER, "stun-interval", 1);
option_add(OPT_EXPIRES, "expires", 1);
option_add('C', "cc", 1);
}
static int handle_options(int short_option, int argi, char **argv)
{
const char *p;
int rc;
switch (short_option) {
case 'h':
print_usage(argv[0]);
print_help();
return 0;
case 'v':
if (!strcasecmp(argv[argi], "list")) {
debug_list_cat();
return 0;
}
rc = parse_debug_opt(argv[argi]);
if (rc < 0) {
fprintf(stderr, "Failed to parse debug option, please use -h for help.\n");
return rc;
}
break;
case 'D':
sofia_debug = atoi(argv[argi]);
break;
case OPT_SEND_NER:
send_no_ringing_after_progress = 1;
break;
case OPT_RECEIVE_NER:
receive_no_ringing_after_progress = 1;
break;
case 'n':
name = strdup(argv[argi]);
break;
case 'l':
if ((p = strchr(argv[argi], '@'))) {
local_user = strdup(argv[argi]);
*strchr(local_user, '@') = '\0';
local_peer = strdup(p + 1);
} else
local_peer = strdup(argv[argi]);
break;
case 'r':
if ((p = strchr(argv[argi], '@'))) {
remote_user = strdup(argv[argi]);
*strchr(remote_user, '@') = '\0';
remote_peer = strdup(p + 1);
} else
remote_peer = strdup(argv[argi]);
break;
case 'a':
asserted_id = strdup(argv[argi]);
break;
case 'R':
if ((p = strchr(argv[argi], '@'))) {
register_user = strdup(argv[argi]);
*strchr(register_user, '@') = '\0';
register_peer = strdup(p + 1);
} else {
fprintf(stderr, "Missing '@' sign in given registrar!\n");
return -EINVAL;
}
break;
case OPT_LOCAL_REG:
local_register = 1;
break;
case OPT_REMOTE_REG:
remote_register = 1;
break;
case 'A':
auth_user = strdup(argv[argi]);
auth_password = strdup(argv[argi + 1]);
auth_realm = strdup(argv[argi + 2]);
break;
case OPT_LOCAL_AUTH:
local_auth = 1;
break;
case OPT_REMOTE_AUTH:
remote_auth = 1;
break;
case 'P':
public_ip = strdup(argv[argi]);
break;
case 'S':
stun_server = strdup(argv[argi]);
break;
case OPT_REG_INTER:
register_interval = atoi(argv[argi]);
break;
case OPT_OPT_INTER:
options_interval = atoi(argv[argi]);
break;
case OPT_STUN_INTER:
stun_interval = atoi(argv[argi]);
break;
case OPT_EXPIRES:
expires = atoi(argv[argi]);
break;
case 'C':
if (!strcasecmp(argv[argi], "help")) {
osmo_cc_help();
return 0;
}
if (cc_argc == MAX_CC_ARGS) {
fprintf(stderr, "Too many osmo-cc args!\n");
break;
}
cc_argv[cc_argc++] = strdup(argv[argi]);
break;
default:
return -EINVAL;
}
return 1;
}
static int quit = 0;
void sighandler(int sigset)
{
if (sigset == SIGHUP || sigset == SIGPIPE)
return;
fprintf(stderr, "\nSignal %d received.\n", sigset);
quit = 1;
}
int main(int argc, char *argv[])
{
int argi, rc;
cc_argv[cc_argc++] = strdup("remote auto");
/* handle options / config file */
add_options();
rc = options_config_file("~/.osmocom/sip/sip.conf", handle_options);
if (rc < 0)
return 0;
argi = options_command_line(argc, argv, handle_options);
if (argi <= 0)
return argi;
sip_init(sofia_debug);
/* complete remote register and authentication flag */
if (register_peer && !local_register && !remote_register)
remote_register = 1;
if (auth_user && !local_auth && !remote_auth)
remote_auth = 1;
if (!local_peer) {
PDEBUG(DSIP, DEBUG_ERROR, "You must specify local SIP peer!\n");
return -EINVAL;
}
if (!remote_peer) {
PDEBUG(DSIP, DEBUG_ERROR, "You must specify remote SIP peer!\n");
return -EINVAL;
}
if (!cc_argc || !!strncasecmp(cc_argv[0], "help", 4)) {
sip_ep = sip_endpoint_create(send_no_ringing_after_progress, receive_no_ringing_after_progress, name, local_user, local_peer, remote_user, remote_peer, asserted_id, local_register, remote_register, register_user, register_peer, local_auth, remote_auth, auth_user, auth_password, auth_realm, public_ip, stun_server, register_interval, options_interval, stun_interval, expires);
if (!sip_ep) {
PDEBUG(DSIP, DEBUG_ERROR, "SIP initializing failed!\n");
goto error;
}
}
rc = osmo_cc_new(&sip_ep->cc_ep, OSMO_CC_VERSION, name, OSMO_CC_LOCATION_BEYOND_INTERWORKING, cc_message, NULL, sip_ep, cc_argc, cc_argv);
if (rc)
goto error;
signal(SIGINT, sighandler);
signal(SIGHUP, sighandler);
signal(SIGTERM, sighandler);
signal(SIGPIPE, sighandler);
while (!quit) {
int w;
process_timer();
sip_handle(sip_ep);
do {
w = 0;
w |= osmo_cc_handle();
} while (w);
usleep(1000);
}
signal(SIGINT, SIG_DFL);
signal(SIGTSTP, SIG_DFL);
signal(SIGHUP, SIG_DFL);
signal(SIGTERM, SIG_DFL);
signal(SIGPIPE, SIG_DFL);
error:
if (sip_ep) {
osmo_cc_delete(&sip_ep->cc_ep);
sip_endpoint_destroy(sip_ep);
}
sip_exit();
return 0;
}

1905
src/sip/sip.c Normal file

File diff suppressed because it is too large Load Diff

115
src/sip/sip.h Normal file
View File

@ -0,0 +1,115 @@
#include "../libtimer/timer.h"
#include "../libosmocc/endpoint.h"
#include <sofia-sip/nua.h>
#include <sofia-sip/stun.h>
#define STUN_RETRY_TIMER 10
#define REGISTER_RETRY_TIMER 10
enum reg_state {
REGISTER_STATE_NULL = 0,
REGISTER_STATE_UNREGISTERED,
REGISTER_STATE_REGISTERING,
REGISTER_STATE_REGISTERED,
REGISTER_STATE_FAILED,
};
enum stun_state {
STUN_STATE_NULL = 0,
STUN_STATE_UNRESOLVED,
STUN_STATE_RESOLVING,
STUN_STATE_RESOLVED,
STUN_STATE_FAILED,
};
enum sip_state {
SIP_STATE_IDLE = 0,
SIP_STATE_OUT_INVITE, /* invite sent, waiting for replies */
SIP_STATE_IN_INVITE, /* invite received, sending replies */
SIP_STATE_CONNECT, /* active call */
SIP_STATE_OUT_RELEASE, /* outgoing release, sending REL_CNF */
};
struct sip_call;
typedef struct sip_endpoint {
/* setting flags */
int send_no_ringing_after_progress;
int receive_no_ringing_after_progress;
/* endpoint */
osmo_cc_endpoint_t cc_ep;
const char *name;
struct sip_call *call_list;
/* SIP settings */
const char *local_user;
const char *local_peer;
const char *remote_user;
const char *remote_peer;
const char *asserted_id;
int local_register;
int remote_register;
const char *register_user;
const char *register_peer;
int authenticate_local;
int authenticate_remote;
const char *auth_user;
const char *auth_password;
const char *auth_realm;
/* NAT help */
char public_ip[256];
const char *stun_server;
/* timers */
int register_interval;
int options_interval;
int stun_interval;
struct timer stun_retry_timer;
struct timer register_retry_timer;
struct timer register_option_timer;
/* SIP stack */
su_root_t *su_root;
nua_t *nua;
nua_handle_t *register_handle;
/* register process */
char remote_contact[256];
char register_nonce[64];
char invite_nonce[64];
enum reg_state register_state;
enum stun_state stun_state;
/* stun process */
stun_handle_t *stun_handle;
su_socket_t stun_socket;
} sip_endpoint_t;
typedef struct sip_call {
struct sip_call *next;
osmo_cc_call_t *cc_call;
uint32_t cc_callref;
sip_endpoint_t *sip_ep;
enum sip_state state;
nua_handle_t *nua_handle;
struct timer invite_option_timer;
char *sdp_request, *sdp_response;
int sdp_sent;
int alerting_sent;
} call_t;
void cc_message(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg);
sip_endpoint_t *sip_endpoint_create(int send_no_ringing_after_progress, int receive_no_ringing_after_progress, const char *name, const char *local_user, const char *local_peer, const char *remote_user, const char *remote_peer, const char *asserted_id, int local_register, int remote_register, const char *register_user, const char *register_peer, int authenticate_local, int authenticate_remote, const char *auth_user, const char *auth_password, const char *auth_realm, const char *public_ip, const char *stun_server, int register_interval, int options_interval, int stun_interval, int expires);
void sip_endpoint_destroy(sip_endpoint_t *sip_ep);
int sip_init(int debug_level);
void sip_exit(void);
void sip_handle(sip_endpoint_t *sip_ep);