From 805ed34740f29b6b73b934dbe86aa12271f2fd93 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sun, 7 Jan 2024 18:07:42 +0100 Subject: [PATCH 1/9] Updated libs --- src/libg711/g711.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/libg711/g711.c b/src/libg711/g711.c index bbbdde5..92404c1 100644 --- a/src/libg711/g711.c +++ b/src/libg711/g711.c @@ -14,7 +14,7 @@ #include /* ulaw -> signed 16-bit */ -static int16_t g711_ulaw_flipped_to_linear[256] = +static int16_t g711_ulaw_to_linear[256] = { 0x8284, 0x8684, 0x8a84, 0x8e84, 0x9284, 0x9684, 0x9a84, 0x9e84, 0xa284, 0xa684, 0xaa84, 0xae84, 0xb284, 0xb684, 0xba84, 0xbe84, @@ -89,7 +89,7 @@ static int16_t g711_alaw_flipped_to_linear[256] = /* Xlaw -> signed 16-bit */ static int16_t g711_alaw_to_linear[256]; -static int16_t g711_ulaw_to_linear[256]; +static int16_t g711_ulaw_flipped_to_linear[256]; /* signed 16-bit -> Xlaw */ static uint8_t g711_linear_to_alaw_flipped[65536]; @@ -196,7 +196,7 @@ void g711_init(void) + ((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]]; + g711_ulaw_flipped_to_linear[i] = g711_ulaw_to_linear[g711_flip[i]]; } /* linear to alaw tables */ @@ -214,18 +214,18 @@ void g711_init(void) /* linear to ulaw tables */ i = j = 0; while(i < 32768) { - if (i - 32768 > g711_ulaw_flipped_to_linear[j]) + if (i - 32768 > g711_ulaw_to_linear[j]) j++; - g711_linear_to_ulaw_flipped[(i - 32768) & 0xffff] = j; - g711_linear_to_ulaw[(i - 32768) & 0xffff] = g711_flip[j]; + g711_linear_to_ulaw[(i - 32768) & 0xffff] = j; + g711_linear_to_ulaw_flipped[(i - 32768) & 0xffff] = g711_flip[j]; i++; } j = 255; while(i < 65536) { - if (i - 32768 > g711_alaw_flipped_to_linear[j]) + if (i - 32768 > g711_ulaw_to_linear[j]) j--; - g711_linear_to_ulaw_flipped[(i - 32768) & 0xffff] = j; - g711_linear_to_ulaw[(i - 32768) & 0xffff] = g711_flip[j]; + g711_linear_to_ulaw[(i - 32768) & 0xffff] = j; + g711_linear_to_ulaw_flipped[(i - 32768) & 0xffff] = g711_flip[j]; i++; } From da94632e6e9a78c17ca3e4ac12b6497d92d01f5c Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Tue, 9 Jan 2024 12:24:14 +0100 Subject: [PATCH 2/9] Move from local to external osmo* libraries src/libdebug -> libosmocore src/libselect -> libosmocore src/libtimer -> libosmocore src/libosmocc -> libosmo-cc src/libg711 -> libosmo-cc --- .gitignore | 6 +- configure.ac | 9 +- src/Makefile.am | 6 +- src/isdn/Makefile.am | 10 +- src/isdn/bridge.c | 123 ++- src/isdn/dss1.c | 168 ++-- src/isdn/ie.c | 425 ++++----- src/isdn/isdn.c | 354 ++++---- src/isdn/isdn.h | 14 +- src/isdn/main.c | 50 +- src/isdn/ph_driver.c | 4 +- src/isdn/tones.c | 8 +- src/libdebug/Makefile.am | 7 - src/libdebug/debug.c | 331 ------- src/libdebug/debug.h | 94 -- src/libg711/Makefile.am | 7 - src/libg711/g711.c | 537 ------------ src/libg711/g711.h | 17 - src/libjitter/jitter.c | 48 +- src/liblogging/Makefile.am | 8 + src/liblogging/categories.c | 42 + src/liblogging/categories.h | 13 + src/liblogging/logging.c | 272 ++++++ src/liblogging/logging.h | 21 + src/libmisdn/core.c | 10 +- src/libmisdn/fsm.c | 20 +- src/libmisdn/fsm.h | 2 +- src/libmisdn/mISDNhw.h | 4 +- src/libmisdn/mISDNif.h | 10 +- src/libmisdn/mlist.h | 44 +- src/libmisdn/printk.c | 34 +- src/libmisdn/printk.h | 15 +- src/libmisdn/socket.c | 6 +- src/libmisdn/stack.c | 14 +- src/libmisdn/timer.h | 8 +- src/liboptions/options.c | 40 +- src/libosmocc/Makefile.am | 15 - src/libosmocc/cause.c | 251 ------ src/libosmocc/cause.h | 5 - src/libosmocc/endpoint.c | 1585 ---------------------------------- src/libosmocc/endpoint.h | 131 --- src/libosmocc/helper.c | 194 ----- src/libosmocc/helper.h | 13 - src/libosmocc/message.c | 1294 --------------------------- src/libosmocc/message.h | 513 ----------- src/libosmocc/rtp.c | 484 ----------- src/libosmocc/rtp.h | 7 - src/libosmocc/screen.c | 694 --------------- src/libosmocc/screen.h | 7 - src/libosmocc/sdp.c | 545 ------------ src/libosmocc/sdp.h | 6 - src/libosmocc/session.c | 625 -------------- src/libosmocc/session.h | 134 --- src/libosmocc/socket.c | 619 ------------- src/libosmocc/socket.h | 44 - src/libph_socket/ph_socket.c | 19 +- src/libph_socket/ph_socket.h | 16 +- src/libselect/Makefile.am | 6 - src/libselect/select.c | 168 ---- src/libselect/select.h | 20 - src/libtimer/Makefile.am | 6 - src/libtimer/timer.c | 165 ---- src/libtimer/timer.h | 23 - 63 files changed, 1093 insertions(+), 9277 deletions(-) delete mode 100644 src/libdebug/Makefile.am delete mode 100644 src/libdebug/debug.c delete mode 100644 src/libdebug/debug.h delete mode 100644 src/libg711/Makefile.am delete mode 100644 src/libg711/g711.c delete mode 100644 src/libg711/g711.h create mode 100644 src/liblogging/Makefile.am create mode 100644 src/liblogging/categories.c create mode 100644 src/liblogging/categories.h create mode 100644 src/liblogging/logging.c create mode 100644 src/liblogging/logging.h delete mode 100644 src/libosmocc/Makefile.am delete mode 100644 src/libosmocc/cause.c delete mode 100644 src/libosmocc/cause.h delete mode 100644 src/libosmocc/endpoint.c delete mode 100644 src/libosmocc/endpoint.h delete mode 100644 src/libosmocc/helper.c delete mode 100644 src/libosmocc/helper.h delete mode 100644 src/libosmocc/message.c delete mode 100644 src/libosmocc/message.h delete mode 100644 src/libosmocc/rtp.c delete mode 100644 src/libosmocc/rtp.h delete mode 100644 src/libosmocc/screen.c delete mode 100644 src/libosmocc/screen.h delete mode 100644 src/libosmocc/sdp.c delete mode 100644 src/libosmocc/sdp.h delete mode 100644 src/libosmocc/session.c delete mode 100644 src/libosmocc/session.h delete mode 100644 src/libosmocc/socket.c delete mode 100644 src/libosmocc/socket.h delete mode 100644 src/libselect/Makefile.am delete mode 100644 src/libselect/select.c delete mode 100644 src/libselect/select.h delete mode 100644 src/libtimer/Makefile.am delete mode 100644 src/libtimer/timer.c delete mode 100644 src/libtimer/timer.h diff --git a/.gitignore b/.gitignore index 6dfb660..65f9260 100644 --- a/.gitignore +++ b/.gitignore @@ -33,14 +33,10 @@ Doxyfile .*.sw? -src/libdebug/libdebug.a -src/libg711/libg711.a +src/liblogging/liblogging.a src/libjitter/libjitter.a src/liboptions/liboptions.a -src/libosmocc/libosmocc.a src/libsample/libsample.a -src/libtimer/libtimer.a -src/libselect/libselect.a src/libph_socket/libph_socket.a src/libmisdn/libmisdn.a src/libmisdnuser/libmisdnuser.a diff --git a/configure.ac b/configure.ac index 8383c2e..62f753d 100644 --- a/configure.ac +++ b/configure.ac @@ -79,15 +79,14 @@ AM_CONFIG_HEADER(config.h) AC_CHECK_LIB([m], [main]) AC_CHECK_LIB([pthread], [main]) +PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.9.0) +PKG_CHECK_MODULES(LIBOSMOCC, libosmocc >= 1.0.0) + AC_OUTPUT( src/liboptions/Makefile - src/libdebug/Makefile + src/liblogging/Makefile src/libsample/Makefile - src/libtimer/Makefile - src/libselect/Makefile src/libjitter/Makefile - src/libosmocc/Makefile - src/libg711/Makefile src/libph_socket/Makefile src/libmisdn/Makefile src/libmisdnuser/Makefile diff --git a/src/Makefile.am b/src/Makefile.am index 464280a..b916f61 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,13 +2,9 @@ AUTOMAKE_OPTIONS = foreign SUBDIRS = \ liboptions \ - libdebug \ + liblogging \ libsample \ - libtimer \ - libselect \ libjitter \ - libosmocc \ - libg711 \ libph_socket \ libmisdn \ libmisdnuser \ diff --git a/src/isdn/Makefile.am b/src/isdn/Makefile.am index e67590a..d5376fd 100644 --- a/src/isdn/Makefile.am +++ b/src/isdn/Makefile.am @@ -14,17 +14,15 @@ osmo_cc_misdn_endpoint_SOURCES = \ osmo_cc_misdn_endpoint_LDADD = \ $(COMMON_LA) \ - ../libdebug/libdebug.a \ ../liboptions/liboptions.a \ ../libsample/libsample.a \ - ../libtimer/libtimer.a \ - ../libselect/libselect.a \ ../libjitter/libjitter.a \ - ../libosmocc/libosmocc.a \ - ../libg711/libg711.a \ ../libph_socket/libph_socket.a \ ../libmisdn/libmisdn.a \ - ../libmisdnuser/libmisdnuser.a + ../libmisdnuser/libmisdnuser.a \ + ../liblogging/liblogging.a \ + $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOCC_LIBS) # -lmisdn diff --git a/src/isdn/bridge.c b/src/isdn/bridge.c index de5c522..7a1fd2e 100644 --- a/src/isdn/bridge.c +++ b/src/isdn/bridge.c @@ -68,7 +68,7 @@ #include #include #include -#include "../libdebug/debug.h" +#include "../liblogging/logging.h" #include #include "isdn.h" #include "bridge.h" @@ -139,7 +139,7 @@ struct channel { }; static struct osmo_fd server_ofd = { .fd = -1 }; -static struct timer server_timer; +static struct osmo_timer_list server_timer; static struct conn *conn_list = NULL; static struct channel *channel_list = NULL; @@ -190,7 +190,7 @@ static void free_all_connections(void) c = conn_list; while (c) { - PDEBUG(DISDN, DEBUG_INFO, "Free pending bridge connection.\n"); + LOGP(DISDN, LOGL_INFO, "Free pending bridge connection.\n"); c2 = c; osmo_fd_unregister(&c->ofd); close(c->ofd.fd); @@ -214,7 +214,7 @@ static int open_server_socket(int daemon) rc = socket(PF_UNIX, SOCK_STREAM, 0); if (rc < 0) { - PDEBUG(DISDN, DEBUG_ERROR, "Failed to create UNIX socket.\n"); + LOGP(DISDN, LOGL_ERROR, "Failed to create UNIX socket.\n"); return rc; } server_ofd.fd = rc; @@ -226,7 +226,7 @@ static int open_server_socket(int daemon) rc = bind(server_ofd.fd, (struct sockaddr *)(&sock_address), sizeof(struct sockaddr_un)); if (rc < 0) { if (!daemon || errno != EADDRINUSE) - PDEBUG(DISDN, DEBUG_INFO, "Failed to bind UNIX socket with path '%s' (errno = %d (%s)).\n", SOCKET_NAME, errno, strerror(errno)); + LOGP(DISDN, LOGL_INFO, "Failed to bind UNIX socket with path '%s' (errno = %d (%s)).\n", SOCKET_NAME, errno, strerror(errno)); osmo_fd_unregister(&server_ofd); close(server_ofd.fd); return -EADDRINUSE; @@ -234,7 +234,7 @@ static int open_server_socket(int daemon) rc = listen(server_ofd.fd, 10); if (rc < 0) { - PDEBUG(DISDN, DEBUG_INFO, "Failed to listen to UNIX socket with path '%s' (errno = %d (%s)).\n", SOCKET_NAME, errno, strerror(errno)); + LOGP(DISDN, LOGL_INFO, "Failed to listen to UNIX socket with path '%s' (errno = %d (%s)).\n", SOCKET_NAME, errno, strerror(errno)); osmo_fd_unregister(&server_ofd); close(server_ofd.fd); return rc; @@ -255,11 +255,11 @@ static int bridge_socket_server_cb(struct osmo_fd __attribute__((unused)) *ofd, if ((when & OSMO_FD_READ)) { rc = accept(server_ofd.fd, (struct sockaddr *)&sock_address, &sock_len); if (rc > 0) { - PDEBUG(DISDN, DEBUG_INFO, "Connection from bridge socket client.\n"); + LOGP(DISDN, LOGL_INFO, "Connection from bridge socket client.\n"); /* create connection */ c = calloc(1, sizeof(*c)); if (!c) { - PDEBUG(DISDN, DEBUG_ERROR, "No mem!\n"); + LOGP(DISDN, LOGL_ERROR, "No mem!\n"); abort(); } c->next = conn_list; @@ -313,10 +313,10 @@ static int bridge_socket_conn_cb(struct osmo_fd *ofd, unsigned int when) if (rc > 0) { c->rx_index += rc; if (c->rx_index == sizeof(c->rx_msg)) { - PDEBUG(DISDN, DEBUG_DEBUG, "Message from bridge socket client.\n"); + LOGP(DISDN, LOGL_DEBUG, "Message from bridge socket client.\n"); /* different version ? */ if (c->rx_msg.version != SOCKET_VERSION) { - PDEBUG(DISDN, DEBUG_ERROR, "Bridge client uses different version than bridge server. Please update all applications to use same server version\n"); + LOGP(DISDN, LOGL_ERROR, "Bridge client uses different version than bridge server. Please update all applications to use same server version\n"); return 0; } /* process message and reset buffer index */ @@ -325,7 +325,7 @@ static int bridge_socket_conn_cb(struct osmo_fd *ofd, unsigned int when) return 0; } } else if (rc == 0 || errno != EAGAIN) { - PDEBUG(DISDN, DEBUG_DEBUG, "Close from bridge socket client.\n"); + LOGP(DISDN, LOGL_DEBUG, "Close from bridge socket client.\n"); close_server_connection(&c->ofd); /* destroy connection */ free_connection(c); @@ -337,7 +337,7 @@ static int bridge_socket_conn_cb(struct osmo_fd *ofd, unsigned int when) static void sighandler(int sigset) { - PDEBUG(DISDN, DEBUG_DEBUG, "Signal %d received.\n", sigset); + LOGP(DISDN, LOGL_DEBUG, "Signal %d received.\n", sigset); } static int quit = 0; @@ -345,11 +345,11 @@ static int quit = 0; static void server_exit_timeout(void __attribute__((unused)) *data) { if (!conn_list) { - PDEBUG(DISDN, DEBUG_DEBUG, "All clients gone, exitting.\n"); + LOGP(DISDN, LOGL_DEBUG, "All clients gone, exitting.\n"); quit = 1; return; } - timer_start(&server_timer, 0.3); + osmo_timer_schedule(&server_timer, 0,300000); } static void server_show_timeout(void __attribute__((unused)) *data) @@ -362,7 +362,7 @@ static void server_show_timeout(void __attribute__((unused)) *data) printf("Card=%d Port=%d Channel=%d Bridge=%d\n", ch->card, ch->port, ch->channel, ch->pcm_bridge); ch = ch->next; } - timer_start(&server_timer, 1.0); + osmo_timer_schedule(&server_timer, 1,0); } /* open socket, wait for connections and read incoming messages */ @@ -375,10 +375,10 @@ void bridge_socket_server_child(int slots, int daemon) rc = open_server_socket(daemon); if (rc < 0) { if (rc == -EADDRINUSE) - PDEBUG(DISDN, DEBUG_INFO, "Bridging socket is already running by a different instance.\n"); + LOGP(DISDN, LOGL_INFO, "Bridging socket is already running by a different instance.\n"); return; } - PDEBUG(DISDN, DEBUG_DEBUG, "Created bridging socket server.\n"); + LOGP(DISDN, LOGL_DEBUG, "Created bridging socket server.\n"); if (daemon) { signal(SIGINT, sighandler); @@ -388,21 +388,18 @@ void bridge_socket_server_child(int slots, int daemon) } if (daemon) { - timer_init(&server_timer, server_exit_timeout, NULL); - timer_start(&server_timer, 0.3); + osmo_timer_setup(&server_timer, server_exit_timeout, NULL); + osmo_timer_schedule(&server_timer, 0,300000); } else { - timer_init(&server_timer, server_show_timeout, NULL); - timer_start(&server_timer, 1.0); + osmo_timer_setup(&server_timer, server_show_timeout, NULL); + osmo_timer_schedule(&server_timer, 1,0); } while(!quit) { - double timeout; - - timeout = process_timer(); - osmo_fd_select(timeout); + osmo_select_main(0); } - timer_exit(&server_timer); + osmo_timer_del(&server_timer); free_all_channels(); free_all_connections(); @@ -417,14 +414,14 @@ int bridge_socket_server(int slots) pid = fork(); if (pid < 0) { - PDEBUG(DISDN, DEBUG_ERROR, "fork() failed: errno=%d\n", errno); + LOGP(DISDN, LOGL_ERROR, "fork() failed: errno=%d\n", errno); return -EINVAL; } if (pid == 0) { /* child */ pid = fork(); if (pid < 0) { - PDEBUG(DISDN, DEBUG_ERROR, "fork() failed: errno=%d\n", errno); + LOGP(DISDN, LOGL_ERROR, "fork() failed: errno=%d\n", errno); exit(0); } if (pid == 0) { @@ -458,7 +455,7 @@ static void rx_channel_info(int socket, int card, int port, int channel, uint16_ if (c) { /* we are already can bridge */ if (can_bridge) { - PDEBUG(DISDN, DEBUG_DEBUG, "There is no change in bridge, do nothing.\n"); + LOGP(DISDN, LOGL_DEBUG, "There is no change in bridge, do nothing.\n"); return; } /* we must remove bridge, if remote channel exists */ @@ -471,34 +468,34 @@ static void rx_channel_info(int socket, int card, int port, int channel, uint16_ /* remote channel exists, so remove bridge */ if (o) { if (o->pcm_bridge && o->socket > 0) { - PDEBUG(DISDN, DEBUG_DEBUG, "We cannot bridge anymore, remove remote channel's bridge.\n"); + LOGP(DISDN, LOGL_DEBUG, "We cannot bridge anymore, remove remote channel's bridge.\n"); tx_bridge_order(o->socket, o->card, o->port, o->channel, 0, 0, 0, 0, 0); o->pcm_bridge = 0; } } /* now we remove our channel */ if (c->pcm_bridge && c->socket > 0) { - PDEBUG(DISDN, DEBUG_DEBUG, "We cannot bridge anymore, remove our bridge.\n"); + LOGP(DISDN, LOGL_DEBUG, "We cannot bridge anymore, remove our bridge.\n"); tx_bridge_order(c->socket, c->card, c->port, c->channel, 0, 0, 0, 0, 0); c->pcm_bridge = 0; } - PDEBUG(DISDN, DEBUG_DEBUG, "Freeing our channel.\n"); + LOGP(DISDN, LOGL_DEBUG, "Freeing our channel.\n"); free_channel(c); return; } /* if channel does not exists and we cannot bridge, do nothing */ if (!can_bridge) { - PDEBUG(DISDN, DEBUG_DEBUG, "There is no change in bridge, do nothing.\n"); + LOGP(DISDN, LOGL_DEBUG, "There is no change in bridge, do nothing.\n"); return; } /* channel does not exist, so we create it */ /* create connection */ - PDEBUG(DISDN, DEBUG_DEBUG, "Creating our channel.\n"); + LOGP(DISDN, LOGL_DEBUG, "Creating our channel.\n"); c = calloc(1, sizeof(*c)); if (!c) { - PDEBUG(DISDN, DEBUG_ERROR, "No mem!\n"); + LOGP(DISDN, LOGL_ERROR, "No mem!\n"); abort(); } c->next = channel_list; @@ -519,11 +516,11 @@ static void rx_channel_info(int socket, int card, int port, int channel, uint16_ } /* no other channel, so we do not need to send a bridge order */ if (!o) { - PDEBUG(DISDN, DEBUG_DEBUG, "We can bridge, but there is no remote that can bridge (yet)..\n"); + LOGP(DISDN, LOGL_DEBUG, "We can bridge, but there is no remote that can bridge (yet)..\n"); return; } - PDEBUG(DISDN, DEBUG_DEBUG, "We can bridge, and remote can bridge, so we assign time slots.\n"); + LOGP(DISDN, LOGL_DEBUG, "We can bridge, and remote can bridge, so we assign time slots.\n"); /* make a list of allocated time slots */ uint8_t pcm_slot[num_slots]; @@ -558,7 +555,7 @@ static void rx_channel_info(int socket, int card, int port, int channel, uint16_ o->rx_bank = 1; o->tx_bank = 0; } else { - PDEBUG(DISDN, DEBUG_NOTICE, "No single free slots, cannot set bridge.\n"); + LOGP(DISDN, LOGL_NOTICE, "No single free slots, cannot set bridge.\n"); return; } } else { @@ -588,7 +585,7 @@ static void rx_channel_info(int socket, int card, int port, int channel, uint16_ o->rx_bank = 0; o->tx_bank = 0; } else { - PDEBUG(DISDN, DEBUG_NOTICE, "No two free slots, cannot set bridge.\n"); + LOGP(DISDN, LOGL_NOTICE, "No two free slots, cannot set bridge.\n"); return; } } @@ -640,7 +637,7 @@ int bridge_socket_client(isdn_t *isdn_ep) rc = socket(PF_UNIX, SOCK_STREAM, 0); if (rc < 0) { - PDEBUG(DISDN, DEBUG_ERROR, "Failed to create UNIX socket.\n"); + LOGP(DISDN, LOGL_ERROR, "Failed to create UNIX socket.\n"); return rc; } client_ofd.fd = rc; @@ -651,14 +648,14 @@ int bridge_socket_client(isdn_t *isdn_ep) rc = connect(client_ofd.fd, (struct sockaddr *)(&sock_address), sizeof(struct sockaddr_un)); if (rc < 0) { - PDEBUG(DISDN, DEBUG_DEBUG, "Failed to connect to UNIX socket with path '%s' (errno = %d (%s)).\n", SOCKET_NAME, errno, strerror(errno)); + LOGP(DISDN, LOGL_DEBUG, "Failed to connect to UNIX socket with path '%s' (errno = %d (%s)).\n", SOCKET_NAME, errno, strerror(errno)); osmo_fd_unregister(&client_ofd); close(client_ofd.fd); client_ofd.fd = -1; return -errno; } - PDEBUG(DISDN, DEBUG_DEBUG, "Created bridging socket client.\n"); + LOGP(DISDN, LOGL_DEBUG, "Created bridging socket client.\n"); return 0; } @@ -677,10 +674,10 @@ static int bridge_socket_client_cb(struct osmo_fd *ofd, unsigned int when) if (rc > 0) { client_rx_index += rc; if (client_rx_index == sizeof(client_rx_msg)) { - PDEBUG(DISDN, DEBUG_DEBUG, "Message from bridge socket server.\n"); + LOGP(DISDN, LOGL_DEBUG, "Message from bridge socket server.\n"); /* different version ? */ if (client_rx_msg.version != SOCKET_VERSION) { - PDEBUG(DISDN, DEBUG_ERROR, "Bridge server uses different version than bridge client. Please update all applications to use same server version\n"); + LOGP(DISDN, LOGL_ERROR, "Bridge server uses different version than bridge client. Please update all applications to use same server version\n"); return 0; } /* process message and reset buffer index */ @@ -688,7 +685,7 @@ static int bridge_socket_client_cb(struct osmo_fd *ofd, unsigned int when) client_rx_index = 0; } } else if (rc == 0 || errno != EAGAIN) { - PDEBUG(DISDN, DEBUG_DEBUG, "Close from bridge socket client.\n"); + LOGP(DISDN, LOGL_DEBUG, "Close from bridge socket client.\n"); osmo_fd_unregister(&client_ofd); close(client_ofd.fd); client_ofd.fd = -1; @@ -707,7 +704,7 @@ int check_local_address(sa_family_t family, struct sockaddr *addr) rc = getifaddrs(&ifaddr); if (rc < 0) { - PDEBUG(DISDN, DEBUG_ERROR, "Failed to read list of interface addresses.\n"); + LOGP(DISDN, LOGL_ERROR, "Failed to read list of interface addresses.\n"); return 0; } @@ -744,7 +741,7 @@ void rx_bridge_order(isdn_t *isdn_ep, int card, int port, int channel, int pcm_b call_t *call; if (!isdn_ep->bridge_possible || isdn_ep->bridge_cardnum != card || isdn_ep->bridge_portnum != port) { - PDEBUG(DISDN, DEBUG_ERROR, "Client received bridge order that does not match our port/port, please fix!\n"); + LOGP(DISDN, LOGL_ERROR, "Client received bridge order that does not match our port/port, please fix!\n"); } /* hunt for call */ @@ -755,14 +752,14 @@ void rx_bridge_order(isdn_t *isdn_ep, int card, int port, int channel, int pcm_b call = call->next; } if (!call) { - PDEBUG(DISDN, DEBUG_DEBUG, "Client received bridge order that does not belong to an active call, ignoring!\n"); + LOGP(DISDN, LOGL_DEBUG, "Client received bridge order that does not belong to an active call, ignoring!\n"); return; } if (pcm_bridge) - PDEBUG(DISDN, DEBUG_DEBUG, "Client received bridge connect order to connect to PCM slots (%d,%d,%d,%d).\n", rx_slot, tx_slot, rx_bank, tx_bank); + LOGP(DISDN, LOGL_DEBUG, "Client received bridge connect order to connect to PCM slots (%d,%d,%d,%d).\n", rx_slot, tx_slot, rx_bank, tx_bank); else - PDEBUG(DISDN, DEBUG_DEBUG, "Client received bridge disconnect order to disconnect to PCM slots.\n"); + LOGP(DISDN, LOGL_DEBUG, "Client received bridge disconnect order to disconnect to PCM slots.\n"); bchannel_bridge(call, pcm_bridge, rx_slot, tx_slot, rx_bank, tx_bank); } @@ -784,29 +781,29 @@ void bridge_socket_client_update(call_t *call, int enable) if (client_ofd.fd <= 0) return; - PDEBUG(DISDN, DEBUG_INFO, "We got called with enable=%d\n", enable); + LOGP(DISDN, LOGL_INFO, "We got called with enable=%d\n", enable); /* do we have HFC card ? */ if (!call->isdn_ep->bridge_possible && enable) { - PDEBUG(DISDN, DEBUG_INFO, "Our card is not an HFC card, cannot use hardware bridging.\n"); + LOGP(DISDN, LOGL_INFO, "Our card is not an HFC card, cannot use hardware bridging.\n"); return; } if (!call->b_channel) { - PDEBUG(DISDN, DEBUG_DEBUG, "Cannot check bridge, no bchannel currently assigned.\n"); + LOGP(DISDN, LOGL_DEBUG, "Cannot check bridge, no bchannel currently assigned.\n"); return; } /* check if essential structures are set */ if (!call->cc_session || !call->cc_session->media_list) { - PDEBUG(DISDN, DEBUG_DEBUG, "Codec/media not set, not ready for bridging.\n"); + LOGP(DISDN, LOGL_DEBUG, "Codec/media not set, not ready for bridging.\n"); return; } media = call->cc_session->media_list; /* check if codec negotiation is complete */ if (!media->description.port_local || (call->direction == DIRECTION_TERMINATOR && !media->description.port_remote)) { - PDEBUG(DISDN, DEBUG_DEBUG, "Codec negotiation is not complete, cannot bridge yet.\n"); + LOGP(DISDN, LOGL_DEBUG, "Codec negotiation is not complete, cannot bridge yet.\n"); return; } @@ -820,7 +817,7 @@ void bridge_socket_client_update(call_t *call, int enable) sa4->sin_family = family; rc = inet_pton(AF_INET, media->connection_data_remote.address, &sa4->sin_addr); if (rc < 1) { - PDEBUG(DISDN, DEBUG_ERROR, "inet_pton failed, please fix!\n"); + LOGP(DISDN, LOGL_ERROR, "inet_pton failed, please fix!\n"); return; } break; @@ -831,26 +828,26 @@ void bridge_socket_client_update(call_t *call, int enable) sa6->sin6_family = family; rc = inet_pton(AF_INET6, media->connection_data_remote.address, &sa6->sin6_addr); if (rc < 1) { - PDEBUG(DISDN, DEBUG_ERROR, "inet_pton failed, please fix!\n"); + LOGP(DISDN, LOGL_ERROR, "inet_pton failed, please fix!\n"); return; } break; case osmo_cc_session_addrtype_unknown: - PDEBUG(DISDN, DEBUG_DEBUG, "Unsupported address type '%s'.\n", media->connection_data_remote.addrtype_name); + LOGP(DISDN, LOGL_DEBUG, "Unsupported address type '%s'.\n", media->connection_data_remote.addrtype_name); return; } rc = check_local_address(family, (struct sockaddr *)&sa); if (rc < 1) { - PDEBUG(DISDN, DEBUG_DEBUG, "Remote RTP peer is not on this machine, cannot use hardware bridging.\n"); + LOGP(DISDN, LOGL_DEBUG, "Remote RTP peer is not on this machine, cannot use hardware bridging.\n"); return; } } else { - PDEBUG(DISDN, DEBUG_DEBUG, "We are originator, we may use hardware bridging.\n"); + LOGP(DISDN, LOGL_DEBUG, "We are originator, we may use hardware bridging.\n"); } /* check if 3PTY */ if (call->conference_3pty) { - PDEBUG(DISDN, DEBUG_DEBUG, "Whe have 3PTY conference, cannot bridge while this is going on.\n"); + LOGP(DISDN, LOGL_DEBUG, "Whe have 3PTY conference, cannot bridge while this is going on.\n"); goto send; } @@ -859,10 +856,10 @@ void bridge_socket_client_update(call_t *call, int enable) send: /* only send on change */ if (can_bridge && !call->can_bridge) { - PDEBUG(DISDN, DEBUG_INFO, "We tell the server we can do hardware bridging.\n"); + LOGP(DISDN, LOGL_INFO, "We tell the server we can do hardware bridging.\n"); } else if (!can_bridge && call->can_bridge) { - PDEBUG(DISDN, DEBUG_INFO, "We tell the server we cannot do hardware bridging anymore.\n"); + LOGP(DISDN, LOGL_INFO, "We tell the server we cannot do hardware bridging anymore.\n"); } else return; call->can_bridge = can_bridge; diff --git a/src/isdn/dss1.c b/src/isdn/dss1.c index d575df1..51517e5 100644 --- a/src/isdn/dss1.c +++ b/src/isdn/dss1.c @@ -25,8 +25,8 @@ #include #include #include -#include "../libdebug/debug.h" -#include "../libg711/g711.h" +#include "../liblogging/logging.h" +#include #include "isdn.h" #include "dss1.h" #include "bridge.h" @@ -75,7 +75,7 @@ static struct l3_msg *create_l3msg(void) l3m = alloc_l3_msg(); if (!l3m) { - PDEBUG(DDSS1, DEBUG_ERROR, "No MEM!\n"); + LOGP(DDSS1, LOGL_ERROR, "No MEM!\n"); abort(); } return l3m; @@ -109,7 +109,7 @@ static void new_state(call_t *call, enum isdn_state state) { if (call->state == state) return; - PDEBUG(DDSS1, DEBUG_DEBUG, "Changing state %s -> %s\n", state_names[call->state], state_names[state]); + LOGP(DDSS1, LOGL_DEBUG, "Changing state %s -> %s\n", state_names[call->state], state_names[state]); call->state = state; } @@ -134,7 +134,7 @@ static void release_and_destroy(call_t *call, uint8_t cc_isdn_cause, uint16_t cc } if (isdn_cause) { - PDEBUG(DDSS1, DEBUG_INFO, "REJECT REQUEST (pid = 0x%x callref = %d)\n", call->l3_pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "REJECT REQUEST (pid = 0x%x callref = %d)\n", call->l3_pid, call->cc_callref); /* creating release complete */ l3m = create_l3msg(); @@ -206,10 +206,10 @@ void setup_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) struct osmo_cc_helper_audio_codecs *codecs; int clearmode = 0; - PDEBUG(DDSS1, DEBUG_INFO, "SETUP INDICATION (pid = 0x%x)\n", pid); + LOGP(DDSS1, LOGL_INFO, "SETUP INDICATION (pid = 0x%x)\n", pid); /* assign pid */ - PDEBUG(DDSS1, DEBUG_DEBUG, " -> new L3ID assigned (l3id = 0x%x)\n", pid); + LOGP(DDSS1, LOGL_DEBUG, " -> new L3ID assigned (l3id = 0x%x)\n", pid); call->l3_pid = pid; call->l3_ces = pid >> 16; @@ -332,7 +332,7 @@ void setup_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) no_channel: osmo_cc_free_msg(msg); /* send MT_RELEASE_COMPLETE to "REJECT" the channel */ - PDEBUG(DDSS1, DEBUG_INFO, "RELEASE-COMPLETE REQUEST (pid = 0x%x)\n", pid); + LOGP(DDSS1, LOGL_INFO, "RELEASE-COMPLETE REQUEST (pid = 0x%x)\n", pid); l3m = create_l3msg(); enc_ie_cause(l3m, call->isdn_ep->serving_location, -rc); call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_RELEASE_COMPLETE, call->l3_pid, l3m); @@ -352,7 +352,7 @@ void setup_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) /* create endpoint */ osmo_cc_call_t *cc_call = osmo_cc_call_new(&call->isdn_ep->cc_ep); call->cc_callref = cc_call->callref; - PDEBUG(DDSS1, DEBUG_DEBUG, " -> new callref assigned (callref = %d)\n", call->cc_callref); + LOGP(DDSS1, LOGL_DEBUG, " -> new callref assigned (callref = %d)\n", call->cc_callref); new_state(call, ISDN_STATE_IN_SETUP); @@ -369,7 +369,7 @@ void setup_ack_ind(call_t *call, uint32_t cmd, uint32_t pid, struct l3_msg *l3m) char display[128]; int rc; - PDEBUG(DDSS1, DEBUG_INFO, "SETUP-ACKNOWLEDGE INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "SETUP-ACKNOWLEDGE INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* create osmo-cc message */ msg = osmo_cc_new_msg(OSMO_CC_MSG_SETUP_ACK_IND); @@ -392,7 +392,7 @@ void setup_ack_ind(call_t *call, uint32_t cmd, uint32_t pid, struct l3_msg *l3m) rc = dec_ie_channel_id(l3m, call->isdn_ep->pri, &exclusive, &channel); rc = open_bchannel_out(call, cmd, (rc < 0) ? -1 : channel, (rc < 0) ? -1 : exclusive); if (rc < 0) { - PDEBUG(DDSS1, DEBUG_NOTICE, "Channel negotiation failed.\n"); + LOGP(DDSS1, LOGL_NOTICE, "Channel negotiation failed.\n"); osmo_cc_free_msg(msg); release_and_destroy(call, OSMO_CC_ISDN_CAUSE_RESOURCE_UNAVAIL, 0, -rc); return; @@ -431,7 +431,7 @@ void proc_ind(call_t *call, uint32_t cmd, uint32_t pid, struct l3_msg *l3m) char display[128]; int rc; - PDEBUG(DDSS1, DEBUG_INFO, "PREOCEEDING INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "PREOCEEDING INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* create osmo-cc message */ msg = osmo_cc_new_msg(OSMO_CC_MSG_PROC_IND); @@ -467,7 +467,7 @@ void proc_ind(call_t *call, uint32_t cmd, uint32_t pid, struct l3_msg *l3m) rc = dec_ie_channel_id(l3m, call->isdn_ep->pri, &exclusive, &channel); rc = open_bchannel_out(call, cmd, (rc < 0) ? -1 : channel, (rc < 0) ? -1 : exclusive); if (rc < 0) { - PDEBUG(DDSS1, DEBUG_NOTICE, "Channel negotiation failed.\n"); + LOGP(DDSS1, LOGL_NOTICE, "Channel negotiation failed.\n"); osmo_cc_free_msg(msg); release_and_destroy(call, OSMO_CC_ISDN_CAUSE_RESOURCE_UNAVAIL, 0, -rc); return; @@ -506,7 +506,7 @@ void alert_ind(call_t *call, uint32_t cmd, uint32_t pid, struct l3_msg *l3m) char display[128]; int rc; - PDEBUG(DDSS1, DEBUG_INFO, "ALERTING INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "ALERTING INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* create osmo-cc message */ msg = osmo_cc_new_msg(OSMO_CC_MSG_ALERT_IND); @@ -542,7 +542,7 @@ void alert_ind(call_t *call, uint32_t cmd, uint32_t pid, struct l3_msg *l3m) rc = dec_ie_channel_id(l3m, call->isdn_ep->pri, &exclusive, &channel); rc = open_bchannel_out(call, cmd, (rc < 0) ? -1 : channel, (rc < 0) ? -1 : exclusive); if (rc < 0) { - PDEBUG(DDSS1, DEBUG_NOTICE, "Channel negotiation failed.\n"); + LOGP(DDSS1, LOGL_NOTICE, "Channel negotiation failed.\n"); osmo_cc_free_msg(msg); release_and_destroy(call, OSMO_CC_ISDN_CAUSE_RESOURCE_UNAVAIL, 0, -rc); return; @@ -581,7 +581,7 @@ void setup_cnf(call_t *call, uint32_t cmd, uint32_t pid, struct l3_msg *l3m) char display[128]; int rc; - PDEBUG(DDSS1, DEBUG_INFO, "CONNECT INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "CONNECT INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* create osmo-cc message */ msg = osmo_cc_new_msg(OSMO_CC_MSG_SETUP_CNF); @@ -626,7 +626,7 @@ void setup_cnf(call_t *call, uint32_t cmd, uint32_t pid, struct l3_msg *l3m) /* complete channel negotiation */ rc = open_bchannel_out(call, cmd, channel, exclusive); /* channel and exclusive may be -1 */ if (rc < 0) { - PDEBUG(DDSS1, DEBUG_NOTICE, "Channel negotiation failed.\n"); + LOGP(DDSS1, LOGL_NOTICE, "Channel negotiation failed.\n"); osmo_cc_free_msg(msg); release_and_destroy(call, OSMO_CC_ISDN_CAUSE_RESOURCE_UNAVAIL, 0, -rc); return; @@ -659,7 +659,7 @@ void setup_comp_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) char display[128]; int rc; - PDEBUG(DDSS1, DEBUG_INFO, "CONNECT-ACKNOWLEDGE INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "CONNECT-ACKNOWLEDGE INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* only send in TE mode, because we automatically reply in NT mode */ if (call->isdn_ep->ntmode) @@ -690,7 +690,7 @@ void info_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) char display[128]; int rc; - PDEBUG(DDSS1, DEBUG_INFO, "INFO INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "INFO INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* create osmo-cc message */ msg = osmo_cc_new_msg(OSMO_CC_MSG_INFO_IND); @@ -725,7 +725,7 @@ void info_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) /* stop tone, if something has been dialled */ if (call->send_local_tones && call->any_dialing && call->state == ISDN_STATE_IN_OVERLAP) { - PDEBUG(DDSS1, DEBUG_DEBUG, "Stop sending locally generated dial tone. (if not already)\n"); + LOGP(DDSS1, LOGL_DEBUG, "Stop sending locally generated dial tone. (if not already)\n"); bchannel_tone(call, 0); } @@ -741,7 +741,7 @@ void disconnect_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) char display[128]; int rc; - PDEBUG(DDSS1, DEBUG_INFO, "DISCONNECT INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "DISCONNECT INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* create osmo-cc message */ msg = osmo_cc_new_msg(OSMO_CC_MSG_DISC_IND); @@ -774,7 +774,7 @@ void disconnect_ind_i(call_t *call, uint32_t pid, struct l3_msg *l3m) uint8_t location, cause; int rc; - PDEBUG(DDSS1, DEBUG_INFO, "DISCONNECT INDICATION of child (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "DISCONNECT INDICATION of child (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* collect cause */ rc = dec_ie_cause(l3m, &location, &cause); @@ -792,7 +792,7 @@ void release_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) char display[128]; int rc; - PDEBUG(DDSS1, DEBUG_INFO, "RELEASE INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "RELEASE INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* create osmo-cc message */ msg = osmo_cc_new_msg(OSMO_CC_MSG_REL_IND); @@ -825,7 +825,7 @@ void release_complete_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) uint8_t location, cause; int rc; - PDEBUG(DDSS1, DEBUG_INFO, "RELEASE-COMPLETE INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "RELEASE-COMPLETE INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* create osmo-cc message */ switch (call->state) { @@ -865,7 +865,7 @@ void release_complete_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) /* CC-RESTART INDICATION */ void restart_ind(uint32_t pid) { - PDEBUG(DDSS1, DEBUG_INFO, "RESTART INDICATION (pid = 0x%x)\n", pid); + LOGP(DDSS1, LOGL_INFO, "RESTART INDICATION (pid = 0x%x)\n", pid); // L3 process is not touched. (not even by network stack) } @@ -886,7 +886,7 @@ void notify_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) char display[128]; int rc; - PDEBUG(DDSS1, DEBUG_INFO, "NOTIFY INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "NOTIFY INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* create osmo-cc message */ msg = osmo_cc_new_msg(OSMO_CC_MSG_NOTIFY_IND); @@ -923,11 +923,11 @@ void hold_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) { osmo_cc_msg_t *msg; - PDEBUG(DDSS1, DEBUG_INFO, "HOLD INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "HOLD INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* reject, if we are on hold */ if (call->hold) { - PDEBUG(DDSS1, DEBUG_INFO, "HOLD-REJECT REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "HOLD-REJECT REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); l3m = create_l3msg(); enc_ie_cause(l3m, call->isdn_ep->serving_location, call->hold?101:31); /* normal unspecified / incompatible state */ call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_HOLD_REJECT, call->l3_pid, l3m); @@ -959,7 +959,7 @@ void hold_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) enable_hold_clock(call->isdn_ep); /* acknowledge hold */ - PDEBUG(DDSS1, DEBUG_INFO, "HOLD-ACKNOWLEDGE REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "HOLD-ACKNOWLEDGE REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); l3m = create_l3msg(); call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_HOLD_ACKNOWLEDGE, call->l3_pid, l3m); } @@ -972,13 +972,13 @@ void retrieve_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) int channel, exclusive; int rc; - PDEBUG(DDSS1, DEBUG_INFO, "RETRIEVE INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "RETRIEVE INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); if (!call->hold) { rc = -101; /* incompatible state */ no_channel: /* reject retrieve */ - PDEBUG(DDSS1, DEBUG_INFO, "RETRIEVE-REJECT REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "RETRIEVE-REJECT REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); l3m = create_l3msg(); enc_ie_cause(l3m, call->isdn_ep->serving_location, rc); call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_RETRIEVE_REJECT, call->l3_pid, l3m); @@ -1015,7 +1015,7 @@ void retrieve_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) jitter_reset(&call->tx_dejitter); /* acknowledge retrieve */ - PDEBUG(DDSS1, DEBUG_INFO, "RETRIEVE-ACKNOWLEDGE REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "RETRIEVE-ACKNOWLEDGE REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); l3m = create_l3msg(); enc_ie_channel_id(l3m, call->isdn_ep->pri, 1, call->b_channel); call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_RETRIEVE_ACKNOWLEDGE, call->l3_pid, l3m); @@ -1030,11 +1030,11 @@ void suspend_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) int rc = -31; /* normal, unspecified */ call_t *check; - PDEBUG(DDSS1, DEBUG_INFO, "SUSPEND INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "SUSPEND INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); if (0) { reject: - PDEBUG(DDSS1, DEBUG_INFO, "SUSPEND-REJECT REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "SUSPEND-REJECT REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); l3m = create_l3msg(); enc_ie_cause(l3m, call->isdn_ep->serving_location, -rc); call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_SUSPEND_REJECT, call->l3_pid, l3m); @@ -1052,7 +1052,7 @@ void suspend_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) if (check->state == ISDN_STATE_SUSPENDED && check->park_len == len && !memcmp(check->park_callid, callid, len)) { - PDEBUG(DDSS1, DEBUG_INFO, "Given Park ID is already in use, rejecting!\n"); + LOGP(DDSS1, LOGL_INFO, "Given Park ID is already in use, rejecting!\n"); rc = -84; /* call id in use */ goto reject; } @@ -1085,7 +1085,7 @@ void suspend_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) enable_hold_clock(call->isdn_ep); /* sending SUSPEND_ACKNOWLEDGE */ - PDEBUG(DDSS1, DEBUG_INFO, "SUSPEND-ACKNOWLEDGE REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "SUSPEND-ACKNOWLEDGE REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); l3m = create_l3msg(); call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_SUSPEND_ACKNOWLEDGE, call->l3_pid, l3m); } @@ -1100,7 +1100,7 @@ void resume_ind(isdn_t *isdn_ep, uint32_t pid, struct l3_msg *l3m) int channel, exclusive; int rc; - PDEBUG(DDSS1, DEBUG_INFO, "RESUME INDICATION (pid = 0x%x)\n", pid); + LOGP(DDSS1, LOGL_INFO, "RESUME INDICATION (pid = 0x%x)\n", pid); /* call id */ rc = dec_ie_call_id(l3m, callid, &len); @@ -1119,10 +1119,10 @@ void resume_ind(isdn_t *isdn_ep, uint32_t pid, struct l3_msg *l3m) /* process given callref */ if (!call) { - PDEBUG(DDSS1, DEBUG_NOTICE, "No parked call found with given park ID, rejecting.\n"); + LOGP(DDSS1, LOGL_NOTICE, "No parked call found with given park ID, rejecting.\n"); rc = -85; no_channel: - PDEBUG(DDSS1, DEBUG_INFO, "RESUME-REJECT REQUEST (pid = 0x%x)\n", pid); + LOGP(DDSS1, LOGL_INFO, "RESUME-REJECT REQUEST (pid = 0x%x)\n", pid); l3m = create_l3msg(); enc_ie_cause(l3m, isdn_ep->serving_location, -rc); isdn_ep->ml3->to_layer3(isdn_ep->ml3, MT_RESUME_REJECT, pid, l3m); @@ -1130,7 +1130,7 @@ void resume_ind(isdn_t *isdn_ep, uint32_t pid, struct l3_msg *l3m) } /* assign pid */ - PDEBUG(DDSS1, DEBUG_DEBUG, "new L3ID assigned (l3id = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_DEBUG, "new L3ID assigned (l3id = 0x%x callref = %d)\n", pid, call->cc_callref); call->l3_pid = pid; call->l3_ces = pid >> 16; @@ -1166,7 +1166,7 @@ void resume_ind(isdn_t *isdn_ep, uint32_t pid, struct l3_msg *l3m) osmo_cc_ll_msg(&call->isdn_ep->cc_ep, call->cc_callref, msg); /* sending RESUME_ACKNOWLEDGE */ - PDEBUG(DDSS1, DEBUG_INFO, "RESUME-ACKNOWLEDGE REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "RESUME-ACKNOWLEDGE REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); l3m = create_l3msg(); enc_ie_channel_id(l3m, call->isdn_ep->pri, 1, call->b_channel); call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_RESUME_ACKNOWLEDGE, call->l3_pid, l3m); @@ -1185,7 +1185,7 @@ void facility_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) call_t *other; int rc; - PDEBUG(DDSS1, DEBUG_INFO, "FACILITY INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "FACILITY INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* facility */ rc = dec_ie_facility(l3m, fac_ie + 1, &fac_len); @@ -1243,7 +1243,7 @@ void facility_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) jitter_reset(&other->conf_dejitter); jitter_reset(&other->tx_dejitter); } else { - PDEBUG(DDSS1, DEBUG_NOTICE, "Phone requests conference, but no call on hold!\n"); + LOGP(DDSS1, LOGL_NOTICE, "Phone requests conference, but no call on hold!\n"); notify = 0; } @@ -1295,7 +1295,7 @@ void progress_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) uint8_t coding, location, progress; int rc; - PDEBUG(DDSS1, DEBUG_INFO, "PROGRESS INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "PROGRESS INDICATION (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* create osmo-cc message */ msg = osmo_cc_new_msg(OSMO_CC_MSG_PROGRESS_IND); @@ -1333,7 +1333,7 @@ void mt_free(call_t *call) { osmo_cc_msg_t *msg; - PDEBUG(DDSS1, DEBUG_DEBUG, "Got MT_FREE (release from stack) (old pid 0x%x)\n", call->l3_pid); + LOGP(DDSS1, LOGL_DEBUG, "Got MT_FREE (release from stack) (old pid 0x%x)\n", call->l3_pid); /* create osmo-cc message */ switch (call->state) { @@ -1365,17 +1365,17 @@ void dss1_message(isdn_t *isdn_ep, call_t *call, uint32_t cmd, uint32_t pid, str switch (cmd) { case MT_TIMEOUT: if (!l3m->cause) { - PDEBUG(DDSS1, DEBUG_ERROR, "timeout without cause.\n"); + LOGP(DDSS1, LOGL_ERROR, "timeout without cause.\n"); break; } if (l3m->cause[0] != 5) { - PDEBUG(DDSS1, DEBUG_ERROR, "expecting timeout with timer diagnostic. (got len=%d)\n", l3m->cause[0]); + LOGP(DDSS1, LOGL_ERROR, "expecting timeout with timer diagnostic. (got len=%d)\n", l3m->cause[0]); break; } timer = (l3m->cause[3]-'0')*100; timer += (l3m->cause[4]-'0')*10; timer += (l3m->cause[5]-'0'); - PDEBUG(DDSS1, DEBUG_DEBUG, "isdn timer T%d timeout\n", timer); + LOGP(DDSS1, LOGL_DEBUG, "isdn timer T%d timeout\n", timer); if (timer == 312) t312_timeout_ind(); break; @@ -1459,7 +1459,7 @@ void dss1_message(isdn_t *isdn_ep, call_t *call, uint32_t cmd, uint32_t pid, str break; default: - PDEBUG(DDSS1, DEBUG_ERROR, "unhandled message: cmd(0x%x) pid(0x%x)\n", cmd, pid); + LOGP(DDSS1, LOGL_ERROR, "unhandled message: cmd(0x%x) pid(0x%x)\n", cmd, pid); } } @@ -1468,7 +1468,7 @@ int dss1_receive(isdn_t *isdn_ep, uint32_t cmd, uint32_t pid, struct l3_msg *l3m { call_t *call; - PDEBUG(DDSS1, DEBUG_DEBUG, "message from L3 stack: cmd(0x%x) pid(0x%x)\n", cmd, pid); + LOGP(DDSS1, LOGL_DEBUG, "message from L3 stack: cmd(0x%x) pid(0x%x)\n", cmd, pid); /* find call that is associated with the pid */ call = isdn_ep->call_list; @@ -1491,9 +1491,9 @@ int dss1_receive(isdn_t *isdn_ep, uint32_t cmd, uint32_t pid, struct l3_msg *l3m if (call) { /* after answering the phone, the PID will be completed and CES will be assigned */ if (cmd == MT_ASSIGN) { - PDEBUG(DDSS1, DEBUG_DEBUG, "Got assignment (old pid 0x%x, new pid 0x%x)\n", call->l3_pid, pid); + LOGP(DDSS1, LOGL_DEBUG, "Got assignment (old pid 0x%x, new pid 0x%x)\n", call->l3_pid, pid); if ((call->l3_pid & MISDN_PID_CRTYPE_MASK) != MISDN_PID_MASTER) - PDEBUG(DDSS1, DEBUG_ERROR, "strange setup-procid 0x%x\n", call->l3_pid); + LOGP(DDSS1, LOGL_ERROR, "strange setup-procid 0x%x\n", call->l3_pid); call->l3_pid = pid; if (call->state == ISDN_STATE_OUT_CONNECTING || call->state == ISDN_STATE_CONNECT) call->l3_ces = pid >> 16; @@ -1528,7 +1528,7 @@ int dss1_receive(isdn_t *isdn_ep, uint32_t cmd, uint32_t pid, struct l3_msg *l3m /* creating call instance, transparent until setup with hdlc */ call = call_create(isdn_ep, DIRECTION_ORIGINATOR, 0, 0, B_MODE_TRANSPARENT); if (!call) { - PDEBUG(DDSS1, DEBUG_ERROR, "Cannot create call instance.\n"); + LOGP(DDSS1, LOGL_ERROR, "Cannot create call instance.\n"); abort(); } dss1_message(isdn_ep, call, cmd, pid, l3m); @@ -1540,11 +1540,11 @@ int dss1_receive(isdn_t *isdn_ep, uint32_t cmd, uint32_t pid, struct l3_msg *l3m break; case MT_FREE: - PDEBUG(DDSS1, DEBUG_DEBUG, "unused L3ID released (pid = 0x%x, call->cc_callref)\n", pid); + LOGP(DDSS1, LOGL_DEBUG, "unused L3ID released (pid = 0x%x, call->cc_callref)\n", pid); break; case MT_RELEASE_COMPLETE: - PDEBUG(DDSS1, DEBUG_ERROR, "MT_RELEASE_COMPLETE must be ignored by stack, not sent to app\n"); + LOGP(DDSS1, LOGL_ERROR, "MT_RELEASE_COMPLETE must be ignored by stack, not sent to app\n"); break; case MT_FACILITY: @@ -1553,11 +1553,11 @@ int dss1_receive(isdn_t *isdn_ep, uint32_t cmd, uint32_t pid, struct l3_msg *l3m case MT_L2IDLE: // L2 became idle - we could sent a MT_L2RELEASE if we are the L2 master - PDEBUG(DDSS1, DEBUG_DEBUG, "Got L2 idle\n"); + LOGP(DDSS1, LOGL_DEBUG, "Got L2 idle\n"); break; default: - PDEBUG(DDSS1, DEBUG_ERROR, "unhandled message: cmd(0x%x) pid(0x%x)\n", cmd, pid); + LOGP(DDSS1, LOGL_ERROR, "unhandled message: cmd(0x%x) pid(0x%x)\n", cmd, pid); return -EINVAL; } @@ -1586,7 +1586,7 @@ void setup_req(call_t *call, osmo_cc_msg_t *msg) int rc; struct osmo_cc_helper_audio_codecs *codecs; - PDEBUG(DDSS1, DEBUG_INFO, "SETUP REQUEST\n"); + LOGP(DDSS1, LOGL_INFO, "SETUP REQUEST\n"); /* select codec */ if (call->isdn_ep->law == 'a') @@ -1601,12 +1601,12 @@ void setup_req(call_t *call, osmo_cc_msg_t *msg) return; } call->sdp = strdup(sdp); - PDEBUG(DDSS1, DEBUG_INFO, "Codec %s selected for transmission.\n", call->codec->payload_name); + LOGP(DDSS1, LOGL_INFO, "Codec %s selected for transmission.\n", call->codec->payload_name); /* get channel */ rc = hunt_bchannel_out(call->isdn_ep, &channel, &exclusive); if (rc < 0) { - PDEBUG(DDSS1, DEBUG_NOTICE, "There is no channel available on the interface.\n"); + LOGP(DDSS1, LOGL_NOTICE, "There is no channel available on the interface.\n"); release_and_destroy(call, -rc, 0, 0); return; } @@ -1617,11 +1617,11 @@ void setup_req(call_t *call, osmo_cc_msg_t *msg) /* creating pid */ call->l3_pid = request_new_pid(call->isdn_ep->ml3); if (call->l3_pid == MISDN_PID_NONE) { - PDEBUG(DDSS1, DEBUG_NOTICE, "There is no free L3ID on the mISDN stack, please restart!\n"); + LOGP(DDSS1, LOGL_NOTICE, "There is no free L3ID on the mISDN stack, please restart!\n"); release_and_destroy(call, OSMO_CC_ISDN_CAUSE_RESOURCE_UNAVAIL, 0, 0); return; } - PDEBUG(DDSS1, DEBUG_DEBUG, "new L3ID assigned (pid = 0x%x)\n", call->l3_pid); + LOGP(DDSS1, LOGL_DEBUG, "new L3ID assigned (pid = 0x%x)\n", call->l3_pid); /* creating setup */ l3m = create_l3msg(); @@ -1629,7 +1629,7 @@ void setup_req(call_t *call, osmo_cc_msg_t *msg) /* bearer capability */ rc = osmo_cc_get_ie_bearer(msg, 0, &coding, &capability, &mode); if (rc < 0) { - PDEBUG(DDSS1, DEBUG_DEBUG, "No bearer capability given, generating from selected codec.\n"); + LOGP(DDSS1, LOGL_DEBUG, "No bearer capability given, generating from selected codec.\n"); coding = OSMO_CC_CODING_ITU_T; if (!strcmp(call->codec->payload_name, "CLEARMODE")) { capability = OSMO_CC_CAPABILITY_DATA; @@ -1639,7 +1639,7 @@ void setup_req(call_t *call, osmo_cc_msg_t *msg) mode = OSMO_CC_MODE_CIRCUIT; } } else - PDEBUG(DDSS1, DEBUG_DEBUG, "Bearer capability given, override what is defined by selected codec.\n"); + LOGP(DDSS1, LOGL_DEBUG, "Bearer capability given, override what is defined by selected codec.\n"); rate = (mode == OSMO_CC_MODE_PACKET) ? 0x00 : 0x10; if (capability == OSMO_CC_CAPABILITY_AUDIO || capability == OSMO_CC_CAPABILITY_SPEECH) { has_user = 1; @@ -1760,18 +1760,18 @@ int process_progress(call_t *call, osmo_cc_msg_t *msg, struct l3_msg *l3m, int c if (coding == OSMO_CC_CODING_ITU_T && (progress == 1 || progress == 8)) { /* if we are sending local tones, we stop them */ if (call->send_local_tones) { - PDEBUG(DDSS1, DEBUG_DEBUG, "Stop sending locally generated tones.\n"); + LOGP(DDSS1, LOGL_DEBUG, "Stop sending locally generated tones.\n"); call->send_local_tones = 0; bchannel_tone(call, 0); } - PDEBUG(DDSS1, DEBUG_DEBUG, "Using remote tones.\n"); + LOGP(DDSS1, LOGL_DEBUG, "Using remote tones.\n"); call->send_remote_tones = 1; goto finish; } /* if we have local tones the first time, send progress indicator */ if (!call->send_local_tones) { - PDEBUG(DDSS1, DEBUG_DEBUG, "Start sending locally generated tones.\n"); + LOGP(DDSS1, LOGL_DEBUG, "Start sending locally generated tones.\n"); call->send_local_tones = 1; coding = OSMO_CC_CODING_ITU_T; location = call->isdn_ep->serving_location; @@ -1899,7 +1899,7 @@ void setup_ack_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg) return; } - PDEBUG(DDSS1, DEBUG_INFO, "SETUP-ACKNOWLEDGE REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "SETUP-ACKNOWLEDGE REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* creating setup acknowledge */ l3m = create_l3msg(); @@ -1943,7 +1943,7 @@ void proc_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg, int with_ies) return; call->proceeding_sent = 1; - PDEBUG(DDSS1, DEBUG_INFO, "PROCEEDING REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "PROCEEDING REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* creating proceeding */ l3m = create_l3msg(); @@ -2003,7 +2003,7 @@ void alert_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg) proc_req(call, pid, msg, 0); } - PDEBUG(DDSS1, DEBUG_INFO, "ALERTING REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "ALERTING REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* creating alerting */ l3m = create_l3msg(); @@ -2060,11 +2060,11 @@ void setup_rsp(call_t *call, uint32_t pid, osmo_cc_msg_t *msg) proc_req(call, pid, msg, 0); } - PDEBUG(DDSS1, DEBUG_INFO, "CONNECT REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "CONNECT REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* stop local tones, if sending until now */ if (call->send_local_tones) { - PDEBUG(DDSS1, DEBUG_INFO, "Stop sending locally generated tones.\n"); + LOGP(DDSS1, LOGL_INFO, "Stop sending locally generated tones.\n"); call->send_local_tones = 0; bchannel_tone(call, 0); } @@ -2136,7 +2136,7 @@ void setup_comp_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg) char display[128]; int rc; - PDEBUG(DDSS1, DEBUG_INFO, "CONNECT ACKNOWLEDGE REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "CONNECT ACKNOWLEDGE REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); new_state(call, ISDN_STATE_CONNECT); @@ -2172,7 +2172,7 @@ void info_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg) char dialing[33]; int rc_called, rc_kp; - PDEBUG(DDSS1, DEBUG_INFO, "INFORMATION REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "INFORMATION REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* keypad */ rc_kp = osmo_cc_get_ie_keypad(msg, 0, keypad, sizeof(keypad)); @@ -2201,7 +2201,7 @@ void progress_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg) struct l3_msg *l3m; int rc; - PDEBUG(DDSS1, DEBUG_INFO, "PROGRESS REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "PROGRESS REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* creating progress */ l3m = create_l3msg(); @@ -2226,7 +2226,7 @@ void notify_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg) char display[128]; int rc_notify, rc_redir, rc_display; - PDEBUG(DDSS1, DEBUG_INFO, "NOTIFY REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "NOTIFY REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* notify */ rc_notify = osmo_cc_get_ie_notify(msg, 0, ¬ify); @@ -2250,7 +2250,7 @@ void notify_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg) /* send message to ISDN */ call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_NOTIFY, call->l3_pid, l3m); } else { - PDEBUG(DDSS1, DEBUG_ERROR, "NOTIFY REQUEST without notification indicator, ignoring.\n"); + LOGP(DDSS1, LOGL_ERROR, "NOTIFY REQUEST without notification indicator, ignoring.\n"); } } @@ -2263,7 +2263,7 @@ void rej_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg) char display[128]; int rc; - PDEBUG(DDSS1, DEBUG_INFO, "REJECT REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "REJECT REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* creating release complete */ l3m = create_l3msg(); @@ -2306,7 +2306,7 @@ void disc_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg) proc_req(call, pid, msg, 0); } - PDEBUG(DDSS1, DEBUG_INFO, "DISCONNECT REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "DISCONNECT REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* creating disconnect */ l3m = create_l3msg(); @@ -2321,7 +2321,7 @@ void disc_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg) /* reset states and handle progress information */ if (call->send_local_tones) { - PDEBUG(DDSS1, DEBUG_DEBUG, "Stop sending locally generated tones.\n"); + LOGP(DDSS1, LOGL_DEBUG, "Stop sending locally generated tones.\n"); call->send_local_tones = 0; bchannel_tone(call, 0); } @@ -2352,7 +2352,7 @@ void rel_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg) char display[128]; int rc; - PDEBUG(DDSS1, DEBUG_INFO, "RELEASE REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); + LOGP(DDSS1, LOGL_INFO, "RELEASE REQUEST (pid = 0x%x callref = %d)\n", pid, call->cc_callref); /* creating release */ l3m = create_l3msg(); @@ -2419,14 +2419,14 @@ void cc_message(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg) /* process SETUP */ if (!call) { if (msg->type != OSMO_CC_MSG_SETUP_REQ) { - PDEBUG(DDSS1, DEBUG_ERROR, "received message without call instance, please fix!\n"); + LOGP(DDSS1, LOGL_ERROR, "received message without call instance, please fix!\n"); osmo_cc_free_msg(msg); return; } /* creating call instance, transparent until setup with hdlc */ call = call_create(isdn_ep, DIRECTION_TERMINATOR, 0, 0, B_MODE_TRANSPARENT); if (!call) { - PDEBUG(DDSS1, DEBUG_ERROR, "Cannot create call instance.\n"); + LOGP(DDSS1, LOGL_ERROR, "Cannot create call instance.\n"); abort(); } /* link with cc */ @@ -2540,7 +2540,7 @@ void cc_message(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg) rel_req(call, call->l3_pid, msg); break; default: - PDEBUG(DDSS1, DEBUG_ERROR, "received an unsupported CC message: %d\n", msg->type); + LOGP(DDSS1, LOGL_ERROR, "received an unsupported CC message: %d\n", msg->type); } osmo_cc_free_msg(msg); diff --git a/src/isdn/ie.c b/src/isdn/ie.c index a79571c..dd30674 100644 --- a/src/isdn/ie.c +++ b/src/isdn/ie.c @@ -13,7 +13,8 @@ #include #include #include -#include "../libdebug/debug.h" +#include +#include "../liblogging/logging.h" #ifndef u_char #define u_char unsigned char #endif @@ -40,15 +41,15 @@ static void strnncpy(char *dst, uint8_t *src, int len, int dst_len) void enc_ie_complete(struct l3_msg *l3m, int complete) { - PDEBUG(DDSS1, DEBUG_DEBUG, " Encode IE COMPLETE\n"); + LOGP(DDSS1, LOGL_DEBUG, " Encode IE COMPLETE\n"); if (complete<0 || complete>1) { - PDEBUG(DDSS1, DEBUG_ERROR, "complete(%d) is out of range.\n", complete); + LOGP(DDSS1, LOGL_ERROR, "complete(%d) is out of range.\n", complete); return; } if (complete) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> complete\n"); + LOGP(DDSS1, LOGL_DEBUG, " -> complete\n"); l3m->sending_complete++; } } @@ -60,12 +61,12 @@ void dec_ie_complete(struct l3_msg *l3m, int *complete) uint8_t p = l3m->sending_complete; if (p) { *complete = 1; - PDEBUG(DDSS1, DEBUG_DEBUG, " Decode IE COMPLETE\n"); + LOGP(DDSS1, LOGL_DEBUG, " Decode IE COMPLETE\n"); } if (*complete) - PDEBUG(DDSS1, DEBUG_DEBUG, " -> complete\n"); + LOGP(DDSS1, LOGL_DEBUG, " -> complete\n"); } @@ -75,47 +76,47 @@ void enc_ie_bearer(struct l3_msg *l3m, uint8_t coding, uint8_t capability, int h uint8_t p[256]; int l; - PDEBUG(DDSS1, DEBUG_DEBUG, " Encode IE BEARER\n"); + LOGP(DDSS1, LOGL_DEBUG, " Encode IE BEARER\n"); if (coding > 3) { - PDEBUG(DDSS1, DEBUG_ERROR, "coding(%d) is out of range.\n", coding); + LOGP(DDSS1, LOGL_ERROR, "coding(%d) is out of range.\n", coding); return; } if (capability > 31) { - PDEBUG(DDSS1, DEBUG_ERROR, "capability(%d) is out of range.\n", capability); + LOGP(DDSS1, LOGL_ERROR, "capability(%d) is out of range.\n", capability); return; } if (mode > 3) { - PDEBUG(DDSS1, DEBUG_ERROR, "mode(%d) is out of range.\n", mode); + LOGP(DDSS1, LOGL_ERROR, "mode(%d) is out of range.\n", mode); return; } if (rate > 31) { - PDEBUG(DDSS1, DEBUG_ERROR, "rate(%d) is out of range.\n", rate); + LOGP(DDSS1, LOGL_ERROR, "rate(%d) is out of range.\n", rate); return; } if (multi > 127) { - PDEBUG(DDSS1, DEBUG_ERROR, "multi(%d) is out of range.\n", multi); + LOGP(DDSS1, LOGL_ERROR, "multi(%d) is out of range.\n", multi); return; } if (user > 31) { - PDEBUG(DDSS1, DEBUG_ERROR, "user L1(%d) is out of range.\n", user); + LOGP(DDSS1, LOGL_ERROR, "user L1(%d) is out of range.\n", user); return; } if (rate != 24 && has_multi) { - PDEBUG(DDSS1, DEBUG_ERROR, "multi(%d) is only possible if rate(%d) would be 24.\n", multi, rate); + LOGP(DDSS1, LOGL_ERROR, "multi(%d) is only possible if rate(%d) would be 24.\n", multi, rate); has_multi = 0; } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> coding = %d\n", coding); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> capability = %d\n", capability); + LOGP(DDSS1, LOGL_DEBUG, " -> coding = %d\n", coding); + LOGP(DDSS1, LOGL_DEBUG, " -> capability = %d\n", capability); if (has_mode) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> mode = %d\n", mode); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> rate = %d\n", rate); + LOGP(DDSS1, LOGL_DEBUG, " -> mode = %d\n", mode); + LOGP(DDSS1, LOGL_DEBUG, " -> rate = %d\n", rate); } if (has_multi) - PDEBUG(DDSS1, DEBUG_DEBUG, " -> multi = %d\n", multi); + LOGP(DDSS1, LOGL_DEBUG, " -> multi = %d\n", multi); if (has_user) - PDEBUG(DDSS1, DEBUG_DEBUG, " -> user = %d\n", user); + LOGP(DDSS1, LOGL_DEBUG, " -> user = %d\n", user); l = 1 + (!!has_mode) + (!!has_multi) + (!!has_user); p[0] = IE_BEARER; @@ -138,10 +139,10 @@ int dec_ie_bearer(struct l3_msg *l3m, uint8_t *coding, uint8_t *capability, int if (!p) return -EINVAL; - PDEBUG(DDSS1, DEBUG_DEBUG, " Decode IE BEARER\n"); + LOGP(DDSS1, LOGL_DEBUG, " Decode IE BEARER\n"); if (p[0] < 2) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error IE too short (len=%d)\n", p[0]); + LOGP(DDSS1, LOGL_DEBUG, " -> error IE too short (len=%d)\n", p[0]); return -EINVAL; } @@ -170,16 +171,16 @@ int dec_ie_bearer(struct l3_msg *l3m, uint8_t *coding, uint8_t *capability, int } } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> coding = %d\n", *coding); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> capability = %d\n", *capability); + LOGP(DDSS1, LOGL_DEBUG, " -> coding = %d\n", *coding); + LOGP(DDSS1, LOGL_DEBUG, " -> capability = %d\n", *capability); if (*has_mode) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> mode = %d\n", *mode); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> rate = %d\n", *rate); + LOGP(DDSS1, LOGL_DEBUG, " -> mode = %d\n", *mode); + LOGP(DDSS1, LOGL_DEBUG, " -> rate = %d\n", *rate); } if (*has_multi) - PDEBUG(DDSS1, DEBUG_DEBUG, " -> multi = %d\n", *multi); + LOGP(DDSS1, LOGL_DEBUG, " -> multi = %d\n", *multi); if (*has_user) - PDEBUG(DDSS1, DEBUG_DEBUG, " -> user = %d\n", *user); + LOGP(DDSS1, LOGL_DEBUG, " -> user = %d\n", *user); return 0; } @@ -191,35 +192,35 @@ void enc_ie_hlc(struct l3_msg *l3m, uint8_t coding, uint8_t interpretation, uint uint8_t p[256]; int l; - PDEBUG(DDSS1, DEBUG_DEBUG, " Encode IE HLC\n"); + LOGP(DDSS1, LOGL_DEBUG, " Encode IE HLC\n"); if (coding > 3) { - PDEBUG(DDSS1, DEBUG_ERROR, "coding(%d) is out of range.\n", coding); + LOGP(DDSS1, LOGL_ERROR, "coding(%d) is out of range.\n", coding); return; } if (interpretation > 7) { - PDEBUG(DDSS1, DEBUG_ERROR, "interpretation(%d) is out of range.\n", interpretation); + LOGP(DDSS1, LOGL_ERROR, "interpretation(%d) is out of range.\n", interpretation); return; } if (presentation > 3) { - PDEBUG(DDSS1, DEBUG_ERROR, "presentation(%d) is out of range.\n", presentation); + LOGP(DDSS1, LOGL_ERROR, "presentation(%d) is out of range.\n", presentation); return; } if (hlc > 127) { - PDEBUG(DDSS1, DEBUG_ERROR, "hlc(%d) is out of range.\n", hlc); + LOGP(DDSS1, LOGL_ERROR, "hlc(%d) is out of range.\n", hlc); return; } if (exthlc > 127) { - PDEBUG(DDSS1, DEBUG_ERROR, "hlc(%d) is out of range.\n", exthlc); + LOGP(DDSS1, LOGL_ERROR, "hlc(%d) is out of range.\n", exthlc); return; } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> coding = %d\n", coding); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> interpretation = %d\n", interpretation); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> presentation = %d\n", presentation); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> hlc = %d\n", hlc); + LOGP(DDSS1, LOGL_DEBUG, " -> coding = %d\n", coding); + LOGP(DDSS1, LOGL_DEBUG, " -> interpretation = %d\n", interpretation); + LOGP(DDSS1, LOGL_DEBUG, " -> presentation = %d\n", presentation); + LOGP(DDSS1, LOGL_DEBUG, " -> hlc = %d\n", hlc); if (has_exthlc) - PDEBUG(DDSS1, DEBUG_DEBUG, " -> exthlc = %d\n", exthlc); + LOGP(DDSS1, LOGL_DEBUG, " -> exthlc = %d\n", exthlc); l = 2 + (!!has_exthlc); p[0] = IE_HLC; @@ -241,10 +242,10 @@ int dec_ie_hlc(struct l3_msg *l3m, uint8_t *coding, uint8_t *interpretation, uin if (!p) return -EINVAL; - PDEBUG(DDSS1, DEBUG_DEBUG, " Decode IE HLC\n"); + LOGP(DDSS1, LOGL_DEBUG, " Decode IE HLC\n"); if (p[0] < 2) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error IE too short (len=%d)\n", p[0]); + LOGP(DDSS1, LOGL_DEBUG, " -> error IE too short (len=%d)\n", p[0]); return -EINVAL; } @@ -257,12 +258,12 @@ int dec_ie_hlc(struct l3_msg *l3m, uint8_t *coding, uint8_t *interpretation, uin *exthlc = p[3] & 0x7f; } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> coding = %d\n", *coding); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> interpretation = %d\n", *interpretation); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> presentation = %d\n", *presentation); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> hlc = %d\n", *hlc); + LOGP(DDSS1, LOGL_DEBUG, " -> coding = %d\n", *coding); + LOGP(DDSS1, LOGL_DEBUG, " -> interpretation = %d\n", *interpretation); + LOGP(DDSS1, LOGL_DEBUG, " -> presentation = %d\n", *presentation); + LOGP(DDSS1, LOGL_DEBUG, " -> hlc = %d\n", *hlc); if (*has_exthlc) - PDEBUG(DDSS1, DEBUG_DEBUG, " -> exthlc = %d\n", *exthlc); + LOGP(DDSS1, LOGL_DEBUG, " -> exthlc = %d\n", *exthlc); return 0; } @@ -274,17 +275,17 @@ void enc_ie_call_id(struct l3_msg *l3m, uint8_t *callid, int callid_len) uint8_t p[256]; int l; - PDEBUG(DDSS1, DEBUG_DEBUG, " Encode IE CALL ID\n"); + LOGP(DDSS1, LOGL_DEBUG, " Encode IE CALL ID\n"); if (callid_len == 0) { return; } if (callid_len > 8) { - PDEBUG(DDSS1, DEBUG_ERROR, "callid_len(%d) is out of range.\n", callid_len); + LOGP(DDSS1, LOGL_ERROR, "callid_len(%d) is out of range.\n", callid_len); return; } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> value = %s\n", debug_hex(callid, callid_len)); + LOGP(DDSS1, LOGL_DEBUG, " -> value = %s\n", osmo_hexdump(callid, callid_len)); l = callid_len; p[0] = IE_CALL_ID; @@ -299,17 +300,17 @@ int dec_ie_call_id(struct l3_msg *l3m, uint8_t *callid, int *callid_len) if (!p) return -EINVAL; - PDEBUG(DDSS1, DEBUG_DEBUG, " Decode IE CALL ID\n"); + LOGP(DDSS1, LOGL_DEBUG, " Decode IE CALL ID\n"); if (p[0] > 8) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error IE too long (len=%d)\n", p[0]); + LOGP(DDSS1, LOGL_DEBUG, " -> error IE too long (len=%d)\n", p[0]); return -EINVAL; } *callid_len = p[0]; memcpy(callid, p+1, *callid_len); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> value = %s\n", debug_hex(callid, *callid_len)); + LOGP(DDSS1, LOGL_DEBUG, " -> value = %s\n", osmo_hexdump(callid, *callid_len)); return 0; } @@ -321,24 +322,24 @@ void enc_ie_called_pn(struct l3_msg *l3m, uint8_t type, uint8_t plan, char *numb uint8_t p[256]; int l; - PDEBUG(DDSS1, DEBUG_DEBUG, " Encode IE CALLED PN\n"); + LOGP(DDSS1, LOGL_DEBUG, " Encode IE CALLED PN\n"); if (type > 7) { - PDEBUG(DDSS1, DEBUG_ERROR, "type(%d) is out of range.\n", type); + LOGP(DDSS1, LOGL_ERROR, "type(%d) is out of range.\n", type); return; } if (plan > 15) { - PDEBUG(DDSS1, DEBUG_ERROR, "plan(%d) is out of range.\n", plan); + LOGP(DDSS1, LOGL_ERROR, "plan(%d) is out of range.\n", plan); return; } if (!number[0]) { - PDEBUG(DDSS1, DEBUG_ERROR, "number is not given.\n"); + LOGP(DDSS1, LOGL_ERROR, "number is not given.\n"); return; } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> type = %d\n", type); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> plan = %d\n", plan); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> number = %s\n", number); + LOGP(DDSS1, LOGL_DEBUG, " -> type = %d\n", type); + LOGP(DDSS1, LOGL_DEBUG, " -> plan = %d\n", plan); + LOGP(DDSS1, LOGL_DEBUG, " -> number = %s\n", number); l = 1; if (number[0]) @@ -356,10 +357,10 @@ int dec_ie_called_pn(struct l3_msg *l3m, uint8_t *type, uint8_t *plan, char *num if (!p) return -EINVAL; - PDEBUG(DDSS1, DEBUG_DEBUG, " Decode IE CALLED PN\n"); + LOGP(DDSS1, LOGL_DEBUG, " Decode IE CALLED PN\n"); if (p[0] < 2) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error IE too short (len=%d)\n", p[0]); + LOGP(DDSS1, LOGL_DEBUG, " -> error IE too short (len=%d)\n", p[0]); return -EINVAL; } @@ -367,9 +368,9 @@ int dec_ie_called_pn(struct l3_msg *l3m, uint8_t *type, uint8_t *plan, char *num *plan = p[1] & 0xf; strnncpy(number, p + 2, p[0] - 1, number_len); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> type = %d\n", *type); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> plan = %d\n", *plan); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> number = %s\n", number); + LOGP(DDSS1, LOGL_DEBUG, " -> type = %d\n", *type); + LOGP(DDSS1, LOGL_DEBUG, " -> plan = %d\n", *plan); + LOGP(DDSS1, LOGL_DEBUG, " -> number = %s\n", number); return 0; } @@ -381,32 +382,32 @@ void enc_ie_calling_pn(struct l3_msg *l3m, uint8_t type, uint8_t plan, int has_p uint8_t p[256]; int l; - PDEBUG(DDSS1, DEBUG_DEBUG, " Encode IE CALLING PN\n"); + LOGP(DDSS1, LOGL_DEBUG, " Encode IE CALLING PN\n"); if (type > 7) { - PDEBUG(DDSS1, DEBUG_ERROR, "type(%d) is out of range.\n", type); + LOGP(DDSS1, LOGL_ERROR, "type(%d) is out of range.\n", type); return; } if (plan > 15) { - PDEBUG(DDSS1, DEBUG_ERROR, "plan(%d) is out of range.\n", plan); + LOGP(DDSS1, LOGL_ERROR, "plan(%d) is out of range.\n", plan); return; } if (present > 3) { - PDEBUG(DDSS1, DEBUG_ERROR, "present(%d) is out of range.\n", present); + LOGP(DDSS1, LOGL_ERROR, "present(%d) is out of range.\n", present); return; } if (screen > 3) { - PDEBUG(DDSS1, DEBUG_ERROR, "screen(%d) is out of range.\n", screen); + LOGP(DDSS1, LOGL_ERROR, "screen(%d) is out of range.\n", screen); return; } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> type = %d\n", type); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> plan = %d\n", plan); + LOGP(DDSS1, LOGL_DEBUG, " -> type = %d\n", type); + LOGP(DDSS1, LOGL_DEBUG, " -> plan = %d\n", plan); if (has_present) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> present = %d\n", present); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> screen = %d\n", screen); + LOGP(DDSS1, LOGL_DEBUG, " -> present = %d\n", present); + LOGP(DDSS1, LOGL_DEBUG, " -> screen = %d\n", screen); } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> number = %s\n", number); + LOGP(DDSS1, LOGL_DEBUG, " -> number = %s\n", number); l = 1; if (number[0]) @@ -453,10 +454,10 @@ int dec_ie_calling_pn(struct l3_msg *l3m, int secondary_ie, uint8_t *type, uint8 if (!p) return -EINVAL; - PDEBUG(DDSS1, DEBUG_DEBUG, " Decode IE CALLING PN\n"); + LOGP(DDSS1, LOGL_DEBUG, " Decode IE CALLING PN\n"); if (p[0] < 1) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error IE too short (len=%d)\n", p[0]); + LOGP(DDSS1, LOGL_DEBUG, " -> error IE too short (len=%d)\n", p[0]); return -EINVAL; } @@ -464,7 +465,7 @@ int dec_ie_calling_pn(struct l3_msg *l3m, int secondary_ie, uint8_t *type, uint8 *plan = p[1] & 0xf; if (!(p[1] & 0x80)) { if (p[0] < 2) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error IE too short (len=%d)\n", p[0]); + LOGP(DDSS1, LOGL_DEBUG, " -> error IE too short (len=%d)\n", p[0]); return -EINVAL; } *has_present = 1; @@ -475,13 +476,13 @@ int dec_ie_calling_pn(struct l3_msg *l3m, int secondary_ie, uint8_t *type, uint8 strnncpy(number, p + 2, p[0] - 1, number_len); } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> type = %d\n", *type); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> plan = %d\n", *plan); + LOGP(DDSS1, LOGL_DEBUG, " -> type = %d\n", *type); + LOGP(DDSS1, LOGL_DEBUG, " -> plan = %d\n", *plan); if (*has_present) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> present = %d\n", *present); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> screen = %d\n", *screen); + LOGP(DDSS1, LOGL_DEBUG, " -> present = %d\n", *present); + LOGP(DDSS1, LOGL_DEBUG, " -> screen = %d\n", *screen); } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> number = %s\n", number); + LOGP(DDSS1, LOGL_DEBUG, " -> number = %s\n", number); return 0; } @@ -493,32 +494,32 @@ void enc_ie_connected_pn(struct l3_msg *l3m, uint8_t type, uint8_t plan, int has uint8_t p[256]; int l; - PDEBUG(DDSS1, DEBUG_DEBUG, " Encode IE CONNECTED PN\n"); + LOGP(DDSS1, LOGL_DEBUG, " Encode IE CONNECTED PN\n"); if (type > 7) { - PDEBUG(DDSS1, DEBUG_ERROR, "type(%d) is out of range.\n", type); + LOGP(DDSS1, LOGL_ERROR, "type(%d) is out of range.\n", type); return; } if (plan > 15) { - PDEBUG(DDSS1, DEBUG_ERROR, "plan(%d) is out of range.\n", plan); + LOGP(DDSS1, LOGL_ERROR, "plan(%d) is out of range.\n", plan); return; } if (present > 3) { - PDEBUG(DDSS1, DEBUG_ERROR, "present(%d) is out of range.\n", present); + LOGP(DDSS1, LOGL_ERROR, "present(%d) is out of range.\n", present); return; } if (screen > 3) { - PDEBUG(DDSS1, DEBUG_ERROR, "screen(%d) is out of range.\n", screen); + LOGP(DDSS1, LOGL_ERROR, "screen(%d) is out of range.\n", screen); return; } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> type = %d\n", type); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> plan = %d\n", plan); + LOGP(DDSS1, LOGL_DEBUG, " -> type = %d\n", type); + LOGP(DDSS1, LOGL_DEBUG, " -> plan = %d\n", plan); if (has_present) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> present = %d\n", present); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> screen = %d\n", screen); + LOGP(DDSS1, LOGL_DEBUG, " -> present = %d\n", present); + LOGP(DDSS1, LOGL_DEBUG, " -> screen = %d\n", screen); } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> number = %s\n", number); + LOGP(DDSS1, LOGL_DEBUG, " -> number = %s\n", number); l = 1; l += strlen(number); @@ -545,10 +546,10 @@ int dec_ie_connected_pn(struct l3_msg *l3m, uint8_t *type, uint8_t *plan, int *h if (!p) return -EINVAL; - PDEBUG(DDSS1, DEBUG_DEBUG, " Decode IE CONNECTED PN\n"); + LOGP(DDSS1, LOGL_DEBUG, " Decode IE CONNECTED PN\n"); if (p[0] < 1) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error IE too short (len=%d)\n", p[0]); + LOGP(DDSS1, LOGL_DEBUG, " -> error IE too short (len=%d)\n", p[0]); return -EINVAL; } @@ -556,7 +557,7 @@ int dec_ie_connected_pn(struct l3_msg *l3m, uint8_t *type, uint8_t *plan, int *h *plan = p[1] & 0xf; if (!(p[1] & 0x80)) { if (p[0] < 2) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error IE too short (len=%d)\n", p[0]); + LOGP(DDSS1, LOGL_DEBUG, " -> error IE too short (len=%d)\n", p[0]); return -EINVAL; } *has_present = 1; @@ -567,13 +568,13 @@ int dec_ie_connected_pn(struct l3_msg *l3m, uint8_t *type, uint8_t *plan, int *h strnncpy(number, p+2, p[0]-1, number_len); } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> type = %d\n", *type); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> plan = %d\n", *plan); + LOGP(DDSS1, LOGL_DEBUG, " -> type = %d\n", *type); + LOGP(DDSS1, LOGL_DEBUG, " -> plan = %d\n", *plan); if (*has_present) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> present = %d\n", *present); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> screen = %d\n", *screen); + LOGP(DDSS1, LOGL_DEBUG, " -> present = %d\n", *present); + LOGP(DDSS1, LOGL_DEBUG, " -> screen = %d\n", *screen); } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> number = %s\n", number); + LOGP(DDSS1, LOGL_DEBUG, " -> number = %s\n", number); return 0; } @@ -585,19 +586,19 @@ void enc_ie_cause(struct l3_msg *l3m, uint8_t location, uint8_t cause) uint8_t p[256]; int l; - PDEBUG(DDSS1, DEBUG_DEBUG, " Encode IE CAUSE\n"); + LOGP(DDSS1, LOGL_DEBUG, " Encode IE CAUSE\n"); if (location > 10) { - PDEBUG(DDSS1, DEBUG_ERROR, "location(%d) is out of range.\n", location); + LOGP(DDSS1, LOGL_ERROR, "location(%d) is out of range.\n", location); return; } if (cause > 127) { - PDEBUG(DDSS1, DEBUG_ERROR, "cause(%d) is out of range.\n", cause); + LOGP(DDSS1, LOGL_ERROR, "cause(%d) is out of range.\n", cause); return; } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> location = %d\n", location); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> value = %d\n", cause); + LOGP(DDSS1, LOGL_DEBUG, " -> location = %d\n", location); + LOGP(DDSS1, LOGL_DEBUG, " -> value = %d\n", cause); l = 2; p[0] = IE_CAUSE; @@ -613,18 +614,18 @@ int dec_ie_cause(struct l3_msg *l3m, uint8_t *location, uint8_t *cause) if (!p) return -EINVAL; - PDEBUG(DDSS1, DEBUG_DEBUG, " Decode IE CAUSE\n"); + LOGP(DDSS1, LOGL_DEBUG, " Decode IE CAUSE\n"); if (p[0] < 2) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error IE too short (len=%d)\n", p[0]); + LOGP(DDSS1, LOGL_DEBUG, " -> error IE too short (len=%d)\n", p[0]); return -EINVAL; } *location = p[1] & 0x0f; *cause = p[2] & 0x7f; - PDEBUG(DDSS1, DEBUG_DEBUG, " -> location = %d\n", *location); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> value = %d\n", *cause); + LOGP(DDSS1, LOGL_DEBUG, " -> location = %d\n", *location); + LOGP(DDSS1, LOGL_DEBUG, " -> value = %d\n", *cause); return 0; } @@ -636,30 +637,30 @@ void enc_ie_channel_id(struct l3_msg *l3m, int pri, int exclusive, int channel) uint8_t p[256]; int l; - PDEBUG(DDSS1, DEBUG_DEBUG, " Encode IE CHANNEL ID\n"); + LOGP(DDSS1, LOGL_DEBUG, " Encode IE CHANNEL ID\n"); if (exclusive < 0 || exclusive > 1) { - PDEBUG(DDSS1, DEBUG_ERROR, "exclusive(%d) is out of range.\n", exclusive); + LOGP(DDSS1, LOGL_ERROR, "exclusive(%d) is out of range.\n", exclusive); return; } if ((channel<=0 && channel != CHANNEL_NO && channel != CHANNEL_ANY) || (!pri && channel > 2) || (pri && channel > 127) || (pri && channel == 16)) { - PDEBUG(DDSS1, DEBUG_ERROR, "channel(%d) is out of range.\n", channel); + LOGP(DDSS1, LOGL_ERROR, "channel(%d) is out of range.\n", channel); return; } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> exclusive = %d\n", exclusive); + LOGP(DDSS1, LOGL_DEBUG, " -> exclusive = %d\n", exclusive); switch(channel) { case CHANNEL_ANY: - PDEBUG(DDSS1, DEBUG_DEBUG, " -> channel = any channel\n"); + LOGP(DDSS1, LOGL_DEBUG, " -> channel = any channel\n"); break; case CHANNEL_NO: - PDEBUG(DDSS1, DEBUG_DEBUG, " -> channel = no channel\n"); + LOGP(DDSS1, LOGL_DEBUG, " -> channel = no channel\n"); break; default: - PDEBUG(DDSS1, DEBUG_DEBUG, " -> channel = %d\n", channel); + LOGP(DDSS1, LOGL_DEBUG, " -> channel = %d\n", channel); } if (!pri) { @@ -706,19 +707,19 @@ int dec_ie_channel_id(struct l3_msg *l3m, int pri, int *exclusive, int *channel) if (!p) return -EINVAL; - PDEBUG(DDSS1, DEBUG_DEBUG, " Decode IE CHANNEL ID\n"); + LOGP(DDSS1, LOGL_DEBUG, " Decode IE CHANNEL ID\n"); if (p[0] < 1) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error IE too short (len=%d)\n", p[0]); + LOGP(DDSS1, LOGL_DEBUG, " -> error IE too short (len=%d)\n", p[0]); return -EINVAL; } if (p[1] & 0x40) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error referring to channels of other interfaces is not supported\n"); + LOGP(DDSS1, LOGL_DEBUG, " -> error referring to channels of other interfaces is not supported\n"); return -EINVAL; } if (p[1] & 0x04) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error using d-channel is not supported\n"); + LOGP(DDSS1, LOGL_DEBUG, " -> error using d-channel is not supported\n"); return -EINVAL; } @@ -726,7 +727,7 @@ int dec_ie_channel_id(struct l3_msg *l3m, int pri, int *exclusive, int *channel) if (!pri) { /* BRI */ if (p[1] & 0x20) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error extended channel ID with non PRI interface\n"); + LOGP(DDSS1, LOGL_DEBUG, " -> error extended channel ID with non PRI interface\n"); return -EINVAL; } *channel = p[1] & 0x03; @@ -738,11 +739,11 @@ int dec_ie_channel_id(struct l3_msg *l3m, int pri, int *exclusive, int *channel) /* PRI */ if (p[0] < 1) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error IE too short for PRI (len=%d)\n", p[0]); + LOGP(DDSS1, LOGL_DEBUG, " -> error IE too short for PRI (len=%d)\n", p[0]); return -EINVAL; } if (!(p[1] & 0x20)) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error basic channel ID with PRI interface\n"); + LOGP(DDSS1, LOGL_DEBUG, " -> error basic channel ID with PRI interface\n"); return -EINVAL; } if ((p[1]&0x03) == 0x00) { @@ -756,30 +757,30 @@ int dec_ie_channel_id(struct l3_msg *l3m, int pri, int *exclusive, int *channel) return -EINVAL; } if (p[0] < 3) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error IE too short for PRI with channel (len=%d)\n", p[0]); + LOGP(DDSS1, LOGL_DEBUG, " -> error IE too short for PRI with channel (len=%d)\n", p[0]); return -EINVAL; } if (p[2] & 0x10) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error channel map not supported\n"); + LOGP(DDSS1, LOGL_DEBUG, " -> error channel map not supported\n"); return -EINVAL; } *channel = p[3] & 0x7f; if ((*channel<1) || (*channel==16)) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error PRI interface channel out of range (%d)\n", *channel); + LOGP(DDSS1, LOGL_DEBUG, " -> error PRI interface channel out of range (%d)\n", *channel); return -EINVAL; } } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> exclusive = %d\n", *exclusive); + LOGP(DDSS1, LOGL_DEBUG, " -> exclusive = %d\n", *exclusive); switch(*channel) { case CHANNEL_ANY: - PDEBUG(DDSS1, DEBUG_DEBUG, " -> channel = any channel\n"); + LOGP(DDSS1, LOGL_DEBUG, " -> channel = any channel\n"); break; case CHANNEL_NO: - PDEBUG(DDSS1, DEBUG_DEBUG, " -> channel = no channel\n"); + LOGP(DDSS1, LOGL_DEBUG, " -> channel = no channel\n"); break; default: - PDEBUG(DDSS1, DEBUG_DEBUG, " -> channel = %d\n", *channel); + LOGP(DDSS1, LOGL_DEBUG, " -> channel = %d\n", *channel); } return 0; @@ -792,18 +793,18 @@ void enc_ie_date(struct l3_msg *l3m, time_t ti, int no_seconds) uint8_t p[256]; int l; - PDEBUG(DDSS1, DEBUG_DEBUG, " Encode IE DATE\n"); + LOGP(DDSS1, LOGL_DEBUG, " Encode IE DATE\n"); struct tm *tm; tm = localtime(&ti); if (!tm) { - PDEBUG(DDSS1, DEBUG_ERROR, "localtime() returned NULL.\n"); + LOGP(DDSS1, LOGL_ERROR, "localtime() returned NULL.\n"); return; } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> day = %d.%d.%d\n", tm->tm_mday, tm->tm_mon+1, tm->tm_year%100); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> time = %d:%d:%d\n", tm->tm_hour, tm->tm_min, tm->tm_sec); + LOGP(DDSS1, LOGL_DEBUG, " -> day = %d.%d.%d\n", tm->tm_mday, tm->tm_mon+1, tm->tm_year%100); + LOGP(DDSS1, LOGL_DEBUG, " -> time = %d:%d:%d\n", tm->tm_hour, tm->tm_min, tm->tm_sec); l = 5 + (!no_seconds); p[0] = IE_DATE; @@ -825,19 +826,19 @@ void enc_ie_display(struct l3_msg *l3m, char *display) uint8_t p[256]; int l; - PDEBUG(DDSS1, DEBUG_DEBUG, " Encode IE DISPLAY\n"); + LOGP(DDSS1, LOGL_DEBUG, " Encode IE DISPLAY\n"); if (!display[0]) { - PDEBUG(DDSS1, DEBUG_ERROR, "display text not given.\n"); + LOGP(DDSS1, LOGL_ERROR, "display text not given.\n"); return; } if (strlen(display) > 80) { - PDEBUG(DDSS1, DEBUG_ERROR, "display text too long (max 80 chars), cutting.\n"); + LOGP(DDSS1, LOGL_ERROR, "display text too long (max 80 chars), cutting.\n"); display[80] = '\0'; } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> text = %s\n", display); + LOGP(DDSS1, LOGL_DEBUG, " -> text = %s\n", display); l = strlen(display); p[0] = IE_DISPLAY; @@ -852,16 +853,16 @@ int dec_ie_display(struct l3_msg *l3m, char *display, int display_len) if (!p) return -EINVAL; - PDEBUG(DDSS1, DEBUG_DEBUG, " Decode IE DISPLAY\n"); + LOGP(DDSS1, LOGL_DEBUG, " Decode IE DISPLAY\n"); if (p[0] < 1) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error IE too short (len=%d)\n", p[0]); + LOGP(DDSS1, LOGL_DEBUG, " -> error IE too short (len=%d)\n", p[0]); return -EINVAL; } strnncpy(display, p+1, p[0], display_len); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> text = %s\n", display); + LOGP(DDSS1, LOGL_DEBUG, " -> text = %s\n", display); return 0; } @@ -870,17 +871,17 @@ int dec_ie_display(struct l3_msg *l3m, char *display, int display_len) /* IE_KEYPAD */ void enc_ie_keypad(struct l3_msg *l3m, char *keypad) { - PDEBUG(DDSS1, DEBUG_DEBUG, " Encode IE KEYPAD\n"); + LOGP(DDSS1, LOGL_DEBUG, " Encode IE KEYPAD\n"); uint8_t p[256]; int l; if (!keypad[0]) { - PDEBUG(DDSS1, DEBUG_ERROR, "keypad info not given.\n"); + LOGP(DDSS1, LOGL_ERROR, "keypad info not given.\n"); return; } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> keypad = %s\n", keypad); + LOGP(DDSS1, LOGL_DEBUG, " -> keypad = %s\n", keypad); l = strlen((char *)keypad); p[0] = IE_KEYPAD; @@ -895,16 +896,16 @@ int dec_ie_keypad(struct l3_msg *l3m, char *keypad, int keypad_len) if (!p) return -EINVAL; - PDEBUG(DDSS1, DEBUG_DEBUG, " Decode IE KEYPAD\n"); + LOGP(DDSS1, LOGL_DEBUG, " Decode IE KEYPAD\n"); if (p[0] < 1) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error IE too short (len=%d)\n", p[0]); + LOGP(DDSS1, LOGL_DEBUG, " -> error IE too short (len=%d)\n", p[0]); return -EINVAL; } strnncpy(keypad, p + 1, p[0], keypad_len); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> keypad = %s\n", keypad); + LOGP(DDSS1, LOGL_DEBUG, " -> keypad = %s\n", keypad); return 0; } @@ -916,14 +917,14 @@ void enc_ie_notify(struct l3_msg *l3m, uint8_t notify) uint8_t p[256]; int l; - PDEBUG(DDSS1, DEBUG_DEBUG, " Encode IE NOTIFY\n"); + LOGP(DDSS1, LOGL_DEBUG, " Encode IE NOTIFY\n"); if (notify > 0x7f) { - PDEBUG(DDSS1, DEBUG_ERROR, "notify(%d) is out of range.\n", notify); + LOGP(DDSS1, LOGL_ERROR, "notify(%d) is out of range.\n", notify); return; } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> notify = %d\n", notify); + LOGP(DDSS1, LOGL_DEBUG, " -> notify = %d\n", notify); l = 1; p[0] = IE_NOTIFY; @@ -940,16 +941,16 @@ int dec_ie_notify(struct l3_msg *l3m, uint8_t *notify) if (!p) return -EINVAL; - PDEBUG(DDSS1, DEBUG_DEBUG, " Decode IE NOTIFY\n"); + LOGP(DDSS1, LOGL_DEBUG, " Decode IE NOTIFY\n"); if (p[0] < 1) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error IE too short (len=%d)\n", p[0]); + LOGP(DDSS1, LOGL_DEBUG, " -> error IE too short (len=%d)\n", p[0]); return -EINVAL; } *notify = p[1] & 0x7f; - PDEBUG(DDSS1, DEBUG_DEBUG, " -> notify = %d\n", *notify); + LOGP(DDSS1, LOGL_DEBUG, " -> notify = %d\n", *notify); return 0; } @@ -961,24 +962,24 @@ void enc_ie_progress(struct l3_msg *l3m, uint8_t coding, uint8_t location, uint8 uint8_t p[256]; int l; - PDEBUG(DDSS1, DEBUG_DEBUG, " Encode IE PROGRESS\n"); + LOGP(DDSS1, LOGL_DEBUG, " Encode IE PROGRESS\n"); if (coding > 0x03) { - PDEBUG(DDSS1, DEBUG_ERROR, "coding(%d) is out of range.\n", coding); + LOGP(DDSS1, LOGL_ERROR, "coding(%d) is out of range.\n", coding); return; } if (location > 0x0f) { - PDEBUG(DDSS1, DEBUG_ERROR, "location(%d) is out of range.\n", location); + LOGP(DDSS1, LOGL_ERROR, "location(%d) is out of range.\n", location); return; } if (progress > 0x7f) { - PDEBUG(DDSS1, DEBUG_ERROR, "progress(%d) is out of range.\n", progress); + LOGP(DDSS1, LOGL_ERROR, "progress(%d) is out of range.\n", progress); return; } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> coding = %d\n", coding); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> location = %d\n", location); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> indicator = %d\n", progress); + LOGP(DDSS1, LOGL_DEBUG, " -> coding = %d\n", coding); + LOGP(DDSS1, LOGL_DEBUG, " -> location = %d\n", location); + LOGP(DDSS1, LOGL_DEBUG, " -> indicator = %d\n", progress); l = 2; p[0] = IE_PROGRESS; @@ -994,10 +995,10 @@ int dec_ie_progress(struct l3_msg *l3m, uint8_t *coding, uint8_t *location, uint if (!p) return -EINVAL; - PDEBUG(DDSS1, DEBUG_DEBUG, " Decode IE PROGRESS\n"); + LOGP(DDSS1, LOGL_DEBUG, " Decode IE PROGRESS\n"); if (p[0] < 1) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error IE too short (len=%d)\n", p[0]); + LOGP(DDSS1, LOGL_DEBUG, " -> error IE too short (len=%d)\n", p[0]); return -EINVAL; } @@ -1005,9 +1006,9 @@ int dec_ie_progress(struct l3_msg *l3m, uint8_t *coding, uint8_t *location, uint *location = p[1] & 0x0f; *progress = p[2] & 0x7f; - PDEBUG(DDSS1, DEBUG_DEBUG, " -> coding = %d\n", *coding); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> location = %d\n", *location); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> indicator = %d\n", *progress); + LOGP(DDSS1, LOGL_DEBUG, " -> coding = %d\n", *coding); + LOGP(DDSS1, LOGL_DEBUG, " -> location = %d\n", *location); + LOGP(DDSS1, LOGL_DEBUG, " -> indicator = %d\n", *progress); return 0; } @@ -1019,38 +1020,38 @@ void enc_ie_redirecting(struct l3_msg *l3m, uint8_t type, uint8_t plan, int has_ uint8_t p[256]; int l; - PDEBUG(DDSS1, DEBUG_DEBUG, " Encode IE REDIRECTING NR\n"); + LOGP(DDSS1, LOGL_DEBUG, " Encode IE REDIRECTING NR\n"); if (type > 7) { - PDEBUG(DDSS1, DEBUG_ERROR, "type(%d) is out of range.\n", type); + LOGP(DDSS1, LOGL_ERROR, "type(%d) is out of range.\n", type); return; } if (plan > 15) { - PDEBUG(DDSS1, DEBUG_ERROR, "plan(%d) is out of range.\n", plan); + LOGP(DDSS1, LOGL_ERROR, "plan(%d) is out of range.\n", plan); return; } if (present > 3) { - PDEBUG(DDSS1, DEBUG_ERROR, "present(%d) is out of range.\n", present); + LOGP(DDSS1, LOGL_ERROR, "present(%d) is out of range.\n", present); return; } if (screen > 3) { - PDEBUG(DDSS1, DEBUG_ERROR, "screen(%d) is out of range.\n", screen); + LOGP(DDSS1, LOGL_ERROR, "screen(%d) is out of range.\n", screen); return; } if (reason > 0x0f) { - PDEBUG(DDSS1, DEBUG_ERROR, "reason(%d) is out of range.\n", reason); + LOGP(DDSS1, LOGL_ERROR, "reason(%d) is out of range.\n", reason); return; } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> type = %d\n", type); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> plan = %d\n", plan); + LOGP(DDSS1, LOGL_DEBUG, " -> type = %d\n", type); + LOGP(DDSS1, LOGL_DEBUG, " -> plan = %d\n", plan); if (has_present) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> present = %d\n", present); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> screen = %d\n", screen); + LOGP(DDSS1, LOGL_DEBUG, " -> present = %d\n", present); + LOGP(DDSS1, LOGL_DEBUG, " -> screen = %d\n", screen); if (has_reason) - PDEBUG(DDSS1, DEBUG_DEBUG, " -> reason = %d\n", reason); + LOGP(DDSS1, LOGL_DEBUG, " -> reason = %d\n", reason); } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> number = %s\n", number); + LOGP(DDSS1, LOGL_DEBUG, " -> number = %s\n", number); l = 1; l += strlen(number); @@ -1088,10 +1089,10 @@ int dec_ie_redirecting(struct l3_msg *l3m, uint8_t *type, uint8_t *plan, int *ha if (!p) return -EINVAL; - PDEBUG(DDSS1, DEBUG_DEBUG, " Decode IE REDIRECTING NR\n"); + LOGP(DDSS1, LOGL_DEBUG, " Decode IE REDIRECTING NR\n"); if (p[0] < 1) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error IE too short (len=%d)\n", p[0]); + LOGP(DDSS1, LOGL_DEBUG, " -> error IE too short (len=%d)\n", p[0]); return -EINVAL; } @@ -1112,15 +1113,15 @@ int dec_ie_redirecting(struct l3_msg *l3m, uint8_t *type, uint8_t *plan, int *ha strnncpy(number, p+2, p[0]-1, number_len); } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> type = %d\n", *type); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> plan = %d\n", *plan); + LOGP(DDSS1, LOGL_DEBUG, " -> type = %d\n", *type); + LOGP(DDSS1, LOGL_DEBUG, " -> plan = %d\n", *plan); if (*has_present) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> present = %d\n", *present); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> screen = %d\n", *screen); + LOGP(DDSS1, LOGL_DEBUG, " -> present = %d\n", *present); + LOGP(DDSS1, LOGL_DEBUG, " -> screen = %d\n", *screen); if (*has_reason) - PDEBUG(DDSS1, DEBUG_DEBUG, " -> reason = %d\n", *reason); + LOGP(DDSS1, LOGL_DEBUG, " -> reason = %d\n", *reason); } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> number = %s\n", number); + LOGP(DDSS1, LOGL_DEBUG, " -> number = %s\n", number); return 0; } @@ -1132,26 +1133,26 @@ void enc_ie_redirection(struct l3_msg *l3m, uint8_t type, uint8_t plan, int has_ uint8_t p[256]; int l; - PDEBUG(DDSS1, DEBUG_DEBUG, " Encode IE REDIRECTION NR\n"); + LOGP(DDSS1, LOGL_DEBUG, " Encode IE REDIRECTION NR\n"); if (type > 7) { - PDEBUG(DDSS1, DEBUG_ERROR, "type(%d) is out of range.\n", type); + LOGP(DDSS1, LOGL_ERROR, "type(%d) is out of range.\n", type); return; } if (plan > 15) { - PDEBUG(DDSS1, DEBUG_ERROR, "plan(%d) is out of range.\n", plan); + LOGP(DDSS1, LOGL_ERROR, "plan(%d) is out of range.\n", plan); return; } if (present > 3) { - PDEBUG(DDSS1, DEBUG_ERROR, "present(%d) is out of range.\n", present); + LOGP(DDSS1, LOGL_ERROR, "present(%d) is out of range.\n", present); return; } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> type = %d\n", type); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> plan = %d\n", plan); + LOGP(DDSS1, LOGL_DEBUG, " -> type = %d\n", type); + LOGP(DDSS1, LOGL_DEBUG, " -> plan = %d\n", plan); if (has_present) - PDEBUG(DDSS1, DEBUG_DEBUG, " -> present = %d\n", present); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> number = %s\n", number); + LOGP(DDSS1, LOGL_DEBUG, " -> present = %d\n", present); + LOGP(DDSS1, LOGL_DEBUG, " -> number = %s\n", number); l = 1; l += strlen(number); @@ -1178,10 +1179,10 @@ int dec_ie_redirection(struct l3_msg *l3m, uint8_t *type, uint8_t *plan, int *ha if (!p) return -EINVAL; - PDEBUG(DDSS1, DEBUG_DEBUG, " Decode IE REDIRECTION NR\n"); + LOGP(DDSS1, LOGL_DEBUG, " Decode IE REDIRECTION NR\n"); if (p[0] < 1) { - PDEBUG(DDSS1, DEBUG_DEBUG, " -> error IE too short (len=%d)\n", p[0]); + LOGP(DDSS1, LOGL_DEBUG, " -> error IE too short (len=%d)\n", p[0]); return -EINVAL; } @@ -1195,11 +1196,11 @@ int dec_ie_redirection(struct l3_msg *l3m, uint8_t *type, uint8_t *plan, int *ha strnncpy(number, p + 2, p[0] - 1, number_len); } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> type = %d\n", *type); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> plan = %d\n", *plan); + LOGP(DDSS1, LOGL_DEBUG, " -> type = %d\n", *type); + LOGP(DDSS1, LOGL_DEBUG, " -> plan = %d\n", *plan); if (*has_present) - PDEBUG(DDSS1, DEBUG_DEBUG, " -> present = %d\n", *present); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> number = %s\n", number); + LOGP(DDSS1, LOGL_DEBUG, " -> present = %d\n", *present); + LOGP(DDSS1, LOGL_DEBUG, " -> number = %s\n", number); return 0; } @@ -1211,12 +1212,12 @@ void enc_ie_facility(struct l3_msg *l3m, uint8_t *facility, int facility_len) uint8_t p[256]; int l; - PDEBUG(DDSS1, DEBUG_DEBUG, " Encode IE FACILITY\n"); + LOGP(DDSS1, LOGL_DEBUG, " Encode IE FACILITY\n"); if (!facility || facility_len <= 0) return; - PDEBUG(DDSS1, DEBUG_DEBUG, " -> value = %s\n", debug_hex(facility, facility_len)); + LOGP(DDSS1, LOGL_DEBUG, " -> value = %s\n", osmo_hexdump(facility, facility_len)); l = facility_len; p[0] = IE_FACILITY; @@ -1233,12 +1234,12 @@ int dec_ie_facility(struct l3_msg *l3m, uint8_t *facility, int *facility_len) if (!p) return -EINVAL; - PDEBUG(DDSS1, DEBUG_DEBUG, " Decode IE FACILITY\n"); + LOGP(DDSS1, LOGL_DEBUG, " Decode IE FACILITY\n"); *facility_len = p[0]; memcpy(facility, p + 1, *facility_len); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> value = %s\n", debug_hex(facility, *facility_len)); + LOGP(DDSS1, LOGL_DEBUG, " -> value = %s\n", osmo_hexdump(facility, *facility_len)); return 0; } @@ -1250,18 +1251,18 @@ void enc_ie_useruser(struct l3_msg *l3m, uint8_t protocol, uint8_t *user, int us uint8_t p[256]; int l; - PDEBUG(DDSS1, DEBUG_DEBUG, " Encode IE USER-USER\n"); + LOGP(DDSS1, LOGL_DEBUG, " Encode IE USER-USER\n"); if (protocol > 127) { - PDEBUG(DDSS1, DEBUG_ERROR, "protocol(%d) is out of range.\n", protocol); + LOGP(DDSS1, LOGL_ERROR, "protocol(%d) is out of range.\n", protocol); return; } if (!user || user_len <= 0) { return; } - PDEBUG(DDSS1, DEBUG_DEBUG, " -> protocol = %d\n", protocol); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> value = %s\n", debug_hex(user, user_len)); + LOGP(DDSS1, LOGL_DEBUG, " -> protocol = %d\n", protocol); + LOGP(DDSS1, LOGL_DEBUG, " -> value = %s\n", osmo_hexdump(user, user_len)); l = user_len; p[0] = IE_USER_USER; @@ -1279,7 +1280,7 @@ int dec_ie_useruser(struct l3_msg *l3m, uint8_t *protocol, uint8_t *user, int *u if (!p) return -EINVAL; - PDEBUG(DDSS1, DEBUG_DEBUG, " Decode IE USER-USER\n"); + LOGP(DDSS1, LOGL_DEBUG, " Decode IE USER-USER\n"); *user_len = p[0] - 1; if (p[0] < 1) @@ -1287,8 +1288,8 @@ int dec_ie_useruser(struct l3_msg *l3m, uint8_t *protocol, uint8_t *user, int *u *protocol = p[1]; memcpy(user, p + 2, (*user_len <= 128) ? *user_len : 128); /* clip to 128 maximum */ - PDEBUG(DDSS1, DEBUG_DEBUG, " -> protocol = %d\n", *protocol); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> value = %s\n", debug_hex(user, *user_len)); + LOGP(DDSS1, LOGL_DEBUG, " -> protocol = %d\n", *protocol); + LOGP(DDSS1, LOGL_DEBUG, " -> value = %s\n", osmo_hexdump(user, *user_len)); return 0; } @@ -1298,9 +1299,9 @@ void enc_ie_signal(struct l3_msg *l3m, uint8_t signal) { uint8_t p[256]; - PDEBUG(DDSS1, DEBUG_DEBUG, " Encode IE SIGNAL\n"); + LOGP(DDSS1, LOGL_DEBUG, " Encode IE SIGNAL\n"); - PDEBUG(DDSS1, DEBUG_DEBUG, " -> signal = %d\n", signal); + LOGP(DDSS1, LOGL_DEBUG, " -> signal = %d\n", signal); p[0] = IE_SIGNAL; p[1] = 1; diff --git a/src/isdn/isdn.c b/src/isdn/isdn.c index d3e6366..7be94e1 100644 --- a/src/isdn/isdn.c +++ b/src/isdn/isdn.c @@ -43,8 +43,11 @@ #include #include #include -#include "../libdebug/debug.h" -#include "../libg711/g711.h" +#include "../liblogging/logging.h" +#include +#include +#include +#include #include "isdn.h" #include "dss1.h" #include "ie.h" @@ -56,11 +59,14 @@ #include #include "../libmisdn/socket.h" -#ifndef container_of -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) -#endif +static double get_time(void) +{ + static struct timespec tv; + + clock_gettime(CLOCK_REALTIME, &tv); + + return (double)tv.tv_sec + (double)tv.tv_nsec / 1000000000.0; +} #define B_TIMER_ACTIVATING 1 // seconds #define B_TIMER_DEACTIVATING 1 // seconds @@ -152,7 +158,7 @@ static int parse_out_channel(isdn_t *isdn_ep, const char *_list) if (!strcasecmp(el, "force")) { isdn_ep->out_channel_exclusive = 1; if (isdn_ep->out_channel) { - PDEBUG(DISDN, DEBUG_ERROR, "Error outgoing channel string: value 'force' may only appear as first element in list.\n"); + LOGP(DISDN, LOGL_ERROR, "Error outgoing channel string: value 'force' may only appear as first element in list.\n"); return(-1); } } else @@ -170,12 +176,12 @@ static int parse_out_channel(isdn_t *isdn_ep, const char *_list) } else { val = get_number(el); if (val == -1) { - PDEBUG(DISDN, DEBUG_ERROR, "Error outgoing channel string: expecting a comma separated list of 'force', 'any', 'free', 'no' and any channel number.\n"); + LOGP(DISDN, LOGL_ERROR, "Error outgoing channel string: expecting a comma separated list of 'force', 'any', 'free', 'no' and any channel number.\n"); return(-1); } if (val<1 || val==16 || val>126) { - PDEBUG(DISDN, DEBUG_ERROR, "Error outgoing channel string: channel '%d' out of range.\n", val); + LOGP(DISDN, LOGL_ERROR, "Error outgoing channel string: channel '%d' out of range.\n", val); return(-1); } selchannel: @@ -205,7 +211,7 @@ static int parse_in_channel(isdn_t *isdn_ep, const char *_list) el = p; p = get_separated(p); if (isdn_ep->in_channel) if (isdn_ep->in_channel->channel == CHANNEL_FREE) { - PDEBUG(DISDN, DEBUG_ERROR, "Error incoming channel list: values behind 'free' keyword have no effect.\n"); + LOGP(DISDN, LOGL_ERROR, "Error incoming channel list: values behind 'free' keyword have no effect.\n"); return(-1); } if (!strcasecmp(el, "free")) { @@ -214,12 +220,12 @@ static int parse_in_channel(isdn_t *isdn_ep, const char *_list) } else { val = get_number(el); if (val == -1) { - PDEBUG(DISDN, DEBUG_ERROR, "Error incoming channel list: expectng a comma separated list of channel numbers and 'free'.\n"); + LOGP(DISDN, LOGL_ERROR, "Error incoming channel list: expectng a comma separated list of channel numbers and 'free'.\n"); return(-1); } if (val<1 || val==16 || val>126) { - PDEBUG(DISDN, DEBUG_ERROR, "Error incoming channel list: channel '%d' out of range.\n", val); + LOGP(DISDN, LOGL_ERROR, "Error incoming channel list: channel '%d' out of range.\n", val); return(-1); } selchannel: @@ -241,24 +247,24 @@ int hunt_bchannel_in(isdn_t *isdn_ep, int channel, int exclusive) struct select_channel *selchannel; int i; - PDEBUG(DISDN, DEBUG_DEBUG, "Channel Selection (incoming call)\n"); + LOGP(DISDN, LOGL_DEBUG, "Channel Selection (incoming call)\n"); if (exclusive<0) exclusive = 0; if (channel == CHANNEL_NO) - PDEBUG(DISDN, DEBUG_DEBUG, " -> request = no-channel\n"); + LOGP(DISDN, LOGL_DEBUG, " -> request = no-channel\n"); else if (channel > 0) - PDEBUG(DISDN, DEBUG_DEBUG, " -> request = channel %d%s\n", channel, exclusive?" (forced)":""); + LOGP(DISDN, LOGL_DEBUG, " -> request = channel %d%s\n", channel, exclusive?" (forced)":""); else - PDEBUG(DISDN, DEBUG_DEBUG, " -> request = any channel\n"); + LOGP(DISDN, LOGL_DEBUG, " -> request = any channel\n"); if (channel==CHANNEL_NO && !isdn_ep->ntmode) { - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = incoming call-waiting not supported for TE-mode\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = incoming call-waiting not supported for TE-mode\n"); return(-6); // channel unacceptable } if (channel <= 0) /* not given, no channel, whatever.. */ channel = CHANNEL_ANY; /* any channel */ if (isdn_ep->b_reserved >= isdn_ep->b_num) { // of out chan.. - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = all channels are reserved\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = all channels are reserved\n"); return(-34); // no channel } if (channel == CHANNEL_ANY) @@ -278,19 +284,19 @@ int hunt_bchannel_in(isdn_t *isdn_ep, int channel, int exclusive) if (exclusive) { /* no exclusive channel */ if (!channel) { - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = exclusively requested channel not in list\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = exclusively requested channel not in list\n"); return(-6); // channel unacceptable } /* get index for channel */ i = channel-1-(channel>=17); if (i < 0 || i >= isdn_ep->b_num || channel == 16) { - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = exclusively requested channel outside interface range\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = exclusively requested channel outside interface range\n"); return(-6); // channel unacceptable } /* check if busy */ if (isdn_ep->b_call[i] == NULL) goto use_channel; - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = exclusively requested channel is busy\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = exclusively requested channel is busy\n"); return(-6); // channel unacceptable } @@ -299,7 +305,7 @@ int hunt_bchannel_in(isdn_t *isdn_ep, int channel, int exclusive) /* get index for channel */ i = channel-1-(channel>=17); if (i < 0 || i >= isdn_ep->b_num || channel == 16) { - PDEBUG(DISDN, DEBUG_DEBUG, " -> quested channel %d outside interface range\n", channel); + LOGP(DISDN, LOGL_DEBUG, " -> quested channel %d outside interface range\n", channel); } else /* if inside range (else) check if available */ if (isdn_ep->b_call[i] == NULL) goto use_channel; @@ -313,7 +319,7 @@ int hunt_bchannel_in(isdn_t *isdn_ep, int channel, int exclusive) while(selchannel) { switch(selchannel->channel) { case CHANNEL_FREE: /* free channel */ - PDEBUG(DISDN, DEBUG_DEBUG, " -> hunting free channel\n"); + LOGP(DISDN, LOGL_DEBUG, " -> hunting free channel\n"); if (isdn_ep->b_reserved >= isdn_ep->b_num) break; /* all channel in use or reserved */ /* find channel */ @@ -328,7 +334,7 @@ int hunt_bchannel_in(isdn_t *isdn_ep, int channel, int exclusive) break; default: - PDEBUG(DISDN, DEBUG_DEBUG, " -> hunting channel %d\n", selchannel->channel); + LOGP(DISDN, LOGL_DEBUG, " -> hunting channel %d\n", selchannel->channel); if (selchannel->channel<1 || selchannel->channel==16) break; /* invalid channels */ i = selchannel->channel-1-(selchannel->channel>=17); @@ -345,13 +351,13 @@ int hunt_bchannel_in(isdn_t *isdn_ep, int channel, int exclusive) selchannel = selchannel->next; } if (!channel) { - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = no channel available\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = no channel available\n"); return(-6); // channel unacceptable } } use_channel: - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = channel available\n"); - PDEBUG(DISDN, DEBUG_DEBUG, " -> connect to channel %d\n", channel); + LOGP(DISDN, LOGL_DEBUG, " -> result = channel available\n"); + LOGP(DISDN, LOGL_DEBUG, " -> connect to channel %d\n", channel); return(channel); } @@ -361,11 +367,11 @@ int hunt_bchannel_out(isdn_t *isdn_ep, int *channel, int *exclusive) struct select_channel *selchannel; int i; - PDEBUG(DISDN, DEBUG_DEBUG, "Channel Selection (outgoing call)\n"); + LOGP(DISDN, LOGL_DEBUG, "Channel Selection (outgoing call)\n"); /* see if link is up on PTP*/ if (isdn_ep->l2hold && isdn_ep->l2link<1) { - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = layer 2 is down\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = layer 2 is down\n"); return -27; } @@ -383,42 +389,42 @@ int hunt_bchannel_out(isdn_t *isdn_ep, int *channel, int *exclusive) while(i < isdn_ep->b_num) { if (isdn_ep->b_call[i] == NULL) { *channel = i+1+(i>=15); - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = free channel %d\n", *channel); + LOGP(DISDN, LOGL_DEBUG, " -> result = free channel %d\n", *channel); break; } i++; } if (*channel) break; - PDEBUG(DISDN, DEBUG_DEBUG, " -> no free channel found\n"); + LOGP(DISDN, LOGL_DEBUG, " -> no free channel found\n"); break; case CHANNEL_ANY: /* don't ask for channel */ if (isdn_ep->b_reserved >= isdn_ep->b_num) { - PDEBUG(DISDN, DEBUG_DEBUG, " -> cannot ask for any channel, because all channel are reserved\n"); + LOGP(DISDN, LOGL_DEBUG, " -> cannot ask for any channel, because all channel are reserved\n"); break; /* all channel in use or reserved */ } - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = any channel\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = any channel\n"); *channel = CHANNEL_ANY; break; case CHANNEL_NO: /* call waiting */ - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = no channel\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = no channel\n"); *channel = CHANNEL_NO; break; default: if (selchannel->channel<1 || selchannel->channel==16) { - PDEBUG(DISDN, DEBUG_DEBUG, " -> channel %d is out of range\n", selchannel->channel); + LOGP(DISDN, LOGL_DEBUG, " -> channel %d is out of range\n", selchannel->channel); break; /* invalid channels */ } i = selchannel->channel-1-(selchannel->channel>=17); if (i >= isdn_ep->b_num) { - PDEBUG(DISDN, DEBUG_DEBUG, " -> channel %d is out of range\n", selchannel->channel); + LOGP(DISDN, LOGL_DEBUG, " -> channel %d is out of range\n", selchannel->channel); break; /* channel not in port */ } if (isdn_ep->b_call[i] == NULL) { - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = channel %d\n", selchannel->channel); + LOGP(DISDN, LOGL_DEBUG, " -> result = channel %d\n", selchannel->channel); *channel = selchannel->channel; break; } @@ -433,7 +439,7 @@ int hunt_bchannel_out(isdn_t *isdn_ep, int *channel, int *exclusive) return 0; /* if channel was found, return channel */ - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = no channel found\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = no channel found\n"); return -34; } @@ -469,23 +475,23 @@ int open_bchannel_out(call_t *call, unsigned int cmd, int channel, int exclusive if (call->state != ISDN_STATE_OUT_SETUP) return(0); - PDEBUG(DISDN, DEBUG_DEBUG, "Channel Selection (reply from outgoing call)\n"); + LOGP(DISDN, LOGL_DEBUG, "Channel Selection (reply from outgoing call)\n"); - PDEBUG(DISDN, DEBUG_DEBUG, " -> request = %d (forced)\n", call->b_channel); - PDEBUG(DISDN, DEBUG_DEBUG, (channel>=0)?" -> reply = %d\n":" -> reply = (none)\n", channel); + LOGP(DISDN, LOGL_DEBUG, " -> request = %d (forced)\n", call->b_channel); + LOGP(DISDN, LOGL_DEBUG, (channel>=0)?" -> reply = %d\n":" -> reply = (none)\n", channel); /* if give channel not accepted or not equal */ if (channel != -1 && call->b_channel != channel) { - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = forced channel not accepted\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = forced channel not accepted\n"); return -44; } rc = seize_bchannel(call, channel, 1); // exclusively if (rc < 0) { - PDEBUG(DISDN, DEBUG_DEBUG, "result = requested channel not available anymore\n"); + LOGP(DISDN, LOGL_DEBUG, "result = requested channel not available anymore\n"); return -47; } - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = channel was accepted\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = channel was accepted\n"); /* activate our exclusive channel */ bchannel_event(call->isdn_ep, call->b_index, B_EVENT_USE); @@ -497,10 +503,10 @@ int open_bchannel_out(call_t *call, unsigned int cmd, int channel, int exclusive if (call->state != ISDN_STATE_OUT_SETUP) return(0); - PDEBUG(DISDN, DEBUG_DEBUG, "Channel Selection (reply from outgoing call)\n"); + LOGP(DISDN, LOGL_DEBUG, "Channel Selection (reply from outgoing call)\n"); - PDEBUG(DISDN, DEBUG_DEBUG, " -> request = %d (suggest)\n", call->b_channel); - PDEBUG(DISDN, DEBUG_DEBUG, (channel>=0)?" -> reply = %d\n":" -> reply = (none)\n", channel); + LOGP(DISDN, LOGL_DEBUG, " -> request = %d (suggest)\n", call->b_channel); + LOGP(DISDN, LOGL_DEBUG, (channel>=0)?" -> reply = %d\n":" -> reply = (none)\n", channel); /* if channel was accepted as given */ if (channel==-1 || call->b_channel==channel) { @@ -509,11 +515,11 @@ int open_bchannel_out(call_t *call, unsigned int cmd, int channel, int exclusive /* if channel was accepted, seize_bchannel shall simply return, because given channel is already set */ rc = seize_bchannel(call, call->b_channel, 1); // exclusively if (rc < 0) { - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = replied channel not available\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = replied channel not available\n"); return -47; } - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = channel was accepted as given\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = channel was accepted as given\n"); /* activate channel accepted by remote */ bchannel_event(call->isdn_ep, call->b_index, B_EVENT_USE); @@ -522,17 +528,17 @@ int open_bchannel_out(call_t *call, unsigned int cmd, int channel, int exclusive /* if channel value is faulty */ if (channel <= 0) { - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = illegal reply\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = illegal reply\n"); return -111; // protocol error } /* if channel was not accepted, try to get a different one */ rc = seize_bchannel(call, channel, 1); // exclusively if (rc < 0) { - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = replied channel not available\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = replied channel not available\n"); return -47; } - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = replied channel accepted\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = replied channel accepted\n"); /* activate channel given by remote */ bchannel_event(call->isdn_ep, call->b_index, B_EVENT_USE); @@ -544,23 +550,23 @@ int open_bchannel_out(call_t *call, unsigned int cmd, int channel, int exclusive if (call->state != ISDN_STATE_OUT_SETUP) return(0); - PDEBUG(DISDN, DEBUG_DEBUG, "Channel Selection (reply from outgoing call)\n"); + LOGP(DISDN, LOGL_DEBUG, "Channel Selection (reply from outgoing call)\n"); - PDEBUG(DISDN, DEBUG_DEBUG, " -> request = any\n"); - PDEBUG(DISDN, DEBUG_DEBUG, (channel>=0)?" -> reply = %d\n":" -> reply = (none)\n", channel); + LOGP(DISDN, LOGL_DEBUG, " -> request = any\n"); + LOGP(DISDN, LOGL_DEBUG, (channel>=0)?" -> reply = %d\n":" -> reply = (none)\n", channel); /* if no channel was replied */ if (channel <= 0) { - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = no channel, protocol error\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = no channel, protocol error\n"); return -111; // protocol error } /* we will see, if our received channel is available */ rc = seize_bchannel(call, channel, 1); // exclusively if (rc < 0) { - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = replied channel not available\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = replied channel not available\n"); return -47; } - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = replied channel accepted\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = replied channel accepted\n"); /* activate channel given by remote */ bchannel_event(call->isdn_ep, call->b_index, B_EVENT_USE); @@ -569,19 +575,19 @@ int open_bchannel_out(call_t *call, unsigned int cmd, int channel, int exclusive /* if not the first reply, but a connect, we are forced */ if (cmd == MT_CONNECT && call->state != ISDN_STATE_OUT_SETUP) { - PDEBUG(DISDN, DEBUG_DEBUG, "Channel Selection (connect reply from outgoing call)\n"); + LOGP(DISDN, LOGL_DEBUG, "Channel Selection (connect reply from outgoing call)\n"); - PDEBUG(DISDN, DEBUG_DEBUG, " -> request = no channel\n"); - PDEBUG(DISDN, DEBUG_DEBUG, (channel>=0)?" -> reply %d%s\n":" -> reply (none)\n", channel, exclusive?" (forced)":""); + LOGP(DISDN, LOGL_DEBUG, " -> request = no channel\n"); + LOGP(DISDN, LOGL_DEBUG, (channel>=0)?" -> reply %d%s\n":" -> reply (none)\n", channel, exclusive?" (forced)":""); if (channel > 0) { goto use_from_connect; } rc = seize_bchannel(call, CHANNEL_ANY, 0); // any channel if (rc < 0) { - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = no channel available during call-waiting\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = no channel available during call-waiting\n"); return -34; } - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = using channel %d\n", call->b_channel); + LOGP(DISDN, LOGL_DEBUG, " -> result = using channel %d\n", call->b_channel); call->b_exclusive = 1; // we are done /* activate channel given by remote */ @@ -593,13 +599,13 @@ int open_bchannel_out(call_t *call, unsigned int cmd, int channel, int exclusive if (call->state != ISDN_STATE_OUT_SETUP) return(0); - PDEBUG(DISDN, DEBUG_DEBUG, "Channel Selection (reply from outgoing call)\n"); + LOGP(DISDN, LOGL_DEBUG, "Channel Selection (reply from outgoing call)\n"); - PDEBUG(DISDN, DEBUG_DEBUG, " -> request = no channel\n"); - PDEBUG(DISDN, DEBUG_DEBUG, (channel>=0)?" -> reply = %d\n":" -> reply = (none)\n", channel); + LOGP(DISDN, LOGL_DEBUG, " -> request = no channel\n"); + LOGP(DISDN, LOGL_DEBUG, (channel>=0)?" -> reply = %d\n":" -> reply = (none)\n", channel); /* if first reply has no channel, we are done */ if (channel <= 0) { - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = no channel until connect\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = no channel until connect\n"); return(0); } @@ -607,10 +613,10 @@ int open_bchannel_out(call_t *call, unsigned int cmd, int channel, int exclusive use_from_connect: rc = seize_bchannel(call, channel, exclusive); if (rc < 0) { - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = replied channel not available\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = replied channel not available\n"); return -47; } - PDEBUG(DISDN, DEBUG_DEBUG, " -> result = replied channel accepted\n"); + LOGP(DISDN, LOGL_DEBUG, " -> result = replied channel accepted\n"); call->b_exclusive = 1; // we are done /* activate channel given by remote */ @@ -631,16 +637,16 @@ isdn_t *isdn_create(void) isdn_ep = calloc(1, sizeof(*isdn_ep)); if (!isdn_ep) { - PDEBUG(DISDN, DEBUG_ERROR, "No memory!\n"); + LOGP(DISDN, LOGL_ERROR, "No memory!\n"); abort(); } if (pthread_mutex_init(&isdn_ep->upqueue_lock, NULL)) { - PDEBUG(DISDN, DEBUG_ERROR, "Cannot init mutex!\n"); + LOGP(DISDN, LOGL_ERROR, "Cannot init mutex!\n"); abort(); } - PDEBUG(DISDN, DEBUG_DEBUG, "ISDN instance created\n"); + LOGP(DISDN, LOGL_DEBUG, "ISDN instance created\n"); return isdn_ep; } @@ -672,13 +678,13 @@ void isdn_destroy(isdn_t *isdn_ep) pthread_mutex_destroy(&isdn_ep->upqueue_lock); - timer_exit(&isdn_ep->l2establish_timer); + osmo_timer_del(&isdn_ep->l2establish_timer); - timer_exit(&isdn_ep->clock_timer); + osmo_timer_del(&isdn_ep->clock_timer); free(isdn_ep); - PDEBUG(DISDN, DEBUG_DEBUG, "ISDN instance destroyed\n"); + LOGP(DISDN, LOGL_DEBUG, "ISDN instance destroyed\n"); } static void clock_timeout(void *data); @@ -693,7 +699,7 @@ int isdn_initialize(isdn_t *isdn_ep, ph_socket_t *ph_socket, char law, const cha /* open mISDN socket */ rc = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE); if (rc < 0) { - PDEBUG(DISDN, DEBUG_ERROR, "Cannot open mISDN due to errno=%d:%s. (Does your Kernel support socket based mISDN? Protocol family is %d.)\n", errno, strerror(errno), PF_ISDN); + LOGP(DISDN, LOGL_ERROR, "Cannot open mISDN due to errno=%d:%s. (Does your Kernel support socket based mISDN? Protocol family is %d.)\n", errno, strerror(errno), PF_ISDN); return -errno; } isdn_ep->l2sock = rc; @@ -702,7 +708,7 @@ int isdn_initialize(isdn_t *isdn_ep, ph_socket_t *ph_socket, char law, const cha /* open mISDN user space */ rc = mISDN_base_create(&mui, ISDN_P_BASE); if (rc < 0) { - PDEBUG(DISDN, DEBUG_ERROR, "Cannot open mISDN due to errno=%d:%s. (Please fix!)\n", errno, strerror(errno)); + LOGP(DISDN, LOGL_ERROR, "Cannot open mISDN due to errno=%d:%s. (Please fix!)\n", errno, strerror(errno)); return -errno; } isdn_ep->l2inst = mui; @@ -735,7 +741,7 @@ int isdn_initialize(isdn_t *isdn_ep, ph_socket_t *ph_socket, char law, const cha } else default_in_channel(isdn_ep); - PDEBUG(DISDN, DEBUG_DEBUG, "ISDN instance initialized\n"); + LOGP(DISDN, LOGL_DEBUG, "ISDN instance initialized\n"); return 0; } @@ -747,7 +753,7 @@ void isdn_add_msn(isdn_t *isdn_ep, const char *msn) m = calloc(1, sizeof(*m) + strlen(msn) + 1); if (!m) { - PDEBUG(DISDN, DEBUG_ERROR, "No memory!\n"); + LOGP(DISDN, LOGL_ERROR, "No memory!\n"); abort(); } @@ -758,7 +764,7 @@ void isdn_add_msn(isdn_t *isdn_ep, const char *msn) strcpy(m->msn, msn); - PDEBUG(DISDN, DEBUG_DEBUG, "added MSDN number '%s'\n", msn); + LOGP(DISDN, LOGL_DEBUG, "added MSDN number '%s'\n", msn); } /* @@ -771,7 +777,7 @@ call_t *call_create(isdn_t *isdn_ep, int direction, int channel, int exclusive, call = calloc(1, sizeof(*call)); if (!call) { - PDEBUG(DISDN, DEBUG_ERROR, "No memory!\n"); + LOGP(DISDN, LOGL_ERROR, "No memory!\n"); abort(); } @@ -801,7 +807,7 @@ call_t *call_create(isdn_t *isdn_ep, int direction, int channel, int exclusive, if (channel > 0) // only if constructor was called with a channel resevation seize_bchannel(call, channel, exclusive); - PDEBUG(DISDN, DEBUG_DEBUG, "Created new call on port #%d:%s\n", isdn_ep->portnum, isdn_ep->portname); + LOGP(DISDN, LOGL_DEBUG, "Created new call on port #%d:%s\n", isdn_ep->portnum, isdn_ep->portname); return call; } @@ -855,7 +861,7 @@ void call_destroy(call_t *call) free(call); - PDEBUG(DISDN, DEBUG_DEBUG, "destroyed call instance\n"); + LOGP(DISDN, LOGL_DEBUG, "destroyed call instance\n"); } /* @@ -871,7 +877,7 @@ static void im_control(int sock, uint32_t op, uint32_t channel, uint32_t p1, uin if (sock < 0) return; - PDEBUG(DISDN, DEBUG_DEBUG, "sending IMCTRLREQ 0x%08x, %d, 0x%02x, 0x%02x\n", op, channel, p1, p2); + LOGP(DISDN, LOGL_DEBUG, "sending IMCTRLREQ 0x%08x, %d, 0x%02x, 0x%02x\n", op, channel, p1, p2); cq.op = op; cq.channel = channel; @@ -879,7 +885,7 @@ static void im_control(int sock, uint32_t op, uint32_t channel, uint32_t p1, uin cq.p2 = p2; rc = ioctl(sock, IMCTRLREQ, &cq); if (rc < 0) - PDEBUG(DISDN, DEBUG_ERROR, "Failed to send IMCTRLREQ to socket %d (errno=%d:%s)\n", sock, errno, strerror(errno)); + LOGP(DISDN, LOGL_ERROR, "Failed to send IMCTRLREQ to socket %d (errno=%d:%s)\n", sock, errno, strerror(errno)); } static int bchannel_kernel_sock_receive_cb(struct osmo_fd *ofd, unsigned int when); @@ -895,17 +901,17 @@ static int bchannel_create(isdn_t *isdn_ep, int index) if (isdn_ep->l2sock) { if (isdn_ep->b_sock[index].ofd.fd > 0) { - PDEBUG(DISDN, DEBUG_ERROR, "Socket already created for index %d\n", index); + LOGP(DISDN, LOGL_ERROR, "Socket already created for index %d\n", index); return -EIO; } /* open socket */ if (isdn_ep->b_mode[index] == B_MODE_HDLC) { - PDEBUG(DISDN, DEBUG_NOTICE, "Use B-Channel with HDLC!!!\n"); + LOGP(DISDN, LOGL_NOTICE, "Use B-Channel with HDLC!!!\n"); } rc = socket(PF_ISDN, SOCK_DGRAM, (isdn_ep->b_mode[index] == B_MODE_HDLC) ? ISDN_P_B_HDLC : ISDN_P_B_RAW); if (rc < 0) { - PDEBUG(DISDN, DEBUG_ERROR, "Failed to open bchannel-socket for index %d with mISDN-DSP layer. Did you load mISDN_dsp.ko?\n", index); + LOGP(DISDN, LOGL_ERROR, "Failed to open bchannel-socket for index %d with mISDN-DSP layer. Did you load mISDN_dsp.ko?\n", index); return(0); } isdn_ep->b_sock[index].ofd.fd = rc; @@ -924,7 +930,7 @@ static int bchannel_create(isdn_t *isdn_ep, int index) addr.channel = channel; rc = bind(isdn_ep->b_sock[index].ofd.fd, (struct sockaddr *)&addr, sizeof(addr)); if (rc < 0) { - PDEBUG(DISDN, DEBUG_ERROR, "Failed to bind bchannel-socket for index %d with mISDN-DSP layer (errno=%d). Did you load mISDN_dsp.ko?\n", index, errno); + LOGP(DISDN, LOGL_ERROR, "Failed to bind bchannel-socket for index %d with mISDN-DSP layer (errno=%d). Did you load mISDN_dsp.ko?\n", index, errno); /* unregister and close */ osmo_fd_unregister(&isdn_ep->b_sock[index].ofd); close(isdn_ep->b_sock[index].ofd.fd); @@ -932,7 +938,7 @@ static int bchannel_create(isdn_t *isdn_ep, int index) } } - PDEBUG(DISDN, DEBUG_DEBUG, "created socket #%d for B-channel %d\n", isdn_ep->b_sock[index].ofd.fd, channel); + LOGP(DISDN, LOGL_DEBUG, "created socket #%d for B-channel %d\n", isdn_ep->b_sock[index].ofd.fd, channel); return 0; } @@ -952,19 +958,19 @@ static void bchannel_activate(isdn_t *isdn_ep, int index, int activate, int time act.id = 0; rc = sendto(isdn_ep->b_sock[index].ofd.fd, &act, MISDN_HEADER_LEN, 0, NULL, 0); if (rc < 0) - PDEBUG(DISDN, DEBUG_ERROR, "Failed to send to socket #%d, of B-channel %d\n", isdn_ep->b_sock[index].ofd.fd, channel); + LOGP(DISDN, LOGL_ERROR, "Failed to send to socket #%d, of B-channel %d\n", isdn_ep->b_sock[index].ofd.fd, channel); } if (isdn_ep->l2inst) { uint8_t mode = PH_MODE_TRANS; if (isdn_ep->b_mode[index] == B_MODE_HDLC) { - PDEBUG(DISDN, DEBUG_NOTICE, "Use B-Channel with HDLC!!!\n"); + LOGP(DISDN, LOGL_NOTICE, "Use B-Channel with HDLC!!!\n"); mode = PH_MODE_HDLC; } ph_socket_tx_msg(isdn_ep->ph_socket, channel, (activate) ? PH_PRIM_ACT_REQ : PH_PRIM_DACT_REQ, &mode, 1); } - PDEBUG(DISDN, DEBUG_DEBUG, "%s B-channel %d%s\n", (activate) ? "activating" : "deactivating", channel, (timeout) ? " after timeout recovery" : ""); + LOGP(DISDN, LOGL_DEBUG, "%s B-channel %d%s\n", (activate) ? "activating" : "deactivating", channel, (timeout) ? " after timeout recovery" : ""); /* reset rx buffer */ isdn_ep->b_buffer_pos[index] = 0; @@ -1023,7 +1029,7 @@ static void bchannel_destroy(isdn_t *isdn_ep, int index) if (isdn_ep->b_sock[index].ofd.fd <= 0) return; - PDEBUG(DISDN, DEBUG_DEBUG, "destroyed socket #%d for B-channel %d\n", isdn_ep->b_sock[index].ofd.fd, channel); + LOGP(DISDN, LOGL_DEBUG, "destroyed socket #%d for B-channel %d\n", isdn_ep->b_sock[index].ofd.fd, channel); /* unregister and close */ osmo_fd_unregister(&isdn_ep->b_sock[index].ofd); @@ -1032,7 +1038,7 @@ static void bchannel_destroy(isdn_t *isdn_ep, int index) } if (isdn_ep->l2inst) { - PDEBUG(DISDN, DEBUG_DEBUG, "destroyed B-channel %d\n", channel); + LOGP(DISDN, LOGL_DEBUG, "destroyed B-channel %d\n", channel); } } @@ -1093,13 +1099,13 @@ void bchannel_event(isdn_t *isdn_ep, int index, int event) call = isdn_ep->b_call[index]; state = isdn_ep->b_state[index]; - PDEBUG(DISDN, DEBUG_DEBUG, "handling event %d at state %d for B-channel %d\n", event, state, channel); + LOGP(DISDN, LOGL_DEBUG, "handling event %d at state %d for B-channel %d\n", event, state, channel); switch(event) { case B_EVENT_USE: /* call must be linked in order to allow activation */ if (!call) { - PDEBUG(DISDN, DEBUG_ERROR, "bchannel must be linked to a call instance\n"); + LOGP(DISDN, LOGL_ERROR, "bchannel must be linked to a call instance\n"); abort(); } switch(state) { @@ -1120,7 +1126,7 @@ void bchannel_event(isdn_t *isdn_ep, int index, int event) /* problems that might occur: * B_EVENT_USE is received when channel already in use. */ - PDEBUG(DISDN, DEBUG_ERROR, "Illegal event %d at state %d, please correct.\n", event, state); + LOGP(DISDN, LOGL_ERROR, "Illegal event %d at state %d, please correct.\n", event, state); } break; @@ -1145,13 +1151,13 @@ void bchannel_event(isdn_t *isdn_ep, int index, int event) break; default: - PDEBUG(DISDN, DEBUG_ERROR, "Illegal event %d at state %d, please correct.\n", event, state); + LOGP(DISDN, LOGL_ERROR, "Illegal event %d at state %d, please correct.\n", event, state); } break; case B_EVENT_DROP: if (!call) { - PDEBUG(DISDN, DEBUG_ERROR, "bchannel must be linked to a call instance\n"); + LOGP(DISDN, LOGL_ERROR, "bchannel must be linked to a call instance\n"); abort(); } switch(state) { @@ -1175,7 +1181,7 @@ void bchannel_event(isdn_t *isdn_ep, int index, int event) break; default: - PDEBUG(DISDN, DEBUG_ERROR, "Illegal event %d at state %d, please correct.\n", event, state); + LOGP(DISDN, LOGL_ERROR, "Illegal event %d at state %d, please correct.\n", event, state); } break; @@ -1200,7 +1206,7 @@ void bchannel_event(isdn_t *isdn_ep, int index, int event) break; default: - PDEBUG(DISDN, DEBUG_ERROR, "Illegal event %d at state %d, please correct.\n", event, state); + LOGP(DISDN, LOGL_ERROR, "Illegal event %d at state %d, please correct.\n", event, state); } break; @@ -1222,19 +1228,19 @@ void bchannel_event(isdn_t *isdn_ep, int index, int event) break; default: - PDEBUG(DISDN, DEBUG_ERROR, "Illegal event %d at state %d, please correct.\n", event, state); + LOGP(DISDN, LOGL_ERROR, "Illegal event %d at state %d, please correct.\n", event, state); } break; default: - PDEBUG(DISDN, DEBUG_ERROR, "Illegal event %d, please correct.\n", event); + LOGP(DISDN, LOGL_ERROR, "Illegal event %d, please correct.\n", event); } isdn_ep->b_state[index] = state; if (timer == 0) - timer_stop(&isdn_ep->b_timer[index]); + osmo_timer_del(&isdn_ep->b_timer[index]); else if (timer > 0) - timer_start(&isdn_ep->b_timer[index], timer); + osmo_timer_schedule(&isdn_ep->b_timer[index], timer,0); } static void bchannel_rx_tx(isdn_t *isdn_ep, int index, struct mISDNhead *hh, unsigned char *data, int len); @@ -1252,7 +1258,7 @@ static int bchannel_kernel_sock_receive_cb(struct osmo_fd *ofd, unsigned int whe int rc; if (!(when & OSMO_FD_READ)) { - PDEBUG(DISDN, DEBUG_ERROR, "this should never happen!\n"); + LOGP(DISDN, LOGL_ERROR, "this should never happen!\n"); return 0; } @@ -1260,11 +1266,11 @@ static int bchannel_kernel_sock_receive_cb(struct osmo_fd *ofd, unsigned int whe if (rc < 0) { if (errno == EAGAIN) return 0; - PDEBUG(DISDN, DEBUG_ERROR, "read error B-channel data (socket #%d errno=%d:%s)\n", ofd->fd, errno, strerror(errno)); + LOGP(DISDN, LOGL_ERROR, "read error B-channel data (socket #%d errno=%d:%s)\n", ofd->fd, errno, strerror(errno)); return 0; } if (rc < (int)MISDN_HEADER_LEN) { - PDEBUG(DISDN, DEBUG_ERROR, "read short frame, got %d, expected %d\n", rc, (int)MISDN_HEADER_LEN); + LOGP(DISDN, LOGL_ERROR, "read short frame, got %d, expected %d\n", rc, (int)MISDN_HEADER_LEN); return 0; } switch (hh->prim) { @@ -1283,14 +1289,14 @@ static int bchannel_kernel_sock_receive_cb(struct osmo_fd *ofd, unsigned int whe if (isdn_ep->b_call[index]) bchannel_rx_tx(isdn_ep, index, hh, buffer + MISDN_HEADER_LEN, rc - MISDN_HEADER_LEN); else - PDEBUG(DISDN, DEBUG_DEBUG, "b-channel is not associated to a call (channel %d), ignoring.\n", channel); + LOGP(DISDN, LOGL_DEBUG, "b-channel is not associated to a call (channel %d), ignoring.\n", channel); break; case PH_ACTIVATE_IND: case DL_ESTABLISH_IND: case PH_ACTIVATE_CNF: case DL_ESTABLISH_CNF: - PDEBUG(DISDN, DEBUG_DEBUG, "DL_ESTABLISH confirm: bchannel is now activated (channel %d).\n", channel); + LOGP(DISDN, LOGL_DEBUG, "DL_ESTABLISH confirm: bchannel is now activated (channel %d).\n", channel); bchannel_event(isdn_ep, index, B_EVENT_ACTIVATED); break; @@ -1298,12 +1304,12 @@ static int bchannel_kernel_sock_receive_cb(struct osmo_fd *ofd, unsigned int whe case DL_RELEASE_IND: case PH_DEACTIVATE_CNF: case DL_RELEASE_CNF: - PDEBUG(DISDN, DEBUG_DEBUG, "DL_RELEASE confirm: bchannel is now de-activated (channel %d).\n", channel); + LOGP(DISDN, LOGL_DEBUG, "DL_RELEASE confirm: bchannel is now de-activated (channel %d).\n", channel); bchannel_event(isdn_ep, index, B_EVENT_DEACTIVATED); break; default: - PDEBUG(DISDN, DEBUG_ERROR, "child message not handled: prim(0x%x) channel(%d) msg->len(%d)\n", hh->prim, channel, rc - (int)MISDN_HEADER_LEN); + LOGP(DISDN, LOGL_ERROR, "child message not handled: prim(0x%x) channel(%d) msg->len(%d)\n", hh->prim, channel, rc - (int)MISDN_HEADER_LEN); } return 1; @@ -1328,14 +1334,14 @@ void bchannel_ph_sock_receive(void *priv, int channel, uint8_t prim, uint8_t *da struct mISDNhead hh = { .prim = PH_DATA_IND }; bchannel_rx_tx(isdn_ep, index, &hh, data, length); } else - PDEBUG(DISDN, DEBUG_DEBUG, "b-channel is not associated to a call (channel %d), ignoring.\n", channel); + LOGP(DISDN, LOGL_DEBUG, "b-channel is not associated to a call (channel %d), ignoring.\n", channel); break; case PH_PRIM_ACT_IND: - PDEBUG(DISDN, DEBUG_DEBUG, "PH_PRIM_ACT_IND: bchannel is now activated (channel %d).\n", channel); + LOGP(DISDN, LOGL_DEBUG, "PH_PRIM_ACT_IND: bchannel is now activated (channel %d).\n", channel); bchannel_event(isdn_ep, index, B_EVENT_ACTIVATED); break; case PH_PRIM_DACT_IND: - PDEBUG(DISDN, DEBUG_DEBUG, "PH_PRIM_DACT_IND: bchannel is now deactivated (channel %d).\n", channel); + LOGP(DISDN, LOGL_DEBUG, "PH_PRIM_DACT_IND: bchannel is now deactivated (channel %d).\n", channel); bchannel_event(isdn_ep, index, B_EVENT_DEACTIVATED); break; } @@ -1405,7 +1411,7 @@ int seize_bchannel(call_t *call, int channel, int exclusive) return -34; /* no free channel */ seize: - PDEBUG(DISDN, DEBUG_DEBUG, "seizing bchannel %d (index %d)\n", channel, index); + LOGP(DISDN, LOGL_DEBUG, "seizing bchannel %d (index %d)\n", channel, index); /* link Port, set parameters */ isdn_ep->b_call[index] = call; @@ -1445,7 +1451,7 @@ void drop_bchannel(call_t *call) if (!call->b_channel) return; - PDEBUG(DISDN, DEBUG_DEBUG, "dropping bchannel %d (index %d)\n", call->b_channel, call->b_index); + LOGP(DISDN, LOGL_DEBUG, "dropping bchannel %d (index %d)\n", call->b_channel, call->b_index); if (isdn_ep->b_state[call->b_index] != B_STATE_IDLE) bchannel_event(isdn_ep, call->b_index, B_EVENT_DROP); @@ -1573,7 +1579,7 @@ static void bchannel_rx_tx(isdn_t *isdn_ep, int index, struct mISDNhead *hh, uns if (hh->prim == PH_CONTROL_IND) { if (len < 4) { - PDEBUG(DISDN, DEBUG_ERROR, "SHORT READ OF PH_CONTROL INDICATION\n"); + LOGP(DISDN, LOGL_ERROR, "SHORT READ OF PH_CONTROL INDICATION\n"); return; } return; @@ -1583,12 +1589,12 @@ static void bchannel_rx_tx(isdn_t *isdn_ep, int index, struct mISDNhead *hh, uns return; if (!call) { - PDEBUG(DISDN, DEBUG_DEBUG, "Dropping b-channel data from channel without call.\n"); + LOGP(DISDN, LOGL_DEBUG, "Dropping b-channel data from channel without call.\n"); return; } if (isdn_ep->b_state[index] != B_STATE_ACTIVE) { - PDEBUG(DISDN, DEBUG_DEBUG, "Dropping b-channel data from inactive channel.\n"); + LOGP(DISDN, LOGL_DEBUG, "Dropping b-channel data from inactive channel.\n"); return; } @@ -1604,7 +1610,7 @@ static void bchannel_rx_tx(isdn_t *isdn_ep, int index, struct mISDNhead *hh, uns if (call->b_rx_time) { double elapsed = now - call->b_rx_time; if ((int)(elapsed * 8000.0) - len > len / 4) - PDEBUG(DISDN, DEBUG_DEBUG, "Data received %d samples, time elapsed %d samples\n", len, (int)(elapsed * 8000.0)); + LOGP(DISDN, LOGL_DEBUG, "Data received %d samples, time elapsed %d samples\n", len, (int)(elapsed * 8000.0)); } call->b_rx_time = now; @@ -1630,7 +1636,7 @@ static void bchannel_rx_tx(isdn_t *isdn_ep, int index, struct mISDNhead *hh, uns if (!call->b_transmitting) { unsigned char init_buf[MISDN_HEADER_LEN + len]; - PDEBUG(DISDN, DEBUG_DEBUG, "First received b-channel data, filling FIFO with two chunks of %d bytes.\n", len); + LOGP(DISDN, LOGL_DEBUG, "First received b-channel data, filling FIFO with two chunks of %d bytes.\n", len); memcpy(init_buf, frm, MISDN_HEADER_LEN); memset(init_buf + MISDN_HEADER_LEN, 0xff, len); /* forward to interface */ @@ -1647,7 +1653,7 @@ static void bchannel_rx_tx(isdn_t *isdn_ep, int index, struct mISDNhead *hh, uns else rc = send(call->isdn_ep->b_sock[call->b_index].ofd.fd, buf, MISDN_HEADER_LEN + len, 0); if (rc < 0) - PDEBUG(DISDN, DEBUG_ERROR, "Write error B-channel data (socket #%d errno=%d:%s)\n", call->isdn_ep->b_sock[call->b_index].ofd.fd, errno, strerror(errno)); + LOGP(DISDN, LOGL_ERROR, "Write error B-channel data (socket #%d errno=%d:%s)\n", call->isdn_ep->b_sock[call->b_index].ofd.fd, errno, strerror(errno)); } /* receive confirm from bchannel */ @@ -1656,7 +1662,7 @@ static void bchannel_confirm(isdn_t *isdn_ep, int index) call_t *call = isdn_ep->b_call[index]; if (!call) { - PDEBUG(DISDN, DEBUG_DEBUG, "Ignoring b-channel confirm of channel without call.\n"); + LOGP(DISDN, LOGL_DEBUG, "Ignoring b-channel confirm of channel without call.\n"); return; } @@ -1664,7 +1670,7 @@ static void bchannel_confirm(isdn_t *isdn_ep, int index) if (call->b_rx_time) { double elapsed = now - call->b_rx_time; if (elapsed > 4) - PDEBUG(DISDN, DEBUG_DEBUG, "Data confirmed, time elapsed %d samples\n", (int)(elapsed * 8000.0)); + LOGP(DISDN, LOGL_DEBUG, "Data confirmed, time elapsed %d samples\n", (int)(elapsed * 8000.0)); } } @@ -1717,7 +1723,7 @@ int do_layer3(struct mlayer3 *ml3, unsigned int cmd, unsigned int pid, struct l3 if (!l3m) { l3m = alloc_l3_msg(); if (!l3m) { - PDEBUG(DISDN, DEBUG_ERROR, "No memory for layer 3 message\n"); + LOGP(DISDN, LOGL_ERROR, "No memory for layer 3 message\n"); abort(); } } @@ -1786,7 +1792,7 @@ int isdn_open(isdn_t *isdn_ep) isdn_ep->upqueue_initialized = 1; rc = pipe(isdn_ep->upqueue_pipe); if (rc < 0) { - PDEBUG(DISDN, DEBUG_ERROR, "Failed to create pipe errno=%d:%s. (Please fix!)\n", errno, strerror(errno)); + LOGP(DISDN, LOGL_ERROR, "Failed to create pipe errno=%d:%s. (Please fix!)\n", errno, strerror(errno)); goto error; } isdn_ep->upqueue_ofd.fd = isdn_ep->upqueue_pipe[0]; @@ -1813,24 +1819,24 @@ int isdn_open(isdn_t *isdn_ep) if (isdn_ep->l2inst) rc = mISDN_base_ioctl(isdn_ep->l2inst, IMGETCOUNT, &cnt); if (rc < 0) { - PDEBUG(DISDN, DEBUG_ERROR, "Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed errno = %d)\n", errno); + LOGP(DISDN, LOGL_ERROR, "Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed errno = %d)\n", errno); goto error; } if (cnt <= 0) { - PDEBUG(DISDN, DEBUG_ERROR, "Found no card. Please be sure to load card drivers.\n"); + LOGP(DISDN, LOGL_ERROR, "Found no card. Please be sure to load card drivers.\n"); goto error; } if (portnum < 0) { portnum = mISDN_getportbyname(isdn_ep, cnt, portname); if (portnum < 0) { - PDEBUG(DISDN, DEBUG_ERROR, "Port name '%s' not found, use 'misdn_info' tool to list all existing ports.\n", portname); + LOGP(DISDN, LOGL_ERROR, "Port name '%s' not found, use 'misdn_info' tool to list all existing ports.\n", portname); goto error; } // note: 'portnum' has now the port number } if (portnum > cnt || portnum < 0) { - PDEBUG(DISDN, DEBUG_ERROR, "Port (%d) given at 'ports' (options.conf) is out of existing port range (%d-%d)\n", portnum, 0, cnt); + LOGP(DISDN, LOGL_ERROR, "Port (%d) given at 'ports' (options.conf) is out of existing port range (%d-%d)\n", portnum, 0, cnt); goto error; } @@ -1842,7 +1848,7 @@ int isdn_open(isdn_t *isdn_ep) if (isdn_ep->l2inst) rc = mISDN_base_ioctl(isdn_ep->l2inst, IMGETDEVINFO, &devinfo); if (rc < 0) { - PDEBUG(DISDN, DEBUG_ERROR, "Cannot get device information for port %d. (ioctl IMGETDEVINFO failed errno=%d)\n", portnum, errno); + LOGP(DISDN, LOGL_ERROR, "Cannot get device information for port %d. (ioctl IMGETDEVINFO failed errno=%d)\n", portnum, errno); goto error; } if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0)) { @@ -1862,19 +1868,19 @@ int isdn_open(isdn_t *isdn_ep) nt = 1; } if (force_nt && !nt) { - PDEBUG(DISDN, DEBUG_ERROR, "Port %d does not support NT-mode\n", portnum); + LOGP(DISDN, LOGL_ERROR, "Port %d does not support NT-mode\n", portnum); goto error; } if (bri && pri) { - PDEBUG(DISDN, DEBUG_ERROR, "Port %d supports BRI and PRI?? What kind of controller is that?. (Can't use this!)\n", portnum); + LOGP(DISDN, LOGL_ERROR, "Port %d supports BRI and PRI?? What kind of controller is that?. (Can't use this!)\n", portnum); goto error; } if (!bri && !pri) { - PDEBUG(DISDN, DEBUG_ERROR, "Port %d does not support BRI nor PRI\n", portnum); + LOGP(DISDN, LOGL_ERROR, "Port %d does not support BRI nor PRI\n", portnum); goto error; } if (!nt && !te) { - PDEBUG(DISDN, DEBUG_ERROR, "Port %d does not support NT-mode nor TE-mode!\n", portnum); + LOGP(DISDN, LOGL_ERROR, "Port %d does not support NT-mode nor TE-mode!\n", portnum); goto error; } /* set NT by turning off TE */ @@ -1887,28 +1893,28 @@ int isdn_open(isdn_t *isdn_ep) /* check for continuous channelmap with no bchannel on slot 16 */ if (test_channelmap(0, devinfo.channelmap)) { - PDEBUG(DISDN, DEBUG_ERROR, "Port %d provides channel 0, but we cannot access it!\n", portnum); + LOGP(DISDN, LOGL_ERROR, "Port %d provides channel 0, but we cannot access it!\n", portnum); goto error; } i = 1; while(i < (int)devinfo.nrbchan + 1) { if (i == 16) { if (test_channelmap(i, devinfo.channelmap)) { - PDEBUG(DISDN, DEBUG_ERROR, "Port %d provides bchannel 16. Please upgrade mISDN, if this port is mISDN loopback interface.\n", portnum); + LOGP(DISDN, LOGL_ERROR, "Port %d provides bchannel 16. Please upgrade mISDN, if this port is mISDN loopback interface.\n", portnum); goto error; } } else { if (!test_channelmap(i, devinfo.channelmap)) { - PDEBUG(DISDN, DEBUG_ERROR, "Port %d has no channel on slot %d!\n", portnum, i); + LOGP(DISDN, LOGL_ERROR, "Port %d has no channel on slot %d!\n", portnum, i); goto error; } } i++; } - timer_init(&isdn_ep->clock_timer, clock_timeout, isdn_ep); + osmo_timer_setup(&isdn_ep->clock_timer, clock_timeout, isdn_ep); - timer_init(&isdn_ep->l2establish_timer, l2establish_timeout, isdn_ep); + osmo_timer_setup(&isdn_ep->l2establish_timer, l2establish_timeout, isdn_ep); isdn_ep->l1link = -1; isdn_ep->l2link = -1; @@ -1947,7 +1953,7 @@ int isdn_open(isdn_t *isdn_ep) /* open layer 3 */ isdn_ep->ml3 = open_layer3(portnum, protocol, prop, do_layer3, isdn_ep); if (!isdn_ep->ml3) { - PDEBUG(DISDN, DEBUG_ERROR, "open_layer3() failed for port %d\n", portnum); + LOGP(DISDN, LOGL_ERROR, "open_layer3() failed for port %d\n", portnum); goto error; } @@ -1965,25 +1971,25 @@ int isdn_open(isdn_t *isdn_ep) isdn_ep->bridge_possible = 1; isdn_ep->bridge_cardnum = strtoul(isdn_ep->portname + 7, NULL, 10); isdn_ep->bridge_portnum = portnum; - PDEBUG(DISDN, DEBUG_INFO, "Port can use HFC bridge of card %d.\n", isdn_ep->bridge_cardnum); + LOGP(DISDN, LOGL_INFO, "Port can use HFC bridge of card %d.\n", isdn_ep->bridge_cardnum); } isdn_ep->ntmode = nt; isdn_ep->pri = pri; isdn_ep->ptp = ptp; isdn_ep->l1hold = l1hold; isdn_ep->l2hold = l2hold; - PDEBUG(DISDN, DEBUG_DEBUG, "Port has %d b-channels.\n", isdn_ep->b_num); + LOGP(DISDN, LOGL_DEBUG, "Port has %d b-channels.\n", isdn_ep->b_num); for (i = 0; i < isdn_ep->b_num; i++) { isdn_ep->b_state[i] = B_STATE_IDLE; - timer_init(&isdn_ep->b_timer[i], b_timer_timeout, &isdn_ep->b_timer_inst); + osmo_timer_setup(&isdn_ep->b_timer[i], b_timer_timeout, &isdn_ep->b_timer_inst); isdn_ep->b_timer_inst[i].isdn_ep = isdn_ep; isdn_ep->b_timer_inst[i].index = i; } /* if ptp, pull up the link */ if (isdn_ep->l2hold && (isdn_ep->ptp || !isdn_ep->ntmode)) { - PDEBUG(DISDN, DEBUG_DEBUG, "reqzest layer 2 to be establised for tei 0\n"); - timer_start(&isdn_ep->l2establish_timer, 5.0); /* 5 seconds */ + LOGP(DISDN, LOGL_DEBUG, "reqzest layer 2 to be establised for tei 0\n"); + osmo_timer_schedule(&isdn_ep->l2establish_timer, 5,0); /* 5 seconds */ } /* for nt-mode ptmp the link is always up */ @@ -2007,11 +2013,11 @@ void isdn_close(isdn_t *isdn_ep) for (i = 0; i < isdn_ep->b_num; i++) { if (isdn_ep->b_sock[i].ofd.fd > 0) { bchannel_destroy(isdn_ep, i); - PDEBUG(DISDN, DEBUG_DEBUG, "freeing %s port %s bchannel (index %d).\n", (isdn_ep->ntmode) ? "NT" : "TE", isdn_ep->portname, i); + LOGP(DISDN, LOGL_DEBUG, "freeing %s port %s bchannel (index %d).\n", (isdn_ep->ntmode) ? "NT" : "TE", isdn_ep->portname, i); } - timer_exit(&isdn_ep->b_timer[i]); + osmo_timer_del(&isdn_ep->b_timer[i]); } - timer_exit(&isdn_ep->l2establish_timer); + osmo_timer_del(&isdn_ep->l2establish_timer); /* close layer 3, if open */ if (isdn_ep->ml3) { @@ -2070,14 +2076,14 @@ again: switch(l3m->type) { case MPH_ACTIVATE_IND: if (isdn_ep->l1link != 1) { - PDEBUG(DISDN, DEBUG_INFO, "layer 1 becomes active\n"); + LOGP(DISDN, LOGL_INFO, "layer 1 becomes active\n"); isdn_ep->l1link = 1; } break; case MPH_DEACTIVATE_IND: if (isdn_ep->l1link != 0) { - PDEBUG(DISDN, DEBUG_INFO, "layer 1 becomes inactive\n"); + LOGP(DISDN, LOGL_INFO, "layer 1 becomes inactive\n"); isdn_ep->l1link = 0; } break; @@ -2085,63 +2091,63 @@ again: case MPH_INFORMATION_IND: switch (l3m->pid) { case L1_SIGNAL_LOS_ON: - PDEBUG(DISDN, DEBUG_DEBUG, "received LOS\n"); + LOGP(DISDN, LOGL_DEBUG, "received LOS\n"); isdn_ep->los = 1; break; case L1_SIGNAL_LOS_OFF: - PDEBUG(DISDN, DEBUG_DEBUG, "LOS is gone\n"); + LOGP(DISDN, LOGL_DEBUG, "LOS is gone\n"); isdn_ep->los = 0; break; case L1_SIGNAL_AIS_ON: - PDEBUG(DISDN, DEBUG_DEBUG, "received AIS\n"); + LOGP(DISDN, LOGL_DEBUG, "received AIS\n"); isdn_ep->ais = 1; break; case L1_SIGNAL_AIS_OFF: - PDEBUG(DISDN, DEBUG_DEBUG, "AIS is gone\n"); + LOGP(DISDN, LOGL_DEBUG, "AIS is gone\n"); isdn_ep->ais = 0; break; case L1_SIGNAL_RDI_ON: - PDEBUG(DISDN, DEBUG_DEBUG, "received RDI\n"); + LOGP(DISDN, LOGL_DEBUG, "received RDI\n"); isdn_ep->rdi = 1; break; case L1_SIGNAL_RDI_OFF: - PDEBUG(DISDN, DEBUG_DEBUG, "RDI is gone\n"); + LOGP(DISDN, LOGL_DEBUG, "RDI is gone\n"); isdn_ep->rdi = 0; break; case L1_SIGNAL_SLIP_TX: isdn_ep->slip_tx++; - PDEBUG(DISDN, DEBUG_DEBUG, "received TX slip #%d\n", isdn_ep->slip_tx); + LOGP(DISDN, LOGL_DEBUG, "received TX slip #%d\n", isdn_ep->slip_tx); break; case L1_SIGNAL_SLIP_RX: isdn_ep->slip_rx++; - PDEBUG(DISDN, DEBUG_DEBUG, "received RX slip #%d\n", isdn_ep->slip_rx); + LOGP(DISDN, LOGL_DEBUG, "received RX slip #%d\n", isdn_ep->slip_rx); break; } break; case MT_L2ESTABLISH: - PDEBUG(DISDN, DEBUG_INFO, "layer 2 becomes active (tei = %d)\n", l3m->pid); + LOGP(DISDN, LOGL_INFO, "layer 2 becomes active (tei = %d)\n", l3m->pid); isdn_ep->l2link = 1; if (l3m->pid < 128) isdn_ep->l2mask[l3m->pid >> 3] |= (1 << (l3m->pid & 7)); if ((!isdn_ep->ntmode || isdn_ep->ptp) && l3m->pid < 127) { - if (timer_running(&isdn_ep->l2establish_timer)) - timer_stop(&isdn_ep->l2establish_timer); + if (osmo_timer_pending(&isdn_ep->l2establish_timer)) + osmo_timer_del(&isdn_ep->l2establish_timer); } break; case MT_L2RELEASE: if (l3m->pid < 128) isdn_ep->l2mask[l3m->pid >> 3] &= ~(1 << (l3m->pid & 7)); - if (!timer_running(&isdn_ep->l2establish_timer)) { - PDEBUG(DISDN, DEBUG_INFO, "layer 2 becomes inactive (tei = %d)\n", l3m->pid); + if (!osmo_timer_pending(&isdn_ep->l2establish_timer)) { + LOGP(DISDN, LOGL_INFO, "layer 2 becomes inactive (tei = %d)\n", l3m->pid); /* down if not nt-ptmp */ if (!isdn_ep->ntmode || isdn_ep->ptp) isdn_ep->l2link = 0; } if ((!isdn_ep->ntmode || isdn_ep->ptp) && l3m->pid < 127) { - if (!timer_running(&isdn_ep->l2establish_timer) && isdn_ep->l2hold) { - timer_start(&isdn_ep->l2establish_timer, 5.0); /* 5 seconds */ + if (!osmo_timer_pending(&isdn_ep->l2establish_timer) && isdn_ep->l2hold) { + osmo_timer_schedule(&isdn_ep->l2establish_timer, 5,0); /* 5 seconds */ isdn_ep->ml3->to_layer3(isdn_ep->ml3, MT_L2ESTABLISH, 0, NULL); } } @@ -2164,9 +2170,9 @@ static void l2establish_timeout(void *data) isdn_t *isdn_ep = data; if (isdn_ep->l2hold && (isdn_ep->ptp || !isdn_ep->ntmode)) { - PDEBUG(DISDN, DEBUG_DEBUG, "the L2 establish timer expired, we try to establish the link portnum=%d.\n", isdn_ep->portnum); + LOGP(DISDN, LOGL_DEBUG, "the L2 establish timer expired, we try to establish the link portnum=%d.\n", isdn_ep->portnum); isdn_ep->ml3->to_layer3(isdn_ep->ml3, MT_L2ESTABLISH, 0, NULL); - timer_start(&isdn_ep->l2establish_timer, 5.0); /* 5 seconds */ + osmo_timer_schedule(&isdn_ep->l2establish_timer, 5,0); /* 5 seconds */ } } @@ -2222,7 +2228,7 @@ static void clock_timeout(void *data) /* if there is too much jitter */ if (isdn_ep->last_time_clock < now) isdn_ep->last_time_clock = now; - timer_start(&isdn_ep->clock_timer, isdn_ep->last_time_clock - now); + osmo_timer_schedule(&isdn_ep->clock_timer, 0,(isdn_ep->last_time_clock - now) * 1000000); } } @@ -2231,12 +2237,12 @@ void enable_hold_clock(isdn_t *isdn_ep) double now; /* already running, so keep running without restart */ - if (timer_running(&isdn_ep->clock_timer)) + if (osmo_timer_pending(&isdn_ep->clock_timer)) return; /* start timer to wait for 20ms */ now = get_time(); isdn_ep->last_time_clock = now + CHUNK_DURATION; - timer_start(&isdn_ep->clock_timer, CHUNK_DURATION); + osmo_timer_schedule(&isdn_ep->clock_timer, 0,CHUNK_DURATION * 1000000); } diff --git a/src/isdn/isdn.h b/src/isdn/isdn.h index 5ca723e..7f92298 100644 --- a/src/isdn/isdn.h +++ b/src/isdn/isdn.h @@ -1,9 +1,9 @@ #include -#include "../libtimer/timer.h" -#include "../libselect/select.h" -#include "../libosmocc/endpoint.h" -#include "../libosmocc/helper.h" +#include +#include +#include +#include #include "../libsample/sample.h" #include "../libjitter/jitter.h" #include "../libph_socket/ph_socket.h" @@ -113,14 +113,14 @@ typedef struct isdn { int los, ais, rdi, slip_rx, slip_tx; int l1link; /* current state */ int l2link; /* current state */ - struct timer l2establish_timer; + struct osmo_timer_list l2establish_timer; int b_num; int b_reserved; int b_mode[128]; int b_state[128]; struct isdn_b_sock b_sock[128]; struct call_list *b_call[128]; - struct timer b_timer[128]; + struct osmo_timer_list b_timer[128]; struct b_timer_inst b_timer_inst[128]; uint8_t b_buffer[128][160]; int b_buffer_pos[128]; @@ -132,7 +132,7 @@ typedef struct isdn { int bridge_portnum; /* clock for tone on hold */ - struct timer clock_timer; + struct osmo_timer_list clock_timer; double last_time_clock; } isdn_t; diff --git a/src/isdn/main.c b/src/isdn/main.c index e4e9725..ed9a59a 100644 --- a/src/isdn/main.c +++ b/src/isdn/main.c @@ -25,9 +25,10 @@ #include #include #include -#include "../libdebug/debug.h" +#include +#include "../liblogging/logging.h" #include "../liboptions/options.h" -#include "../libg711/g711.h" +#include #include #include "isdn.h" #include "dss1.h" @@ -73,7 +74,7 @@ static void print_help() printf(" --config [~/]\n"); printf(" Give a config file to use. If it starts with '~/', path is at home dir.\n"); printf(" Each line in config file is one option, '-' or '--' must not be given!\n"); - debug_print_help(); + logging_print_help(); printf(" --ulaw\n"); printf(" Use U-LAW for b-channel coding instead of alaw.\n"); printf(" -p --port | \n"); @@ -190,11 +191,9 @@ static int handle_options(int short_option, int argi, char **argv) print_help(); return 0; case 'v': - if (!strcasecmp(argv[argi], "list")) { - debug_list_cat(); + rc = parse_logging_opt(argv[argi]); + if (rc > 0) return 0; - } - rc = parse_debug_opt(argv[argi]); if (rc < 0) { fprintf(stderr, "Failed to parse debug option, please use -h for help.\n"); return rc; @@ -298,13 +297,9 @@ void sighandler(int sigset) static struct mi_ext_fn_s mi_fn; -static int mISDNlib_debug(const char *file, int line, const char *func, int __attribute__((unused)) level, const char *fmt, va_list va) +static int mISDNlib_debug(const char *file, int line, const char __attribute__((unused)) *func, int __attribute__((unused)) level, const char *fmt, va_list va) { - char text[256]; - vsnprintf(text, sizeof(text) - 1, fmt, va); - text[sizeof(text) - 1] = '\0'; -// PDEBUG(DDSS1, DEBUG_NOTICE, "libmisdn (file %s, line %d, func %s(), level %d): %s\n", file, line, func, level, text); - _printdebug(file, func, line, DMISDN, DEBUG_NOTICE, NULL, "%s", text); + LOGPSRC(DMISDN, LOGL_NOTICE, file, line, fmt, va); return 0; } @@ -317,6 +312,9 @@ int main(int argc, char *argv[]) int layer3_initialized = 0; struct ph_socket_driver ph_drv; const char *p; + struct osmo_timer_list mISDN_timer; + + logging_init(); g711_init(); @@ -380,13 +378,13 @@ int main(int argc, char *argv[]) /* init instance */ rc = isdn_initialize(isdn_ep, (misdn_user) ? &ph_drv.ph_socket : NULL, law, portname, ntmode, ptp, layer1hold, layer2hold, channel_out, channel_in, timeouts, tx_delay, local_tones, serving_location); if (rc) { - PDEBUG(DISDN, DEBUG_ERROR, "mISDN initializing failed!\n"); + LOGP(DISDN, LOGL_ERROR, "mISDN initializing failed!\n"); goto error; } rc = isdn_open(isdn_ep); if (rc) { - PDEBUG(DISDN, DEBUG_ERROR, "mISDN open failed!\n"); + LOGP(DISDN, LOGL_ERROR, "mISDN open failed!\n"); goto error; } @@ -397,6 +395,9 @@ int main(int argc, char *argv[]) if (rc < 0) goto error; + /* Dummy timer to interrupt osmo_select_main when mISDN timer fires before anything else. */ + osmo_timer_setup(&mISDN_timer, NULL, NULL); + /* real time priority */ if (rt_prio > 0) { struct sched_param schedp; @@ -416,7 +417,7 @@ int main(int argc, char *argv[]) while (!quit) { int work; - double timeout, misdn_timeout = 0.0; + double misdn_timeout = 0.0; do { work = 0; @@ -427,18 +428,11 @@ int main(int argc, char *argv[]) work |= work_layer3(isdn_ep->ml3, &misdn_timeout); } } while (work); - /* handle all timers - * timeout is 0, if there was an event - * -> handle FDs without waiting, continue this loop - * timeout is not 0, if there was no event - * -> wait until FD or timeout - */ - timeout = process_timer(); - /* reduce timer, if mISDN timer hits earlier */ - if (misdn_timeout > 0.0 && misdn_timeout < timeout) - timeout = misdn_timeout; - /* wait for FD event until given timeout */ - osmo_fd_select(timeout); + /* wait for event or stop, if mISDN_timer fires */ + if (misdn_timeout) + osmo_timer_schedule(&mISDN_timer, floor(misdn_timeout), (misdn_timeout - floor(misdn_timeout)) * 1000000); + osmo_select_main(0); + osmo_timer_del(&mISDN_timer); } signal(SIGINT, SIG_DFL); diff --git a/src/isdn/ph_driver.c b/src/isdn/ph_driver.c index 7daed8a..e4d2f94 100644 --- a/src/isdn/ph_driver.c +++ b/src/isdn/ph_driver.c @@ -21,8 +21,8 @@ #include #include #include -#include "../libtimer/timer.h" -#include "../libselect/select.h" +#include +#include #include "../libph_socket/ph_socket.h" #include "ph_driver.h" #define __MISDNL1L2__ diff --git a/src/isdn/tones.c b/src/isdn/tones.c index 52709b8..21ff727 100644 --- a/src/isdn/tones.c +++ b/src/isdn/tones.c @@ -17,8 +17,8 @@ #include #include #include -#include "../libdebug/debug.h" -#include "../libg711/g711.h" +#include "../liblogging/logging.h" +#include #include #include "tones.h" @@ -452,10 +452,10 @@ int isdn_tone_set(struct isdn_tone *t, int tone) i++; } if (!pat) { - PDEBUG(DISDN, DEBUG_ERROR, "given tone 0x%x is invalid\n", tone); + LOGP(DISDN, LOGL_ERROR, "given tone 0x%x is invalid\n", tone); return -EINVAL; } - PDEBUG(DISDN, DEBUG_DEBUG, "playing given tone 0x%x\n", tone); + LOGP(DISDN, LOGL_DEBUG, "playing given tone 0x%x\n", tone); t->tone = tone; t->pattern = pat; t->index = 0; diff --git a/src/libdebug/Makefile.am b/src/libdebug/Makefile.am deleted file mode 100644 index 210a097..0000000 --- a/src/libdebug/Makefile.am +++ /dev/null @@ -1,7 +0,0 @@ -AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) - -noinst_LIBRARIES = libdebug.a - -libdebug_a_SOURCES = \ - debug.c - diff --git a/src/libdebug/debug.c b/src/libdebug/debug.c deleted file mode 100644 index 22811e2..0000000 --- a/src/libdebug/debug.c +++ /dev/null @@ -1,331 +0,0 @@ -/* Simple debug functions for level and category filtering - * - * (C) 2016 by Andreas Eversberg - * All Rights Reserved - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "debug.h" - -const char *debug_level[] = { - "debug ", - "info ", - "notice ", - "error ", - NULL, -}; - -struct debug_cat { - const char *name; - const char *color; -} debug_cat[] = { - { "options", "\033[0;33m" }, - { "sender", "\033[1;33m" }, - { "sound", "\033[0;35m" }, - { "dsp", "\033[0;31m" }, - { "anetz", "\033[1;34m" }, - { "bnetz", "\033[1;34m" }, - { "cnetz", "\033[1;34m" }, - { "nmt", "\033[1;34m" }, - { "amps", "\033[1;34m" }, - { "r2000", "\033[1;34m" }, - { "imts", "\033[1;34m" }, - { "mpt1327", "\033[1;34m" }, - { "jollycom", "\033[1;34m" }, - { "eurosignal", "\033[1;34m" }, - { "pocsag", "\033[1;34m" }, - { "golay", "\033[1;34m" }, - { "5-ton-folge", "\033[1;34m" }, - { "frame", "\033[0;36m" }, - { "call", "\033[0;37m" }, - { "cc", "\033[1;32m" }, - { "database", "\033[0;33m" }, - { "transaction", "\033[0;32m" }, - { "dms", "\033[0;33m" }, - { "sms", "\033[1;37m" }, - { "sdr", "\033[1;31m" }, - { "uhd", "\033[1;35m" }, - { "soapy", "\033[1;35m" }, - { "wave", "\033[1;33m" }, - { "radio", "\033[1;34m" }, - { "am791x", "\033[0;31m" }, - { "uart", "\033[0;32m" }, - { "device", "\033[0;33m" }, - { "datenklo", "\033[1;34m" }, - { "zeit", "\033[1;34m" }, - { "sim layer 1", "\033[0;31m" }, - { "sim layer 2", "\033[0;33m" }, - { "sim ICL layer", "\033[0;36m" }, - { "sim layer 7", "\033[0;37m" }, - { "mtp layer 2", "\033[1;33m" }, - { "mtp layer 3", "\033[1;36m" }, - { "MuP", "\033[1;37m" }, - { "router", "\033[1;35m" }, - { "stderr", "\033[1;37m" }, - { "ss5", "\033[1;34m" }, - { "r1", "\033[1;34m" }, - { "isdn", "\033[1;35m" }, - { "misdn", "\033[0;34m" }, - { "dss1", "\033[1;34m" }, - { "sip", "\033[1;35m" }, - { "telephone", "\033[1;34m" }, - { "uk0", "\033[1;34m" }, - { "ph", "\033[0;33m" }, - { "dcf77", "\033[1;34m" }, - { "jitter", "\033[0;36m" }, - { NULL, NULL } -}; - -int debuglevel = DEBUG_INFO; -int debug_date = 0; -uint64_t debug_mask[2] = { ~0, ~0 }; -extern int num_kanal; - -void (*clear_console_text)(void) = NULL; -void (*print_console_text)(void) = NULL; - -int debug_limit_scroll = 0; - -static int lock_initialized = 0; -static pthread_mutex_t debug_mutex; - -void lock_debug(void) -{ - int rc; - - if (!lock_initialized) { - rc = pthread_mutex_init(&debug_mutex, NULL); - if (rc == 0) - lock_initialized = 1; - } - if (lock_initialized) - pthread_mutex_lock(&debug_mutex); -} - -void unlock_debug(void) -{ - if (lock_initialized) - pthread_mutex_unlock(&debug_mutex); -} - -void get_win_size(int *w, int *h) -{ - struct winsize win; - int rc; - - rc = ioctl(0, TIOCGWINSZ, &win); - if (rc) { - *w = 80; - *h = 25; - return; - } - - *h = win.ws_row; - *w = win.ws_col; -} - -void _printdebug(const char *file, const char __attribute__((unused)) *function, int line, int cat, int level, const char *kanal, const char *fmt, ...) -{ - char buffer[4096], *b = buffer; - int s = sizeof(buffer) - 1; - const char *p; - va_list args; - int w, h = 0; // make GCC happy - - if (debuglevel > level) - return; - - if (!(debug_mask[cat >> 6] & ((uint64_t)1 << (cat & 63)))) - return; - - lock_debug(); - - buffer[sizeof(buffer) - 1] = '\0'; - - /* if kanal is used, prefix the channel number */ - if (num_kanal > 1 && kanal) { - sprintf(buffer, "(chan %s) ", kanal); - b = strchr(buffer, '\0'); - s -= strlen(buffer); - } - - va_start(args, fmt); - vsnprintf(b, s, fmt, args); - va_end(args); - - while ((p = strchr(file, '/'))) - file = p + 1; - if (clear_console_text) - clear_console_text(); - if (debug_limit_scroll) { - get_win_size(&w, &h); - printf("\0337\033[%d;%dr\0338", debug_limit_scroll + 1, h); - } - if (debug_date) { - struct timeval tv; - struct tm *tm; - - gettimeofday(&tv, NULL); - tm = localtime(&tv.tv_sec); - - printf("%04d-%02d-%02d %02d:%02d:%02d.%03d ", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(tv.tv_usec / 10000.0)); - } - printf("%s%s %4d %s-%s: %s\033[0;39m", debug_cat[cat].color, file, line, debug_cat[cat].name, debug_level[level], buffer); - if (debug_limit_scroll) - printf("\0337\033[%d;%dr\0338", 1, h); - if (print_console_text) - print_console_text(); - fflush(stdout); - - unlock_debug(); -} - -const char *debug_amplitude(double level) -{ - static char text[42]; - - strcpy(text, " : "); - if (level > 1.0) - level = 1.0; - if (level < -1.0) - level = -1.0; - text[20 + (int)(level * 20)] = '*'; - - return text; -} - -#define level2db(level) (20 * log10(level)) - -const char *debug_db(double level_db) -{ - static char text[128]; - int l; - - strcpy(text, ": . : . : . : . : . : . : . : . | . : . : . : . : . : . : . : . :"); - if (level_db <= 0.0) - return text; - l = (int)round(level2db(level_db)); - if (l > 48) - return text; - if (l < -48) - return text; - text[l + 48] = '*'; - - return text; -} - -void debug_print_help(void) -{ - printf(" -v --verbose | ,[,[,...]] | list\n"); - printf(" Use 'list' to get a list of all levels and categories\n"); - printf(" Verbose level: digit of debug level (default = '%d')\n", debuglevel); - printf(" Verbose level+category: level digit followed by one or more categories\n"); - printf(" -> If no category is specified, all categories are selected\n"); - printf(" -v --verbose date\n"); - printf(" Show date with debug output\n"); -} - -void debug_list_cat(void) -{ - int i; - - printf("Give number of debug level:\n"); - for (i = 0; debug_level[i]; i++) - printf(" %d = %s\n", i, debug_level[i]); - printf("\n"); - - printf("Give name(s) of debug category:\n"); - for (i = 0; debug_cat[i].name; i++) - printf(" %s%s\033[0;39m\n", debug_cat[i].color, debug_cat[i].name); - printf("\n"); -} - -int parse_debug_opt(const char *optarg) -{ - int i, max_level = 0; - char *dup, *dstring, *p; - - if (!strcasecmp(optarg, "date")) { - debug_date = 1; - return 0; - } - - for (i = 0; debug_level[i]; i++) - max_level = i; - - dup = dstring = strdup(optarg); - p = strsep(&dstring, ","); - for (i = 0; i < p[i]; i++) { - if (p[i] < '0' || p[i] > '9') { - fprintf(stderr, "Only digits are allowed for debug level!\n"); - free(dup); - return -EINVAL; - } - } - debuglevel = atoi(p); - if (debuglevel > max_level) { - fprintf(stderr, "Debug level too high, use 'list' to show available levels!\n"); - free(dup); - return -EINVAL; - } - if (dstring) - memset(debug_mask, 0, sizeof(debug_mask)); - while((p = strsep(&dstring, ","))) { - for (i = 0; debug_cat[i].name; i++) { - if (!strcasecmp(p, debug_cat[i].name)) - break; - } - if (!debug_cat[i].name) { - fprintf(stderr, "Given debug category '%s' unknown, use 'list' to show available categories!\n", p); - free(dup); - return -EINVAL; - } - debug_mask[i >> 6] |= ((uint64_t)1 << (i & 63)); - } - - free(dup); - return 0; -} - -const char *debug_hex(const uint8_t *data, int len) -{ - static char *text = NULL; - char *p; - int i; - - if (text) - free(text); - p = text = calloc(1, len * 3 + 1); - for (i = 0; i < len; i++) { - sprintf(p, "%02x ", *data++); - p += 3; - } - if (text[0]) - p[-1] = '\0'; - - return text; -} - diff --git a/src/libdebug/debug.h b/src/libdebug/debug.h deleted file mode 100644 index 3554af5..0000000 --- a/src/libdebug/debug.h +++ /dev/null @@ -1,94 +0,0 @@ - -#define DEBUG_DEBUG 0 /* debug info, not for normal use */ -#define DEBUG_INFO 1 /* all info about process */ -#define DEBUG_NOTICE 2 /* something unexpected happens */ -#define DEBUG_ERROR 3 /* there is an error with this software */ - -#define DOPTIONS 0 -#define DSENDER 1 -#define DSOUND 2 -#define DDSP 3 -#define DANETZ 4 -#define DBNETZ 5 -#define DCNETZ 6 -#define DNMT 7 -#define DAMPS 8 -#define DR2000 9 -#define DIMTS 10 -#define DMPT1327 11 -#define DJOLLY 12 -#define DEURO 13 -#define DPOCSAG 14 -#define DGOLAY 15 -#define DFUENF 16 -#define DFRAME 17 -#define DCALL 18 -#define DCC 19 -#define DDB 20 -#define DTRANS 21 -#define DDMS 22 -#define DSMS 23 -#define DSDR 24 -#define DUHD 25 -#define DSOAPY 26 -#define DWAVE 27 -#define DRADIO 28 -#define DAM791X 29 -#define DUART 30 -#define DDEVICE 31 -#define DDATENKLO 32 -#define DZEIT 33 -#define DSIM1 34 -#define DSIM2 35 -#define DSIMI 36 -#define DSIM7 37 -#define DMTP2 38 -#define DMTP3 39 -#define DMUP 40 -#define DROUTER 41 -#define DSTDERR 42 -#define DSS5 43 -#define DR1 44 -#define DISDN 45 -#define DMISDN 46 -#define DDSS1 47 -#define DSIP 48 -#define DTEL 49 -#define DUK0 50 -#define DPH 51 -#define DDCF77 52 -#define DJITTER 53 -//NOTE: increment mask array, if 127 is exceeded - -void lock_debug(void); -void unlock_debug(void); - -void get_win_size(int *w, int *h); - -#define PDEBUG(cat, level, fmt, arg...) _printdebug(__FILE__, __FUNCTION__, __LINE__, cat, level, NULL, fmt, ## arg) -#define PDEBUG_CHAN(cat, level, fmt, arg...) _printdebug(__FILE__, __FUNCTION__, __LINE__, cat, level, CHAN, fmt, ## arg) -void _printdebug(const char *file, const char *function, int line, int cat, int level, const char *chan_str, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 7, 8))); - -const char *debug_amplitude(double level); -const char *debug_db(double level_db); - -void debug_print_help(void); -void debug_list_cat(void); -int parse_debug_opt(const char *opt); - -extern int debuglevel; - -extern void (*clear_console_text)(void); -extern void (*print_console_text)(void); - -extern int debug_limit_scroll; - -const char *debug_hex(const uint8_t *data, int len); - -#define LOGP PDEBUG -#define LOGL_DEBUG DEBUG_DEBUG -#define LOGL_INFO DEBUG_INFO -#define LOGL_NOTICE DEBUG_NOTICE -#define LOGL_ERROR DEBUG_ERROR -#define osmo_hexdump debug_hex - diff --git a/src/libg711/Makefile.am b/src/libg711/Makefile.am deleted file mode 100644 index 15223bf..0000000 --- a/src/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/libg711/g711.c b/src/libg711/g711.c deleted file mode 100644 index 92404c1..0000000 --- a/src/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_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_flipped_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_flipped_to_linear[i] = g711_ulaw_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_to_linear[j]) - j++; - g711_linear_to_ulaw[(i - 32768) & 0xffff] = j; - g711_linear_to_ulaw_flipped[(i - 32768) & 0xffff] = g711_flip[j]; - i++; - } - j = 255; - while(i < 65536) { - if (i - 32768 > g711_ulaw_to_linear[j]) - j--; - g711_linear_to_ulaw[(i - 32768) & 0xffff] = j; - g711_linear_to_ulaw_flipped[(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, void __attribute__((unused)) *priv) -{ - 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, void __attribute__((unused)) *priv) -{ - 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, void __attribute__((unused)) *priv) -{ - 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, void __attribute__((unused)) *priv) -{ - 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, void __attribute__((unused)) *priv) -{ - 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, void __attribute__((unused)) *priv) -{ - 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, void __attribute__((unused)) *priv) -{ - 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, void __attribute__((unused)) *priv) -{ - 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, void __attribute__((unused)) *priv) -{ - 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, void __attribute__((unused)) *priv) -{ - 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, void __attribute__((unused)) *priv) -{ - 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, void __attribute__((unused)) *priv) -{ - 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, void __attribute__((unused)) *priv) -{ - 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, void __attribute__((unused)) *priv) -{ - 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, void __attribute__((unused)) *priv) -{ - 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/libg711/g711.h b/src/libg711/g711.h deleted file mode 100644 index 389daa9..0000000 --- a/src/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 *priv); -void g711_encode_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv); -void g711_decode_alaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv); -void g711_decode_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv); -void g711_encode_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv); -void g711_encode_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv); -void g711_decode_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv); -void g711_decode_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv); -void g711_transcode_alaw_to_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv); -void g711_transcode_alaw_flipped_to_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv); -void g711_transcode_alaw_to_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv); -void g711_transcode_ulaw_to_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv); -void g711_transcode_ulaw_flipped_to_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv); -void g711_transcode_ulaw_to_alaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv); -void g711_transcode_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv); - diff --git a/src/libjitter/jitter.c b/src/libjitter/jitter.c index 1de03c2..bcf27ac 100644 --- a/src/libjitter/jitter.c +++ b/src/libjitter/jitter.c @@ -77,7 +77,7 @@ #include #include #include "../libsample/sample.h" -#include "../libdebug/debug.h" +#include "../liblogging/logging.h" #include "jitter.h" #define INITIAL_DELAY_INTERVAL 0.5 @@ -104,7 +104,7 @@ int jitter_create(jitter_t *jb, const char *name, double samplerate, int sample_ jb->extra_size = (int)(EXTRA_BUFFER * samplerate); jb->extra_samples = calloc(sample_size, jb->extra_size); if (!jb->extra_samples) { - PDEBUG(DJITTER, DEBUG_ERROR, "No memory for frame.\n"); + LOGP(DJITTER, LOGL_ERROR, "No memory for frame.\n"); rc = -ENOMEM; goto error; } @@ -118,7 +118,7 @@ int jitter_create(jitter_t *jb, const char *name, double samplerate, int sample_ jitter_reset(jb); - PDEBUG(DJITTER, DEBUG_INFO, "%sCreated jitter buffer. (samplerate=%.0f, target_window=%.0fms, max_window=%.0fms, flag:latency=%s flag:repeat=%s)\n", jb->name, samplerate, target_window_duration * 1000.0, max_window_duration * 1000.0, (window_flags & JITTER_FLAG_LATENCY) ? "true" : "false", (window_flags & JITTER_FLAG_REPEAT) ? "true" : "false"); + LOGP(DJITTER, LOGL_INFO, "%sCreated jitter buffer. (samplerate=%.0f, target_window=%.0fms, max_window=%.0fms, flag:latency=%s flag:repeat=%s)\n", jb->name, samplerate, target_window_duration * 1000.0, max_window_duration * 1000.0, (window_flags & JITTER_FLAG_LATENCY) ? "true" : "false", (window_flags & JITTER_FLAG_REPEAT) ? "true" : "false"); error: if (rc) @@ -139,7 +139,7 @@ void jitter_reset(jitter_t *jb) { jitter_frame_t *jf, *temp; - PDEBUG(DJITTER, DEBUG_INFO, "%sReset jitter buffer.\n", jb->name); + LOGP(DJITTER, LOGL_INFO, "%sReset jitter buffer.\n", jb->name); /* jitter buffer locked */ jb->unlocked = 0; @@ -172,7 +172,7 @@ void jitter_destroy(jitter_t *jb) { jitter_reset(jb); - PDEBUG(DJITTER, DEBUG_INFO, "%sDestroying jitter buffer.\n", jb->name); + LOGP(DJITTER, LOGL_INFO, "%sDestroying jitter buffer.\n", jb->name); if (jb->extra_samples) { free(jb->extra_samples); @@ -201,7 +201,7 @@ void jitter_save(jitter_t *jb, void *samples, int length, int has_sequence, uint /* generate sequence and timestamp automatically, if enabled */ if (!has_sequence) { #ifdef DEBUG_JITTER - PDEBUG(DJITTER, DEBUG_DEBUG, "%sSave frame of %d samples (no seqence).\n", jb->name, length); + LOGP(DJITTER, LOGL_DEBUG, "%sSave frame of %d samples (no seqence).\n", jb->name, length); #endif sequence = jb->next_sequence; jb->next_sequence++; @@ -210,7 +210,7 @@ void jitter_save(jitter_t *jb, void *samples, int length, int has_sequence, uint ssrc = jb->window_ssrc; } else { #ifdef HEAVY_DEBUG - PDEBUG(DJITTER, DEBUG_DEBUG, "%sSave frame of %d samples (seqence=%u timestamp=%u ssrc=0x%02x).\n", jb->name, length, sequence, timestamp, ssrc); + LOGP(DJITTER, LOGL_DEBUG, "%sSave frame of %d samples (seqence=%u timestamp=%u ssrc=0x%02x).\n", jb->name, length, sequence, timestamp, ssrc); #endif jb->next_sequence = sequence + 1; jb->next_timestamp = timestamp + length; @@ -219,9 +219,9 @@ void jitter_save(jitter_t *jb, void *samples, int length, int has_sequence, uint /* first packet (with this ssrc) sets window size to target_window_size */ if (!jb->window_valid || jb->window_ssrc != ssrc) { if (!jb->window_valid) - PDEBUG(DJITTER, DEBUG_DEBUG, "%s Initial frame after init or reset.\n", jb->name); + LOGP(DJITTER, LOGL_DEBUG, "%s Initial frame after init or reset.\n", jb->name); else - PDEBUG(DJITTER, DEBUG_DEBUG, "%s SSRC changed.\n", jb->name); + LOGP(DJITTER, LOGL_DEBUG, "%s SSRC changed.\n", jb->name); // NOTE: Reset must be called before finding the frame location below, because there will be no frame in list anymore! jitter_reset(jb); jb->unlocked = 1; @@ -241,7 +241,7 @@ void jitter_save(jitter_t *jb, void *samples, int length, int has_sequence, uint offset_sequence = (int16_t)(sequence - (*jfp)->sequence); /* found double entry */ if (offset_sequence == 0) { - PDEBUG(DJITTER, DEBUG_DEBUG, "%s Dropping double packet (sequence = %d)\n", jb->name, sequence); + LOGP(DJITTER, LOGL_DEBUG, "%s Dropping double packet (sequence = %d)\n", jb->name, sequence); return; } /* offset is negative, so we found the position to insert frame */ @@ -252,7 +252,7 @@ void jitter_save(jitter_t *jb, void *samples, int length, int has_sequence, uint offset_timestamp = timestamp - jb->window_timestamp; #ifdef HEAVY_DEBUG - PDEBUG(DJITTER, DEBUG_DEBUG, "%sFrame has offset of %.0fms in jitter buffer.\n", jb->name, (double)offset_timestamp * jb->sample_duration * 1000.0); + LOGP(DJITTER, LOGL_DEBUG, "%sFrame has offset of %.0fms in jitter buffer.\n", jb->name, (double)offset_timestamp * jb->sample_duration * 1000.0); #endif /* measure delay */ @@ -262,11 +262,11 @@ void jitter_save(jitter_t *jb, void *samples, int length, int has_sequence, uint /* if frame is too early (delay ceases), shift window to the future */ if (offset_timestamp > jb->max_window_size) { if ((jb->window_flags & JITTER_FLAG_LATENCY)) { - PDEBUG(DJITTER, DEBUG_DEBUG, "%s Frame too early: Shift jitter buffer to the future, to make the frame fit to the end. (offset_timestamp(%d) > max_window_size(%d))\n", jb->name, offset_timestamp, jb->max_window_size); + LOGP(DJITTER, LOGL_DEBUG, "%s Frame too early: Shift jitter buffer to the future, to make the frame fit to the end. (offset_timestamp(%d) > max_window_size(%d))\n", jb->name, offset_timestamp, jb->max_window_size); /* shift window so it fits to the end of window */ jb->window_timestamp = timestamp - jb->max_window_size; } else { - PDEBUG(DJITTER, DEBUG_DEBUG, "%s Frame too early: Shift jitter buffer to the future, to make the frame fit to the target delay. (offset_timestamp(%d) > max_window_size(%d))\n", jb->name, offset_timestamp, jb->max_window_size); + LOGP(DJITTER, LOGL_DEBUG, "%s Frame too early: Shift jitter buffer to the future, to make the frame fit to the target delay. (offset_timestamp(%d) > max_window_size(%d))\n", jb->name, offset_timestamp, jb->max_window_size); /* shift window so frame fits to the start of window + target delay */ jb->window_timestamp = timestamp - (uint32_t)(jb->target_window_size); } @@ -275,11 +275,11 @@ void jitter_save(jitter_t *jb, void *samples, int length, int has_sequence, uint /* is frame is too late, shift window to the past. */ if (offset_timestamp < 0) { if ((jb->window_flags & JITTER_FLAG_LATENCY)) { - PDEBUG(DJITTER, DEBUG_DEBUG, "%s Frame too late: Shift jitter buffer to the past, and add target window size. (offset_timestamp(%d) < 0)\n", jb->name, offset_timestamp); + LOGP(DJITTER, LOGL_DEBUG, "%s Frame too late: Shift jitter buffer to the past, and add target window size. (offset_timestamp(%d) < 0)\n", jb->name, offset_timestamp); /* shift window so frame fits to the start of window + half of target delay */ jb->window_timestamp = timestamp - (uint32_t)(jb->target_window_size) / 2; } else { - PDEBUG(DJITTER, DEBUG_DEBUG, "%s Frame too late: Shift jitter buffer to the past, and add half target window size. (offset_timestamp(%d) < 0)\n", jb->name, offset_timestamp); + LOGP(DJITTER, LOGL_DEBUG, "%s Frame too late: Shift jitter buffer to the past, and add half target window size. (offset_timestamp(%d) < 0)\n", jb->name, offset_timestamp); /* shift window so frame fits to the start of window + target delay */ jb->window_timestamp = timestamp - (uint32_t)(jb->target_window_size); } @@ -287,11 +287,11 @@ void jitter_save(jitter_t *jb, void *samples, int length, int has_sequence, uint /* insert or append frame */ #ifdef HEAVY_DEBUG - PDEBUG(DJITTER, DEBUG_DEBUG, "%s Store frame\n", jb->name); + LOGP(DJITTER, LOGL_DEBUG, "%s Store frame\n", jb->name); #endif jf = malloc(sizeof(*jf) + length * jb->sample_size); if (!jf) { - PDEBUG(DJITTER, DEBUG_ERROR, "No memory for frame.\n"); + LOGP(DJITTER, LOGL_ERROR, "No memory for frame.\n"); return; } memset(jf, 0, sizeof(*jf)); // note: clear header only @@ -311,7 +311,7 @@ void jitter_load(jitter_t *jb, void *samples, int length) int32_t count, count2, index; #ifdef HEAVY_DEBUG - PDEBUG(DJITTER, DEBUG_DEBUG, "%sLoad chunk of %d samples.\n", jb->name, length); + LOGP(DJITTER, LOGL_DEBUG, "%sLoad chunk of %d samples.\n", jb->name, length); #endif /* now unlock jitter buffer */ @@ -321,10 +321,10 @@ void jitter_load(jitter_t *jb, void *samples, int length) jb->delay_counter += jb->sample_duration * (double)length; if (jb->delay_counter >= jb->delay_interval) { if (jb->min_delay_value >= 0) - PDEBUG(DJITTER, DEBUG_DEBUG, "%s Statistics: target_window_delay=%.0fms max_window_delay=%.0fms current min_delay=%.0fms\n", jb->name, (double)jb->target_window_size * jb->sample_duration * 1000.0, (double)jb->max_window_size * jb->sample_duration * 1000.0, (double)jb->min_delay_value * jb->sample_duration * 1000.0); + LOGP(DJITTER, LOGL_DEBUG, "%s Statistics: target_window_delay=%.0fms max_window_delay=%.0fms current min_delay=%.0fms\n", jb->name, (double)jb->target_window_size * jb->sample_duration * 1000.0, (double)jb->max_window_size * jb->sample_duration * 1000.0, (double)jb->min_delay_value * jb->sample_duration * 1000.0); /* delay reduction, if maximum delay is greater than target jitter window size */ if ((jb->window_flags & JITTER_FLAG_LATENCY) && jb->min_delay_value > jb->target_window_size) { - PDEBUG(DJITTER, DEBUG_DEBUG, "%s Reducing current minimum delay of %.0fms, because maximum delay is greater than target window size of %.0fms.\n", jb->name, (double)jb->min_delay_value * jb->sample_duration * 1000.0, (double)jb->target_window_size * jb->sample_duration * 1000.0); + LOGP(DJITTER, LOGL_DEBUG, "%s Reducing current minimum delay of %.0fms, because maximum delay is greater than target window size of %.0fms.\n", jb->name, (double)jb->min_delay_value * jb->sample_duration * 1000.0, (double)jb->target_window_size * jb->sample_duration * 1000.0); /* only reduce delay to half of the target window size */ jb->window_timestamp += jb->min_delay_value - jb->target_window_size / 2; @@ -349,9 +349,9 @@ void jitter_load(jitter_t *jb, void *samples, int length) if (count > 0) { #ifdef HEAVY_DEBUG if (jf) - PDEBUG(DJITTER, DEBUG_DEBUG, "%s There is a frame ahead in buffer after %d samples. Interpolating gap.\n", jb->name, jf->timestamp - jb->window_timestamp); + LOGP(DJITTER, LOGL_DEBUG, "%s There is a frame ahead in buffer after %d samples. Interpolating gap.\n", jb->name, jf->timestamp - jb->window_timestamp); else - PDEBUG(DJITTER, DEBUG_DEBUG, "%s There is no frame ahead in buffer. Interpolating gap.\n", jb->name); + LOGP(DJITTER, LOGL_DEBUG, "%s There is no frame ahead in buffer. Interpolating gap.\n", jb->name); #endif /* extrapolate by playing the extrapolation buffer */ while (count) { @@ -366,7 +366,7 @@ void jitter_load(jitter_t *jb, void *samples, int length) jb->extra_timeout_count++; if (jb->extra_timeout_count == jb->extra_timeout_max) { #ifdef HEAVY_DEBUG - PDEBUG(DJITTER, DEBUG_DEBUG, "%s Repeated jitter buffer enough, clearing to silence.\n", jb->name); + LOGP(DJITTER, LOGL_DEBUG, "%s Repeated jitter buffer enough, clearing to silence.\n", jb->name); #endif clear_extra_buffer(jb); } @@ -393,7 +393,7 @@ void jitter_load(jitter_t *jb, void *samples, int length) count = jb->extra_size - jb->extra_index; /* copy samples from packet to play out, increment sample pointer and decrement length */ #ifdef HEAVY_DEBUG - PDEBUG(DJITTER, DEBUG_DEBUG, "%s Copy data (offset=%u count=%u) from frame (sequence=%u timestamp=%u length=%u).\n", jb->name, index, count, jf->sequence, jf->timestamp, jf->length); + LOGP(DJITTER, LOGL_DEBUG, "%s Copy data (offset=%u count=%u) from frame (sequence=%u timestamp=%u length=%u).\n", jb->name, index, count, jf->sequence, jf->timestamp, jf->length); #endif memcpy(samples, (uint8_t *)jf->samples + index * jb->sample_size, count * jb->sample_size); samples = (uint8_t *)samples + count * jb->sample_size; diff --git a/src/liblogging/Makefile.am b/src/liblogging/Makefile.am new file mode 100644 index 0000000..a1b1e18 --- /dev/null +++ b/src/liblogging/Makefile.am @@ -0,0 +1,8 @@ +AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) + +noinst_LIBRARIES = liblogging.a + +liblogging_a_SOURCES = \ + logging.c \ + categories.c + diff --git a/src/liblogging/categories.c b/src/liblogging/categories.c new file mode 100644 index 0000000..a31d8c4 --- /dev/null +++ b/src/liblogging/categories.c @@ -0,0 +1,42 @@ + +#include +#include +#include "categories.h" + +/* All logging categories used by this project. */ + +struct log_info_cat log_categories[] = { + [DOPTIONS] = { + .name = "DOPTIONS", + .description = "config options", + .color = "\033[0;33m", + }, + [DJITTER] = { + .name = "DJITTER", + .description = "jitter buffer handling", + .color = "\033[0;36m", + }, + [DISDN] = { + .name = "DISDN", + .description = "ISDN control", + .color = "\033[1;35m", + }, + [DMISDN] = { + .name = "DMISDN", + .description = "mISDN stack", + .color = "\033[0;34m", + }, + [DDSS1] = { + .name = "DDSS1", + .description = "ISDN DSS1 protocol", + .color = "\033[1;34m", + }, + [DPH] = { + .name = "DPH", + .description = "PH SAP socket interface", + .color = "\033[0;33m", + }, +}; + +size_t log_categories_size = ARRAY_SIZE(log_categories); + diff --git a/src/liblogging/categories.h b/src/liblogging/categories.h new file mode 100644 index 0000000..6320c79 --- /dev/null +++ b/src/liblogging/categories.h @@ -0,0 +1,13 @@ + +enum { + DOPTIONS, + DJITTER, + DISDN, + DMISDN, + DDSS1, + DPH, +}; + +extern struct log_info_cat log_categories[]; +extern size_t log_categories_size; + diff --git a/src/liblogging/logging.c b/src/liblogging/logging.c new file mode 100644 index 0000000..56578d5 --- /dev/null +++ b/src/liblogging/logging.c @@ -0,0 +1,272 @@ +/* Logging (on segmented part of the window) + * + * (C) 2016 by Andreas Eversberg + * All Rights Reserved + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include "logging.h" + +int loglevel = LOGL_INFO; + +extern int num_kanal; + +static int scroll_window_start = 0; +static int scroll_window_end = 0; +static int scroll_window_height = 0; + +void lock_logging(void) +{ + log_tgt_mutex_lock(); +} + +void unlock_logging(void) +{ + log_tgt_mutex_unlock(); +} + +void get_win_size(int *w, int *h) +{ + struct winsize win; + int rc; + + rc = ioctl(0, TIOCGWINSZ, &win); + if (rc) { + *w = 80; + *h = 25; + return; + } + + if (h) + *h = win.ws_row; + if (w) + *w = win.ws_col; +} + +void enable_limit_scroll(bool enable) +{ + /* Before the window is set, keep scrolling everything. */ + if (scroll_window_height == 0) + return; + + /* If window is too small. */ + if (scroll_window_end - scroll_window_start <= 0) + return; + + if (enable) { + printf("\0337\033[%d;%dr\0338", scroll_window_start, scroll_window_end); + } else + printf("\0337\033[%d;%dr\0338", 1, scroll_window_height); + fflush(stdout); +} + +void logging_limit_scroll_top(int lines) +{ + lock_logging(); + + get_win_size(NULL, &scroll_window_height); + scroll_window_start = lines + 1; + if (scroll_window_end == 0) + scroll_window_end = scroll_window_height; + + enable_limit_scroll(true); + + unlock_logging(); +} + +void logging_limit_scroll_bottom(int lines) +{ + int i; + + lock_logging(); + + get_win_size(NULL, &scroll_window_height); + scroll_window_end = scroll_window_height - lines; + if (scroll_window_start == 0) + scroll_window_start = 1; + + /* Make space by adding empty lines. */ + for (i = scroll_window_end; i < scroll_window_height; i++) + printf("\n"); + /* Go up by number of lines to be in window. */ + printf("\033[%dA", scroll_window_height - scroll_window_end); + /* Enable window. */ + enable_limit_scroll(true); + + unlock_logging(); +} + +const char *debug_amplitude(double level) +{ + static char text[42]; + + strcpy(text, " : "); + if (level > 1.0) + level = 1.0; + if (level < -1.0) + level = -1.0; + text[20 + (int)(level * 20)] = '*'; + + return text; +} + +#define level2db(level) (20 * log10(level)) + +const char *debug_db(double level_db) +{ + static char text[128]; + int l; + + strcpy(text, ": . : . : . : . : . : . : . : . | . : . : . : . : . : . : . : . :"); + if (level_db <= 0.0) + return text; + l = (int)round(level2db(level_db)); + if (l > 48) + return text; + if (l < -48) + return text; + text[l + 48] = '*'; + + return text; +} + +void logging_print_help(void) +{ + printf(" -v --verbose | ,[,[,...]] | list\n"); + printf(" Use 'list' to get a list of all levels and categories.\n"); + printf(" Verbose level: digit of debug level (default = '%d')\n", loglevel); + printf(" Verbose level+category: level digit followed by one or more categories\n"); + printf(" -> If no category is specified, all categories are selected\n"); + printf(" -v --verbose date\n"); + printf(" Show date with debug output\n"); +} + +static unsigned char log_levels[] = { LOGL_DEBUG, LOGL_INFO, LOGL_NOTICE, LOGL_ERROR }; +static char *log_level_names[] = { "debug", "info", "notice", "error" }; + +static void list_cat(void) +{ + int i; + + printf("Give number of debug level:\n"); + for (i = 0; i < (int)sizeof(log_levels); i++) + printf(" %d = %s\n", log_levels[i], log_level_names[i]); + printf("\n"); + + printf("Give name(s) of debug category:\n"); + for (i = 0; i < (int)osmo_log_info->num_cat; i++) { + if (!osmo_log_info->cat[i].name) + continue; + printf(" "); + if (osmo_log_info->cat[i].color) + printf("%s", osmo_log_info->cat[i].color); + if (osmo_log_info->cat[i].name) + printf("%s\033[0;39m = %s\n", osmo_log_info->cat[i].name, osmo_log_info->cat[i].description); + } + printf("\n"); +} + +int parse_logging_opt(const char *optarg) +{ + int i; + char *dup, *dstring, *p; + + if (!strcasecmp(optarg, "list")) { + list_cat(); + return 1; + } + + if (!strcasecmp(optarg, "date")) { + log_set_print_timestamp(osmo_stderr_target, 1); + return 0; + } + + dup = dstring = strdup(optarg); + p = strsep(&dstring, ","); + for (i = 0; i < p[i]; i++) { + if (p[i] < '0' || p[i] > '9') { + fprintf(stderr, "Only digits are allowed for debug level!\n"); + free(dup); + return -EINVAL; + } + } + loglevel = atoi(p); + for (i = 0; i < (int)sizeof(log_levels); i++) { + if (log_levels[i] == loglevel) + break; + } + if (i == (int)sizeof(log_levels)) { + fprintf(stderr, "Logging level does not exist, use '-v list' to show available levels!\n"); + free(dup); + return -EINVAL; + } + /* Set loglevel and enable all categories, if dstring is not set. Else set loglevel and disable all categories. */ + for (i = 0; i < (int)osmo_log_info->num_cat; i++) { + if (!osmo_stderr_target->categories[i].loglevel) + continue; + osmo_stderr_target->categories[i].loglevel = loglevel; + osmo_stderr_target->categories[i].enabled = (!dstring); + } + /* Enable each given category. */ + while((p = strsep(&dstring, ","))) { + for (i = 0; i < (int)osmo_log_info->num_cat; i++) { + if (!log_category_name(i)) + continue; + if (!strcasecmp(p, log_category_name(i))) + break; + } + if (i == (int)osmo_log_info->num_cat) { + fprintf(stderr, "Given logging category '%s' unknown, use '-v list' to show available categories!\n", p); + free(dup); + return -EINVAL; + } + osmo_stderr_target->categories[i].loglevel = loglevel; + osmo_stderr_target->categories[i].enabled = 1; + } + + free(dup); + return 0; +} + +/* Call after configuation above. */ +void logging_init(void) +{ + int i; + + struct log_info log_info = { + .cat = log_categories, + .num_cat = log_categories_size, + }; + + osmo_init_logging2(NULL, &log_info); + log_set_print_timestamp(osmo_stderr_target, 0); + log_set_print_level(osmo_stderr_target, 1); + log_set_print_category_hex(osmo_stderr_target, 0); + log_set_print_category(osmo_stderr_target, 1); + + /* Set loglevel and enable all categories. */ + for (i = 0; i < (int)osmo_log_info->num_cat; i++) { + if (!osmo_stderr_target->categories[i].loglevel) + continue; + osmo_stderr_target->categories[i].loglevel = loglevel; + osmo_stderr_target->categories[i].enabled = 1; + } +} + diff --git a/src/liblogging/logging.h b/src/liblogging/logging.h new file mode 100644 index 0000000..67f1434 --- /dev/null +++ b/src/liblogging/logging.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include "categories.h" + +extern int loglevel; + +#define LOGP_CHAN(cat, level, fmt, arg...) LOGP(cat, level, "(chan %s) " fmt, CHAN, ## arg) + +void get_win_size(int *w, int *h); +void lock_logging(void); +void unlock_logging(void); +void enable_limit_scroll(bool enable); +void logging_limit_scroll_top(int lines); +void logging_limit_scroll_bottom(int lines); +const char *debug_amplitude(double level); +const char *debug_db(double level_db); +void logging_print_help(void); +int parse_logging_opt(const char *optarg); +void logging_init(void); + diff --git a/src/libmisdn/core.c b/src/libmisdn/core.c index 8c7d8ba..5f6c91b 100644 --- a/src/libmisdn/core.c +++ b/src/libmisdn/core.c @@ -176,7 +176,7 @@ struct mISDNdevice { struct mISDNdevice *dev; - hlist_for_each_entry(dev, &dev_list.head, list) { + m_hlist_for_each_entry(dev, &dev_list.head, list) { if (dev->id == id) return dev; } @@ -188,7 +188,7 @@ get_mdevice_count(void) { int cnt = 0; struct mISDNdevice *dev; - hlist_for_each_entry(dev, &dev_list.head, list) { + m_hlist_for_each_entry(dev, &dev_list.head, list) { cnt++; } return cnt; @@ -235,7 +235,7 @@ mISDN_register_device(struct mISDNdevice *dev, // dev->dev.parent = parent; // dev_set_drvdata(&dev->dev, dev); - hlist_add_head(&dev->list, &dev_list.head); + m_hlist_add_head(&dev->list, &dev_list.head); // err = device_add(&dev->dev); // if (err) // goto error3; @@ -256,7 +256,7 @@ mISDN_unregister_device(struct mISDNdevice *dev) { printk(KERN_DEBUG "mISDN_unregister %s %d\n", dev_name(dev), dev->id); /* sysfs_remove_link(&dev->dev.kobj, "device"); */ - hlist_del(&dev->list); + m_hlist_del(&dev->list); // device_del(&dev->dev); // dev_set_drvdata(&dev->dev, NULL); @@ -421,7 +421,7 @@ int mISDN_work(void) struct mISDNdevice *dev; int work = 0; - hlist_for_each_entry(dev, &dev_list.head, list) { + m_hlist_for_each_entry(dev, &dev_list.head, list) { work |= work_stack(dev); } diff --git a/src/libmisdn/fsm.c b/src/libmisdn/fsm.c index e24ca4f..6c757a4 100644 --- a/src/libmisdn/fsm.c +++ b/src/libmisdn/fsm.c @@ -99,7 +99,7 @@ FsmExpireTimer(void *data) if (ft->fi->debug) ft->fi->printdebug(ft->fi, "FsmExpireTimer %lx", (long) ft); #endif - timer_exit(&ft->tl); + osmo_timer_del(&ft->tl); mISDN_FsmEvent(ft->fi, ft->event, ft->arg); } @@ -124,7 +124,7 @@ mISDN_FsmDelTimer(struct FsmTimer *ft, int __attribute__((unused)) where) ft->fi->printdebug(ft->fi, "mISDN_FsmDelTimer %lx %d", (long) ft, where); #endif - timer_exit(&ft->tl); + osmo_timer_del(&ft->tl); } EXPORT_SYMBOL(mISDN_FsmDelTimer); @@ -139,7 +139,7 @@ mISDN_FsmAddTimer(struct FsmTimer *ft, (long) ft, millisec, where); #endif - if (ft->tl.linked) { +// if (ft->tl.linked) { if (ft->fi->debug) { printk(KERN_WARNING "mISDN_FsmAddTimer: timer already active!\n"); @@ -147,11 +147,11 @@ mISDN_FsmAddTimer(struct FsmTimer *ft, "mISDN_FsmAddTimer already active!"); } return -1; - } +// } ft->event = event; ft->arg = arg; - timer_init(&ft->tl, ft->func, ft); - timer_start(&ft->tl, (double)millisec / 1000); + osmo_timer_setup(&ft->tl, ft->func, ft); + osmo_timer_schedule(&ft->tl, millisec / 1000, (millisec % 1000) * 1000); return 0; } EXPORT_SYMBOL(mISDN_FsmAddTimer); @@ -167,11 +167,11 @@ mISDN_FsmRestartTimer(struct FsmTimer *ft, (long) ft, millisec, where); #endif - if (ft->tl.linked) - timer_exit(&ft->tl); +// if (ft->tl.linked) + osmo_timer_del(&ft->tl); ft->event = event; ft->arg = arg; - timer_init(&ft->tl, ft->func, ft); - timer_start(&ft->tl, (double)millisec / 1000.0); + osmo_timer_setup(&ft->tl, ft->func, ft); + osmo_timer_schedule(&ft->tl, millisec / 1000, (millisec % 1000) * 1000); } EXPORT_SYMBOL(mISDN_FsmRestartTimer); diff --git a/src/libmisdn/fsm.h b/src/libmisdn/fsm.h index dfa6e74..42b0e27 100644 --- a/src/libmisdn/fsm.h +++ b/src/libmisdn/fsm.h @@ -41,7 +41,7 @@ struct FsmNode { struct FsmTimer { struct FsmInst *fi; - struct timer tl; + struct osmo_timer_list tl; void *func; int event; void *arg; diff --git a/src/libmisdn/mISDNhw.h b/src/libmisdn/mISDNhw.h index 3897fd7..1d64f57 100644 --- a/src/libmisdn/mISDNhw.h +++ b/src/libmisdn/mISDNhw.h @@ -84,7 +84,7 @@ struct dchannel { void *l1; void *hw; int slot; /* multiport card channel slot */ -// struct timer_list timer; +// struct osmo_timer_list_list timer; /* receive data */ struct sk_buff *rx_skb; int maxlen; @@ -145,7 +145,7 @@ struct bchannel { u_int state; void *hw; int slot; /* multiport card channel slot */ -// struct timer_list timer; +// struct osmo_timer_list_list timer; /* receive data */ uint8_t fill[MISDN_BCH_FILL_SIZE]; struct sk_buff *rx_skb; diff --git a/src/libmisdn/mISDNif.h b/src/libmisdn/mISDNif.h index b99ccc1..d51ce6d 100644 --- a/src/libmisdn/mISDNif.h +++ b/src/libmisdn/mISDNif.h @@ -415,7 +415,7 @@ struct mISDN_ctrl_req { #include "skbuff.h" #include "printk.h" #include "bitops.h" -#include "container_of.h" +//#include "container_of.h" #include //#include @@ -518,12 +518,12 @@ struct mISDNchannel { }; struct mISDN_sock_list { - struct hlist_head head; + struct m_hlist_head head; rwlock_t lock; }; struct mISDN_sock { - struct hlist_node list; + struct m_hlist_node list; int sk_protocol; int sk_state; struct sk_buff_head sk_receive_queue; @@ -534,12 +534,12 @@ struct mISDN_sock { struct mISDN_dev_list { - struct hlist_head head; + struct m_hlist_head head; rwlock_t lock; }; struct mISDNdevice { - struct hlist_node list; + struct m_hlist_node list; struct mISDNchannel D; u_int id; u_int Dprotocols; diff --git a/src/libmisdn/mlist.h b/src/libmisdn/mlist.h index eed2813..5aadb7b 100644 --- a/src/libmisdn/mlist.h +++ b/src/libmisdn/mlist.h @@ -11,12 +11,12 @@ struct list_head { struct list_head *next, *prev; }; -struct hlist_head { - struct hlist_node *first; +struct m_hlist_head { + struct m_hlist_node *first; }; -struct hlist_node { - struct hlist_node *next, **pprev; +struct m_hlist_node { + struct m_hlist_node *next, **pprev; }; @@ -31,7 +31,7 @@ static inline void INIT_LIST_HEAD(struct list_head *list) list->prev = list; } -#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) +#define INIT_M_HLIST_HEAD(ptr) ((ptr)->first = NULL) /* * list_add_head - add a new entry on the top @@ -48,16 +48,16 @@ static inline void list_add_head(struct list_head *new, struct list_head *head) } /** - * hlist_add_head - add a new entry at the beginning of the hlist + * m_hlist_add_head - add a new entry at the beginning of the m_hlist * @n: new entry to be added - * @h: hlist head to add it after + * @h: m_hlist head to add it after * * Insert a new entry after the specified head. * This is good for implementing stacks. */ -static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) +static inline void m_hlist_add_head(struct m_hlist_node *n, struct m_hlist_head *h) { - struct hlist_node *first = h->first; + struct m_hlist_node *first = h->first; n->next = first; if (first) first->pprev = &n->next; @@ -94,10 +94,10 @@ static inline void list_del(struct list_head *entry) entry->prev = (void *)LIST_POISON2; } -static inline void hlist_del(struct hlist_node *n) +static inline void m_hlist_del(struct m_hlist_node *n) { - struct hlist_node *next = n->next; - struct hlist_node **pprev = n->pprev; + struct m_hlist_node *next = n->next; + struct m_hlist_node **pprev = n->pprev; *pprev = next; if (next) @@ -126,10 +126,10 @@ static inline int list_empty(const struct list_head *head) } /** - * hlist_empty - Is the specified hlist_head structure an empty hlist? + * m_hlist_empty - Is the specified m_hlist_head structure an empty m_hlist? * @h: Structure to check. */ -static inline int hlist_empty(const struct hlist_head *h) +static inline int m_hlist_empty(const struct m_hlist_head *h) { return !h->first; } @@ -178,21 +178,21 @@ static inline int hlist_empty(const struct hlist_head *h) #endif -#define hlist_entry(ptr, type, member) container_of(ptr,type,member) +#define m_hlist_entry(ptr, type, member) container_of(ptr,type,member) -#define hlist_entry_safe(ptr, type, member) \ +#define m_hlist_entry_safe(ptr, type, member) \ ({ typeof(ptr) ____ptr = (ptr); \ - ____ptr ? hlist_entry(____ptr, type, member) : NULL; \ + ____ptr ? m_hlist_entry(____ptr, type, member) : NULL; \ }) /** - * hlist_for_each_entry - iterate over list of given type + * m_hlist_for_each_entry - iterate over list of given type * @pos: the type * to use as a loop cursor. * @head: the head for your list. - * @member: the name of the hlist_node within the struct. + * @member: the name of the m_hlist_node within the struct. */ -#define hlist_for_each_entry(pos, head, member) \ - for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\ +#define m_hlist_for_each_entry(pos, head, member) \ + for (pos = m_hlist_entry_safe((head)->first, typeof(*(pos)), member);\ pos; \ - pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member)) + pos = m_hlist_entry_safe((pos)->member.next, typeof(*(pos)), member)) diff --git a/src/libmisdn/printk.c b/src/libmisdn/printk.c index 7199ef2..0cb155c 100644 --- a/src/libmisdn/printk.c +++ b/src/libmisdn/printk.c @@ -3,25 +3,37 @@ #include #include "printk.h" -void _printk(const char *file, const char *function, int line, const char *fmt, ...) +void _printk(const char *file, __attribute__((unused)) const char *function, int line, const char *fmt, ...) { - char buffer[4096], *b = buffer; - int s = sizeof(buffer) - 1; - int level = 1; + int level = LOGL_INFO; va_list args; - buffer[sizeof(buffer) - 1] = '\0'; - /* remove debug level from format */ if (fmt[0] >= '0' && fmt[0] <= '9') { - level = fmt[0] - '0'; + switch (fmt[0]) { + case '0': + case '1': + case '2': + case '3': + level = LOGL_ERROR; + break; + case '4': + case '5': + level = LOGL_NOTICE; + break; + case '6': + level = LOGL_INFO; + break; + case '7': + case '8': + case '9': + level = LOGL_DEBUG; + break; + } fmt++; } va_start(args, fmt); - vsnprintf(b, s, fmt, args); + LOGPSRC(DMISDN, level, file, line, fmt, args); va_end(args); - - _printdebug(file, function, line, DMISDN, level, NULL, "%s", b); } - diff --git a/src/libmisdn/printk.h b/src/libmisdn/printk.h index 6c1009b..d3ee068 100644 --- a/src/libmisdn/printk.h +++ b/src/libmisdn/printk.h @@ -3,13 +3,16 @@ #define MISDN_PRINTK_H #include -#include "../libdebug/debug.h" +#include "../liblogging/logging.h" -#define KERN_DEBUG "0" -#define KERN_INFO "1" -#define KERN_NOTICE "2" -#define KERN_WARNING "2" -#define KERN_ERR "3" +#define KERN_EMERG "0" /* system is unusable */ +#define KERN_ALERT "1" /* action must be taken immediately */ +#define KERN_CRIT "2" /* critical conditions */ +#define KERN_ERR "3" /* error conditions */ +#define KERN_WARNING "4" /* warning conditions */ +#define KERN_NOTICE "5" /* normal but significant condition */ +#define KERN_INFO "6" /* informational */ +#define KERN_DEBUG "7" /* debug-level messages */ #define printk(fmt, arg...) _printk(__FILE__, __FUNCTION__, __LINE__, fmt, ## arg) void _printk(const char *file, const char *function, int line, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 4, 5))); diff --git a/src/libmisdn/socket.c b/src/libmisdn/socket.c index 435564a..378b789 100644 --- a/src/libmisdn/socket.c +++ b/src/libmisdn/socket.c @@ -40,14 +40,14 @@ static void mISDN_sock_link(struct mISDN_sock_list *l, struct mISDN_sock *msk) { write_lock_bh(&l->lock); - hlist_add_head(&msk->list, &l->head); + m_hlist_add_head(&msk->list, &l->head); write_unlock_bh(&l->lock); } static void mISDN_sock_unlink(struct mISDN_sock_list __attribute__((unused)) *l, struct mISDN_sock *msk) { write_lock_bh(&l->lock); - hlist_del(&msk->list); + m_hlist_del(&msk->list); write_unlock_bh(&l->lock); } @@ -425,7 +425,7 @@ int mISDN_data_bind(void *inst, struct sockaddr *addr, int addr_len) if (msk->sk_protocol < ISDN_P_B_START) { read_lock_bh(&data_sockets.lock); - hlist_for_each_entry(cmsk, &data_sockets.head, list) { + m_hlist_for_each_entry(cmsk, &data_sockets.head, list) { if (msk == cmsk) continue; if (cmsk->dev != msk->dev) diff --git a/src/libmisdn/stack.c b/src/libmisdn/stack.c index 825267a..2f232b7 100644 --- a/src/libmisdn/stack.c +++ b/src/libmisdn/stack.c @@ -58,7 +58,7 @@ send_socklist(struct mISDN_sock_list *sl, struct sk_buff *skb) struct sk_buff *cskb = NULL; read_lock(&sl->lock); - hlist_for_each_entry(msk, &sl->head, list) { + m_hlist_for_each_entry(msk, &sl->head, list) { if (msk->sk_state != MISDN_BOUND) continue; if (!cskb) @@ -144,13 +144,13 @@ send_msg_to_layer(struct mISDNstack *st, struct sk_buff *skb) printk(KERN_DEBUG "%s prim(%x) id(%x) lm(%x) %p\n", __func__, hh->prim, hh->id, lm, skb); if (lm == 0x1) { - if (!hlist_empty(&st->l1sock.head)) { + if (!m_hlist_empty(&st->l1sock.head)) { __net_timestamp(skb); send_socklist(&st->l1sock, skb); } return st->layer1->send(st->layer1, skb); } else if (lm == 0x2) { - if (!hlist_empty(&st->l1sock.head)) + if (!m_hlist_empty(&st->l1sock.head)) send_socklist(&st->l1sock, skb); send_layer2(st, skb); return 0; @@ -379,7 +379,7 @@ create_stack(struct mISDNdevice *dev) } newst->dev = dev; INIT_LIST_HEAD(&newst->layer2); - INIT_HLIST_HEAD(&newst->l1sock.head); + INIT_M_HLIST_HEAD(&newst->l1sock.head); rwlock_init(&newst->l1sock.lock); // init_waitqueue_head(&newst->workq); skb_queue_head_init(&newst->msgq); @@ -450,7 +450,7 @@ connect_layer1(struct mISDNdevice *dev, struct mISDNchannel *ch, if (err) return err; write_lock_bh(&dev->D.st->l1sock.lock); - hlist_add_head(&msk->list, &dev->D.st->l1sock.head); + m_hlist_add_head(&msk->list, &dev->D.st->l1sock.head); write_unlock_bh(&dev->D.st->l1sock.lock); break; default: @@ -592,7 +592,7 @@ delete_channel(struct mISDNchannel *ch) case ISDN_P_NT_E1: case ISDN_P_TE_E1: write_lock_bh(&ch->st->l1sock.lock); - hlist_del(&msk->list); + m_hlist_del(&msk->list); write_unlock_bh(&ch->st->l1sock.lock); ch->st->dev->D.ctrl(&ch->st->dev->D, CLOSE_CHANNEL, NULL); break; @@ -649,7 +649,7 @@ delete_stack(struct mISDNdevice *dev) if (!list_empty(&st->layer2)) printk(KERN_WARNING "%s: layer2 list not empty\n", __func__); - if (!hlist_empty(&st->l1sock.head)) + if (!m_hlist_empty(&st->l1sock.head)) printk(KERN_WARNING "%s: layer1 list not empty\n", __func__); kfree(st); diff --git a/src/libmisdn/timer.h b/src/libmisdn/timer.h index 4ab600e..ad31d42 100644 --- a/src/libmisdn/timer.h +++ b/src/libmisdn/timer.h @@ -2,14 +2,14 @@ #ifndef _MISDN_TIMER_H #define _MISDN_TIMER_H -#include "../libtimer/timer.h" +#include #if 0 #define timer_list timer #define timer_setup(ti, fu, flags) timer_init(ti, fu, NULL) -#define add_timer timer_start -#define del_timer timer_stop -#define timer_pending timer_running +#define add_timer osmo_timer_schedule +#define del_timer osmo_timer_del +#define timer_pending osmo_timer_pending #endif #define from_timer(var, callback_timer, timer_fieldname) \ diff --git a/src/liboptions/options.c b/src/liboptions/options.c index d49e698..cc19b89 100644 --- a/src/liboptions/options.c +++ b/src/liboptions/options.c @@ -23,7 +23,7 @@ #include #include #include "options.h" -#include "../libdebug/debug.h" +#include "../liblogging/logging.h" typedef struct option { struct option *next; @@ -47,7 +47,7 @@ char *options_strdup(const char *s) o = malloc(sizeof(struct options_strdup_entry) + strlen(s)); if (!o) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "No mem!\n"); + LOGP(DOPTIONS, LOGL_ERROR, "No mem!\n"); abort(); } o->next = options_strdup_list; @@ -64,19 +64,19 @@ void option_add(int short_option, const char *long_option, int parameter_count) /* check if option already exists or is not allowed */ for (option = option_head; option; option = option->next) { if (!strcmp(option->long_option, "config")) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Option '%s' is not allowed to add, please fix!\n", option->long_option); + LOGP(DOPTIONS, LOGL_ERROR, "Option '%s' is not allowed to add, please fix!\n", option->long_option); abort(); } if (option->short_option == short_option || !strcmp(option->long_option, long_option)) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Option '%s' added twice, please fix!\n", option->long_option); + LOGP(DOPTIONS, LOGL_ERROR, "Option '%s' added twice, please fix!\n", option->long_option); abort(); } } option = calloc(1, sizeof(*option)); if (!option) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "No mem!\n"); + LOGP(DOPTIONS, LOGL_ERROR, "No mem!\n"); abort(); } @@ -115,7 +115,7 @@ int options_config_file(int argc, char *argv[], const char *config_file, int (*h /* open config file */ fp = fopen(config, "r"); if (!fp) { - PDEBUG(DOPTIONS, DEBUG_INFO, "Config file '%s' seems not to exist, using command line options only.\n", config); + LOGP(DOPTIONS, LOGL_INFO, "Config file '%s' seems not to exist, using command line options only.\n", config); return 1; } @@ -201,21 +201,21 @@ int options_config_file(int argc, char *argv[], const char *config_file, int (*h /* search option */ for (option = option_head; option; option = option->next) { if (opt[0] == option->short_option && opt[1] == '\0') { - PDEBUG(DOPTIONS, DEBUG_INFO, "Config file option '%s' ('%s'), parameter%s\n", opt, option->long_option, params); + LOGP(DOPTIONS, LOGL_INFO, "Config file option '%s' ('%s'), parameter%s\n", opt, option->long_option, params); break; } if (!strcmp(opt, option->long_option)) { - PDEBUG(DOPTIONS, DEBUG_INFO, "Config file option '%s', parameter%s\n", opt, params); + LOGP(DOPTIONS, LOGL_INFO, "Config file option '%s', parameter%s\n", opt, params); break; } } if (!option) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given option '%s' in config file '%s' at line %d is not a valid option, use '-h' for help!\n", opt, config_file, line); + LOGP(DOPTIONS, LOGL_ERROR, "Given option '%s' in config file '%s' at line %d is not a valid option, use '-h' for help!\n", opt, config_file, line); rc = -EINVAL; goto done; } if (option->parameter_count != i) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given option '%s' in config file '%s' at line %d requires %d parameter(s), use '-h' for help!\n", opt, config_file, line, option->parameter_count); + LOGP(DOPTIONS, LOGL_ERROR, "Given option '%s' in config file '%s' at line %d requires %d parameter(s), use '-h' for help!\n", opt, config_file, line, option->parameter_count); return -EINVAL; } rc = handle_options(option->short_option, 0, args); @@ -242,11 +242,11 @@ int options_command_line(int argc, char *argv[], int (*handle_options)(int short /* --config */ if (!strcmp(argv[argi], "--config")) { if (argi > 1) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given command line option '%s' must be the first option specified, use '-h' for help!\n", argv[argi]); + LOGP(DOPTIONS, LOGL_ERROR, "Given command line option '%s' must be the first option specified, use '-h' for help!\n", argv[argi]); return -EINVAL; } if (argc <= 2) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given command line option '%s' requires 1 parameter, use '-h' for help!\n", argv[argi]); + LOGP(DOPTIONS, LOGL_ERROR, "Given command line option '%s' requires 1 parameter, use '-h' for help!\n", argv[argi]); return -EINVAL; } argi += 1; @@ -255,7 +255,7 @@ int options_command_line(int argc, char *argv[], int (*handle_options)(int short if (argv[argi][0] == '-') { if (argv[argi][1] != '-') { if (strlen(argv[argi]) != 2) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given command line option '%s' exceeds one character, use '-h' for help!\n", argv[argi]); + LOGP(DOPTIONS, LOGL_ERROR, "Given command line option '%s' exceeds one character, use '-h' for help!\n", argv[argi]); return -EINVAL; } /* -x */ @@ -265,9 +265,9 @@ int options_command_line(int argc, char *argv[], int (*handle_options)(int short params[0] = '\0'; for (i = 0; i < option->parameter_count; i++) sprintf(strchr(params, '\0'), " '%s'", argv[argi + 1 + i]); - PDEBUG(DOPTIONS, DEBUG_INFO, "Command line option '%s' ('--%s'), parameter%s\n", argv[argi], option->long_option, params); + LOGP(DOPTIONS, LOGL_INFO, "Command line option '%s' ('--%s'), parameter%s\n", argv[argi], option->long_option, params); } else - PDEBUG(DOPTIONS, DEBUG_INFO, "Command line option '%s' ('--%s')\n", argv[argi], option->long_option); + LOGP(DOPTIONS, LOGL_INFO, "Command line option '%s' ('--%s')\n", argv[argi], option->long_option); break; } } @@ -279,19 +279,19 @@ int options_command_line(int argc, char *argv[], int (*handle_options)(int short params[0] = '\0'; for (i = 0; i < option->parameter_count; i++) sprintf(strchr(params, '\0'), " '%s'", argv[argi + 1 + i]); - PDEBUG(DOPTIONS, DEBUG_INFO, "Command line option '%s', parameter%s\n", argv[argi], params); + LOGP(DOPTIONS, LOGL_INFO, "Command line option '%s', parameter%s\n", argv[argi], params); } else - PDEBUG(DOPTIONS, DEBUG_INFO, "Command line option '%s'\n", argv[argi]); + LOGP(DOPTIONS, LOGL_INFO, "Command line option '%s'\n", argv[argi]); break; } } } if (!option) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given command line option '%s' is not a valid option, use '-h' for help!\n", argv[argi]); + LOGP(DOPTIONS, LOGL_ERROR, "Given command line option '%s' is not a valid option, use '-h' for help!\n", argv[argi]); return -EINVAL; } if (argi + option->parameter_count >= argc) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given command line option '%s' requires %d parameter(s), use '-h' for help!\n", argv[argi], option->parameter_count); + LOGP(DOPTIONS, LOGL_ERROR, "Given command line option '%s' requires %d parameter(s), use '-h' for help!\n", argv[argi], option->parameter_count); return -EINVAL; } rc = handle_options(option->short_option, argi + 1, argv); @@ -306,7 +306,7 @@ int options_command_line(int argc, char *argv[], int (*handle_options)(int short /* no more options, so we check if there is an option after a non-option parameter */ for (i = argi; i < argc; i++) { if (argv[i][0] == '-') { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given command line option '%s' behind command line parameter '%s' not allowed! Please put all command line options before command line parameter(s).\n", argv[i], argv[argi]); + LOGP(DOPTIONS, LOGL_ERROR, "Given command line option '%s' behind command line parameter '%s' not allowed! Please put all command line options before command line parameter(s).\n", argv[i], argv[argi]); return -EINVAL; } } diff --git a/src/libosmocc/Makefile.am b/src/libosmocc/Makefile.am deleted file mode 100644 index 27c0f6c..0000000 --- a/src/libosmocc/Makefile.am +++ /dev/null @@ -1,15 +0,0 @@ -AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) - -noinst_LIBRARIES = libosmocc.a - -libosmocc_a_SOURCES = \ - message.c \ - socket.c \ - cause.c \ - screen.c \ - endpoint.c \ - session.c \ - sdp.c \ - rtp.c \ - helper.c - diff --git a/src/libosmocc/cause.c b/src/libosmocc/cause.c deleted file mode 100644 index df2b07b..0000000 --- a/src/libosmocc/cause.c +++ /dev/null @@ -1,251 +0,0 @@ -/* OSMO-CC Processing: convert causes - * - * (C) 2019 by Andreas Eversberg - * All Rights Reserved - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include "message.h" -#include "cause.h" - -/* stolen from freeswitch, did some corrections */ -/* map sip responses to QSIG cause codes ala RFC4497 section 8.4.4 */ -static uint8_t status2isdn_cause(uint16_t status) -{ - switch (status) { - case 200: - return 16; //SWITCH_CAUSE_NORMAL_CLEARING; - case 401: - case 402: - case 403: - case 407: - case 603: - return 21; //SWITCH_CAUSE_CALL_REJECTED; - case 404: - case 485: - case 604: - return 1; //SWITCH_CAUSE_UNALLOCATED_NUMBER; - case 408: - case 504: - return 102; //SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE; - case 410: - return 22; //SWITCH_CAUSE_NUMBER_CHANGED; - case 413: - case 414: - case 416: - case 420: - case 421: - case 423: - case 505: - case 513: - return 127; //SWITCH_CAUSE_INTERWORKING; - case 480: - return 18; //SWITCH_CAUSE_NO_USER_RESPONSE; - case 400: - case 481: - case 500: - case 503: - return 41; //SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE; - case 486: - case 600: - return 17; //SWITCH_CAUSE_USER_BUSY; - case 484: - return 28; //SWITCH_CAUSE_INVALID_NUMBER_FORMAT; - case 488: - case 606: - return 65; //SWITCH_CAUSE_BERER_CAPABILITY_NOT_IMPLEMENTED; - case 502: - return 38; //SWITCH_CAUSE_NETWORK_OUT_OF_ORDER; - case 405: - return 63; //SWITCH_CAUSE_SERVICE_UNAVAILABLE; - case 406: - case 415: - case 501: - return 79; //SWITCH_CAUSE_SERVICE_NOT_IMPLEMENTED; - case 482: - case 483: - return 25; //SWITCH_CAUSE_EXCHANGE_ROUTING_ERROR; - case 487: - return 31; //??? SWITCH_CAUSE_ORIGINATOR_CANCEL; (not specified) - default: - return 31; //SWITCH_CAUSE_NORMAL_UNSPECIFIED; - } -} - -static uint16_t isdn2status_cause(uint8_t cause, uint8_t location) -{ - switch (cause) { - case 1: - return 404; - case 2: - return 404; - case 3: - return 404; - case 17: - return 486; - case 18: - return 408; - case 19: - return 480; - case 20: - return 480; - case 21: - if (location == OSMO_CC_LOCATION_USER) - return 603; - return 403; - case 22: - //return 301; - return 410; - case 23: - return 410; - case 26: - return 404; - case 27: - return 502; - case 28: - return 484; - case 29: - return 501; - case 31: - return 480; - case 34: - return 503; - case 38: - return 503; - case 41: - return 503; - case 42: - return 503; - case 47: - return 503; - case 55: - return 403; - case 57: - return 403; - case 58: - return 503; - case 65: - return 488; - case 69: - return 501; - case 70: - return 488; - case 79: - return 501; - case 87: - return 403; - case 88: - return 503; - case 102: - return 504; - case 111: - return 500; - case 127: - return 500; - default: - return 468; - } -} - -static uint8_t socket2isdn_cause(uint8_t sock) -{ - switch (sock) { - case OSMO_CC_SOCKET_CAUSE_FAILED: - return 47; - case OSMO_CC_SOCKET_CAUSE_BROKEN_PIPE: - return 41; - case OSMO_CC_SOCKET_CAUSE_VERSION_MISMATCH: - return 38; - case OSMO_CC_SOCKET_CAUSE_TIMEOUT: - return 41; - default: - return 31; - } -} - -void osmo_cc_convert_cause(struct osmo_cc_ie_cause *cause) -{ - /* complete cause, from socket cause */ - if (cause->socket_cause && cause->isdn_cause == 0 && ntohs(cause->sip_cause_networkorder) == 0) - cause->isdn_cause = socket2isdn_cause(cause->socket_cause); - - /* convert ISDN cause to SIP cause */ - if (cause->isdn_cause && ntohs(cause->sip_cause_networkorder) == 0) { - cause->sip_cause_networkorder = htons(isdn2status_cause(cause->isdn_cause, cause->location)); - } - - /* convert SIP cause to ISDN cause */ - if (ntohs(cause->sip_cause_networkorder) && cause->isdn_cause == 0) { - cause->isdn_cause = status2isdn_cause(ntohs(cause->sip_cause_networkorder)); - } - - /* no cause at all: use Normal Call Clearing */ - if (cause->isdn_cause == 0 && ntohs(cause->sip_cause_networkorder) == 0) { - cause->isdn_cause = OSMO_CC_ISDN_CAUSE_NORM_CALL_CLEAR; - cause->sip_cause_networkorder = htons(486); - } -} - -void osmo_cc_convert_cause_msg(osmo_cc_msg_t *msg) -{ - void *ie; - uint8_t type; - uint16_t length; - void *value; - - /* search for (all) cause IE and convert the values, if needed */ - ie = msg->data; - while ((value = osmo_cc_msg_sep_ie(msg, &ie, &type, &length))) { - if (type == OSMO_CC_IE_CAUSE && length >= sizeof(struct osmo_cc_ie_cause)) { - osmo_cc_convert_cause(value); - } - } -} - -uint8_t osmo_cc_collect_cause(uint8_t old_cause, uint8_t new_cause) -{ - /* first cause */ - if (old_cause == 0) - return new_cause; - - /* first prio: return 17 */ - if (old_cause == OSMO_CC_ISDN_CAUSE_USER_BUSY - || new_cause == OSMO_CC_ISDN_CAUSE_USER_BUSY) - return OSMO_CC_ISDN_CAUSE_USER_BUSY; - - /* second prio: return 21 */ - if (old_cause == OSMO_CC_ISDN_CAUSE_CALL_REJECTED - || new_cause == OSMO_CC_ISDN_CAUSE_CALL_REJECTED) - return OSMO_CC_ISDN_CAUSE_CALL_REJECTED; - - /* third prio: return other than 88 and 18 (what ever was first) */ - if (old_cause != OSMO_CC_ISDN_CAUSE_INCOMPAT_DEST - && old_cause != OSMO_CC_ISDN_CAUSE_USER_NOTRESPOND) - return old_cause; - if (new_cause != OSMO_CC_ISDN_CAUSE_INCOMPAT_DEST - && new_cause != OSMO_CC_ISDN_CAUSE_USER_NOTRESPOND) - return new_cause; - - /* fourth prio: return 88 */ - if (old_cause == OSMO_CC_ISDN_CAUSE_INCOMPAT_DEST - || new_cause == OSMO_CC_ISDN_CAUSE_INCOMPAT_DEST) - return OSMO_CC_ISDN_CAUSE_INCOMPAT_DEST; - - /* fith prio: return 18 */ - return OSMO_CC_ISDN_CAUSE_USER_NOTRESPOND; -} - diff --git a/src/libosmocc/cause.h b/src/libosmocc/cause.h deleted file mode 100644 index 22319f4..0000000 --- a/src/libosmocc/cause.h +++ /dev/null @@ -1,5 +0,0 @@ - -void osmo_cc_convert_cause(struct osmo_cc_ie_cause *cause); -void osmo_cc_convert_cause_msg(osmo_cc_msg_t *msg); -uint8_t osmo_cc_collect_cause(uint8_t old_cause, uint8_t new_cause); - diff --git a/src/libosmocc/endpoint.c b/src/libosmocc/endpoint.c deleted file mode 100644 index e78b3ed..0000000 --- a/src/libosmocc/endpoint.c +++ /dev/null @@ -1,1585 +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 "../libselect/select.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) { - LOGP(DCC, LOGL_ERROR, "No memory for call process instance.\n"); - abort(); - } - - LOGP(DCC, LOGL_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; - - LOGP(DCC, LOGL_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) -{ - LOGP(DCC, LOGL_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)) { - LOGP(DCC, LOGL_ERROR, "Host IP in given address '%s' is invalid.\n", address); - return -EINVAL; - } - portstring = osmo_cc_port_of_address(address); - if (!portstring) { - LOGP(DCC, LOGL_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) { - LOGP(DCC, LOGL_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; - } - LOGP(DCC, LOGL_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; - LOGP(DCC, LOGL_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; - LOGP(DCC, LOGL_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]) { - LOGP(DCC, LOGL_ERROR, "No remote peer attached, rejecting call.\n"); - goto reject; - } - if (!att) { - LOGP(DCC, LOGL_ERROR, "No remote peer attached for given interface '%s', rejecting call.\n", interface); - goto reject; - } - host = att->attached_host; - port = att->attached_port; - LOGP(DCC, LOGL_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(void *data) -{ - osmo_cc_endpoint_t *ep = data; - osmo_cc_call_t *call; - osmo_cc_msg_t *msg; - - LOGP(DCC, LOGL_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) -{ - LOGP(DCC, LOGL_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); - LOGP(DCC, LOGL_INFO, "Attachment to remote peer \"%s\" failed, retrying.\n", call->ep->remote_address); - } - - if (call->attached_name) - LOGP(DCC, LOGL_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]) { - LOGP(DCC, LOGL_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; - LOGP(DCC, LOGL_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) { - LOGP(DCC, LOGL_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); - } - - LOGP(DCC, LOGL_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; - LOGP(DCC, LOGL_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 modify_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* to lower layer */ - forward_to_ll(call, msg); -} - -static void modify_cnf(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* to upper layer */ - forward_to_ul(call, msg); -} - -static void modify_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* to upper layer */ - forward_to_ul(call, msg); -} - -static void modify_rsp(osmo_cc_call_t *call, osmo_cc_msg_t *msg) -{ - /* to lower layer */ - forward_to_ll(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; - LOGP(DCC, LOGL_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; - LOGP(DCC, LOGL_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; - LOGP(DCC, LOGL_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; - LOGP(DCC, LOGL_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; - LOGP(DCC, LOGL_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; - LOGP(DCC, LOGL_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type)); - call->upper_layer_released = 1; - - /* to lower layer */ - forward_to_ll(call, msg); -} - -#define SBIT(a) (1 << a) -#define ALL_STATES (~0) - -static struct statemachine { - uint32_t states; - int type; - void (*action)(osmo_cc_call_t *call, osmo_cc_msg_t *msg); -} statemachine_list[] = { - /* attachment states */ - {SBIT(OSMO_CC_STATE_ATTACH_SENT), - OSMO_CC_MSG_ATTACH_RSP, attach_rsp}, - {SBIT(OSMO_CC_STATE_ATTACH_OUT) | SBIT(OSMO_CC_STATE_ATTACH_SENT), - OSMO_CC_MSG_REL_REQ, attach_rel}, - {SBIT(OSMO_CC_STATE_IDLE), - OSMO_CC_MSG_ATTACH_REQ, attach_req}, - {SBIT(OSMO_CC_STATE_ATTACH_IN), - OSMO_CC_MSG_REL_REQ, attach_rel}, - - /* call setup toward lower layer protocol */ - {SBIT(OSMO_CC_STATE_IDLE), - OSMO_CC_MSG_SETUP_REQ, setup_req}, - {SBIT(OSMO_CC_STATE_INIT_OUT), - OSMO_CC_MSG_SETUP_ACK_IND, setup_ack_ind}, - {SBIT(OSMO_CC_STATE_INIT_OUT) | SBIT(OSMO_CC_STATE_OVERLAP_OUT), - OSMO_CC_MSG_PROC_IND, proc_ind}, - {SBIT(OSMO_CC_STATE_INIT_OUT) | SBIT(OSMO_CC_STATE_OVERLAP_OUT) | - SBIT(OSMO_CC_STATE_PROCEEDING_OUT), - OSMO_CC_MSG_ALERT_IND, alert_ind}, - {SBIT(OSMO_CC_STATE_INIT_OUT) | SBIT(OSMO_CC_STATE_OVERLAP_OUT) | - SBIT(OSMO_CC_STATE_PROCEEDING_OUT) | SBIT(OSMO_CC_STATE_ALERTING_OUT), - OSMO_CC_MSG_SETUP_CNF, setup_cnf}, - {SBIT(OSMO_CC_STATE_OVERLAP_OUT) | SBIT(OSMO_CC_STATE_PROCEEDING_OUT) | - SBIT(OSMO_CC_STATE_ALERTING_OUT), - OSMO_CC_MSG_PROGRESS_IND, progress_ind}, - {SBIT(OSMO_CC_STATE_OVERLAP_OUT), - OSMO_CC_MSG_INFO_REQ, info_req}, - {SBIT(OSMO_CC_STATE_PROCEEDING_OUT) | SBIT(OSMO_CC_STATE_ALERTING_OUT), - OSMO_CC_MSG_NOTIFY_IND, notify_ind}, - {SBIT(OSMO_CC_STATE_CONNECTING_OUT), - OSMO_CC_MSG_SETUP_COMP_REQ, setup_comp_req}, - - /* call setup from lower layer protocol */ - {SBIT(OSMO_CC_STATE_IDLE), - OSMO_CC_MSG_SETUP_IND, setup_ind}, - {SBIT(OSMO_CC_STATE_INIT_IN), - OSMO_CC_MSG_SETUP_ACK_REQ, setup_ack_req}, - {SBIT(OSMO_CC_STATE_INIT_IN) | SBIT(OSMO_CC_STATE_OVERLAP_IN), - OSMO_CC_MSG_PROC_REQ, proc_req}, - {SBIT(OSMO_CC_STATE_INIT_IN) | SBIT(OSMO_CC_STATE_OVERLAP_IN) | - SBIT(OSMO_CC_STATE_PROCEEDING_IN), - OSMO_CC_MSG_ALERT_REQ, alert_req}, - {SBIT(OSMO_CC_STATE_INIT_IN) | SBIT(OSMO_CC_STATE_OVERLAP_IN) | - SBIT(OSMO_CC_STATE_PROCEEDING_IN) | SBIT(OSMO_CC_STATE_ALERTING_IN), - OSMO_CC_MSG_SETUP_RSP, setup_rsp}, - {SBIT(OSMO_CC_STATE_OVERLAP_IN) | SBIT(OSMO_CC_STATE_PROCEEDING_IN) | - SBIT(OSMO_CC_STATE_ALERTING_IN), - OSMO_CC_MSG_PROGRESS_REQ, progress_req}, - {SBIT(OSMO_CC_STATE_OVERLAP_IN), - OSMO_CC_MSG_INFO_IND, info_ind}, - {SBIT(OSMO_CC_STATE_PROCEEDING_IN) | SBIT(OSMO_CC_STATE_ALERTING_IN), - OSMO_CC_MSG_NOTIFY_REQ, notify_req}, - {SBIT(OSMO_CC_STATE_CONNECTING_IN), - OSMO_CC_MSG_SETUP_COMP_IND, setup_comp_ind}, - - /* active state */ - {SBIT(OSMO_CC_STATE_ACTIVE), - OSMO_CC_MSG_NOTIFY_IND, notify_ind}, - {SBIT(OSMO_CC_STATE_ACTIVE), - OSMO_CC_MSG_NOTIFY_REQ, notify_req}, - {SBIT(OSMO_CC_STATE_ACTIVE), - OSMO_CC_MSG_INFO_IND, info_ind}, - {SBIT(OSMO_CC_STATE_ACTIVE), - OSMO_CC_MSG_INFO_REQ, info_req}, - {SBIT(OSMO_CC_STATE_ACTIVE), - OSMO_CC_MSG_MODIFY_REQ, modify_req}, - {SBIT(OSMO_CC_STATE_ACTIVE), - OSMO_CC_MSG_MODIFY_CNF, modify_cnf}, - {SBIT(OSMO_CC_STATE_ACTIVE), - OSMO_CC_MSG_MODIFY_IND, modify_ind}, - {SBIT(OSMO_CC_STATE_ACTIVE), - OSMO_CC_MSG_MODIFY_RSP, modify_rsp}, - - /* 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) { - LOGP(DCC, LOGL_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; - } - - LOGP(DCC, LOGL_INFO, "Handle message %s at state %s (callref %d)\n", - osmo_cc_msg_value2name(msg->type), state_names[call->state], call->callref); - if (debuglevel <= LOGL_INFO) - osmo_cc_debug_ie(msg, LOGL_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)) { - LOGP(DCC, LOGL_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)) { - LOGP(DCC, LOGL_ERROR, "Received message from socket that is not an _REQ nor _RSP, please fix!\n"); - osmo_cc_free_msg(msg); - return; - } - - call = osmo_cc_call_by_callref(ep, callref); - if (call) { - /* if we are not in INIT-IN state, we change a CC-REJ-REQ into CC-REL_REQ. - * this happens, if the socket fails. - */ - if (call->state != OSMO_CC_STATE_INIT_IN - && msg->type == OSMO_CC_MSG_REJ_REQ) - msg->type = OSMO_CC_MSG_REL_REQ; - - osmo_cc_msg_list_enqueue(&call->sock_queue, msg, call->callref); - return; - } - - /* if no ref exists */ - - /* reject and release are ignored */ - if (msg->type == OSMO_CC_MSG_REJ_REQ - || msg->type == OSMO_CC_MSG_REL_REQ) { - osmo_cc_free_msg(msg); - return; - } - - /* reject if not a setup/attach or release message */ - if (msg->type != OSMO_CC_MSG_SETUP_REQ - && msg->type != OSMO_CC_MSG_ATTACH_REQ) { - sock_reject_msg(&ep->os, callref, ep->serving_location, 0, OSMO_CC_ISDN_CAUSE_INVAL_CALLREF, 0); - osmo_cc_free_msg(msg); - return; - } - - /* create call instance with one socket reference */ - call = call_new(ep, callref); - - osmo_cc_msg_list_enqueue(&call->sock_queue, msg, call->callref); -} - -static void osmo_cc_help_name(void) -{ - printf("Name options:\n\n"); - - printf("name \n"); - - printf("Allows to override endpoint name given by application.\n"); -} - -static int osmo_cc_set_name(osmo_cc_endpoint_t *ep, const char *text) -{ - if (!strncasecmp(text, "name", 4)) { - text += 4; - /* remove spaces after keyword */ - while (*text) { - if (*text > 32) - break; - text++; - } - } else { - LOGP(DCC, LOGL_ERROR, "Invalid name definition '%s'\n", text); - return -EINVAL; - } - - free((char *)ep->local_name); - ep->local_name = strdup(text); - - return 0; -} - -static void osmo_cc_help_address(void) -{ - printf("Address options:\n\n"); - - printf("local :\n"); - printf("local []:\n"); - printf("remote :\n"); - printf("remote []:\n\n"); - printf("remote auto\n\n"); - printf("remote none\n\n"); - - printf("These options can be used to define local and remote IP and port for the socket\n"); - printf("interface. Note that IPv6 addresses must be enclosed by '[' and ']'.\n\n"); - - printf("If no local address was given, the IPv4 loopback IP and port %d is used. If\n", OSMO_CC_DEFAULT_PORT); - printf("this port is already in use, the first free higher port is used.\n\n"); - - printf("If no remote address is given, the local IP is used. If the local port is %d,\n", OSMO_CC_DEFAULT_PORT); - printf("the remote port will be %d. If not, the remote port will be %d. This way it is\n", OSMO_CC_DEFAULT_PORT + 1, OSMO_CC_DEFAULT_PORT); - printf("possible to link two interfaces without any IP configuration required.\n\n"); - - printf("Use 'remote auto' to enable and 'remote none' to disable. This can be useful to\n"); - printf("override application default.\n\n"); -} - -static int osmo_cc_set_address(osmo_cc_endpoint_t *ep, const char *text) -{ - const char **address_p, **host_p; - uint16_t *port_p; - int local = 0; - int rc; - - if (!strncasecmp(text, "local", 5)) { - text += 5; - /* remove spaces after keyword */ - while (*text) { - if (*text > 32) - break; - text++; - } - address_p = &ep->local_address; - host_p = &ep->local_host; - port_p = &ep->local_port; - local = 1; - } else if (!strncasecmp(text, "remote", 6)) { - text += 6; - /* remove spaces after keyword */ - while (*text) { - if (*text > 32) - break; - text++; - } - if (!strcasecmp(text, "auto")) { - LOGP(DCC, LOGL_DEBUG, "setting automatic remote peer selection\n"); - ep->remote_auto = 1; - return 0; - } - if (!strcasecmp(text, "none")) { - LOGP(DCC, LOGL_DEBUG, "disable automatic remote peer selection\n"); - ep->remote_auto = 0; - return 0; - } - ep->remote_auto = 0; - address_p = &ep->remote_address; - host_p = &ep->remote_host; - port_p = &ep->remote_port; - } else { - LOGP(DCC, LOGL_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) { - LOGP(DCC, LOGL_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 { - LOGP(DCC, LOGL_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) { - LOGP(DCC, LOGL_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') { - LOGP(DCC, LOGL_ERROR, "Given 'from' port in '%s' is invalid.\n", text); - return -EINVAL; - } - from = from * 10 + *text - '0'; - text++; - } - - /* remove spaces after keyword */ - while (*text) { - if (*text > 32) - break; - text++; - } - - /* to port */ - while (*text > ' ') { - if (*text < '0' || *text > '9') { - LOGP(DCC, LOGL_ERROR, "Given 'to' port in '%s' is invalid.\n", text); - return -EINVAL; - } - to = to * 10 + *text - '0'; - text++; - } - - osmo_cc_set_rtp_ports(&ep->session_config, from, to); - return 0; - } - - return -EINVAL; -} - -void osmo_cc_help(void) -{ - osmo_cc_help_name(); - osmo_cc_help_address(); - osmo_cc_help_rtp(); - osmo_cc_help_screen(); -} - -/* create a new endpoint instance */ -int osmo_cc_new(osmo_cc_endpoint_t *ep, const char *version, const char *name, uint8_t serving_location, void (*ll_msg_cb)(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg), void (*ul_msg_cb)(osmo_cc_call_t *call, osmo_cc_msg_t *msg), void *priv, int argc, const char *argv[]) -{ - osmo_cc_endpoint_t **epp; - int rc; - int i; - - LOGP(DCC, LOGL_DEBUG, "Creating new endpoint instance.\n"); - - if (!!strcmp(version, OSMO_CC_VERSION)) { - LOGP(DCC, LOGL_ERROR, "Application was compiled for different Osmo-CC version.\n"); - return OSMO_CC_RC_VERSION_MISMATCH; - } - - memset(ep, 0, sizeof(*ep)); - - /* attach to list */ - epp = &osmo_cc_endpoint_list; - while (*epp) - epp = &((*epp)->next); - *epp = ep; - - if (name) - ep->local_name = strdup(name); - ep->ll_msg_cb = ll_msg_cb; - ep->ul_msg_cb = ul_msg_cb; - ep->serving_location = serving_location; - ep->priv = priv; - - osmo_cc_set_local_peer(&ep->session_config, osmo_cc_session_nettype_inet, osmo_cc_session_addrtype_ipv4, "127.0.0.1"); - osmo_cc_set_rtp_ports(&ep->session_config, 16384, 32767); - - /* apply args */ - for (i = 0; i < argc; i++) { - if (!strncasecmp(argv[i], "name", 4)) { - rc = osmo_cc_set_name(ep, argv[i]); - if (rc < 0) { - return rc; - } - } else - if (!strncasecmp(argv[i], "local", 5)) { - rc = osmo_cc_set_address(ep, argv[i]); - if (rc < 0) { - return rc; - } - } else - if (!strncasecmp(argv[i], "remote", 6)) { - rc = osmo_cc_set_address(ep, argv[i]); - if (rc < 0) { - return rc; - } - } else - if (!strncasecmp(argv[i], "rtp", 3)) { - rc = osmo_cc_set_rtp(ep, argv[i]); - if (rc < 0) { - return rc; - } - } else - if (!strncasecmp(argv[i], "screen", 6)) { - rc = osmo_cc_add_screen(ep, argv[i]); - if (rc < 0) { - return rc; - } - } else { - LOGP(DCC, LOGL_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"; - LOGP(DCC, LOGL_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); - LOGP(DCC, LOGL_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; - LOGP(DCC, LOGL_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.data); - } - } - - return 0; -} - -/* destroy an endpoint instance */ -void osmo_cc_delete(osmo_cc_endpoint_t *ep) -{ - osmo_cc_endpoint_t **epp; - - LOGP(DCC, LOGL_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)) { - LOGP(DCC, LOGL_ERROR, "String way too long!\n"); - return NULL; - } - - if (address[0] == '[' && (p = strchr(address, ']'))) { - memcpy(host, address + 1, p - address - 1); - host[p - address - 1] = '\0'; - return host; - } - - strcpy(host, address); - if ((p = strchr(host, ':'))) - *p = '\0'; - - return host; -} - -/* get port from address */ -const char *osmo_cc_port_of_address(const char *address) -{ - const char *p; - int i; - - if (address[0] == '[' && (p = strchr(address, ']'))) - address = p + 1; - - if (!(p = strchr(address, ':'))) - return NULL; - p++; - - /* check for zero */ - if (p[0] == '0') - return NULL; - - /* check for digits */ - for (i = 0; i < (int)strlen(p); i++) { - if (p[i] < '0' || p[i] > '9') - return NULL; - } - - /* check for magnitude */ - if (atoi(p) > 65535) - return NULL; - - return p; -} - diff --git a/src/libosmocc/endpoint.h b/src/libosmocc/endpoint.h deleted file mode 100644 index 4425532..0000000 --- a/src/libosmocc/endpoint.h +++ /dev/null @@ -1,131 +0,0 @@ -#ifndef OSMO_CC_ENDPOINT_H -#define OSMO_CC_ENDPOINT_H - -#include "message.h" -#include "socket.h" -#include "cause.h" - -/* special osmo-cc error codes */ -#define OSMO_CC_RC_SEE_ERRNO -1 -#define OSMO_CC_RC_VERSION_MISMATCH 1 - -#define OSMO_CC_ATTACH_TIMER 2 - -/* call control state */ -enum osmo_cc_state { - OSMO_CC_STATE_IDLE = 0, - /* call states */ - OSMO_CC_STATE_INIT_OUT, /* outgoing CC-SETUP-REQ sent */ - OSMO_CC_STATE_INIT_IN, /* incoming CC-SETUP-IND received */ - OSMO_CC_STATE_OVERLAP_OUT, /* received CC-SETUP-ACK-IND on outgoing call */ - OSMO_CC_STATE_OVERLAP_IN, /* sent CC-SETUP-ACK-REQ on incoming call */ - OSMO_CC_STATE_PROCEEDING_OUT, /* received CC-PROC-IND on outgoing call */ - OSMO_CC_STATE_PROCEEDING_IN, /* sent CC-PROC-REQ on incoming call */ - OSMO_CC_STATE_ALERTING_OUT, /* received CC-ALERT-IND on outgoing call */ - OSMO_CC_STATE_ALERTING_IN, /* sent CC-ALERT-REQ on incoming call */ - OSMO_CC_STATE_CONNECTING_OUT, /* received CC-SETUP-CNF on outgoing call */ - OSMO_CC_STATE_CONNECTING_IN, /* sent CC-SETUP-RSP on incoming call */ - OSMO_CC_STATE_ACTIVE, /* received or sent CC-SETUP-COMPL-* */ - OSMO_CC_STATE_DISCONNECTING_OUT, /* sent CC-DISC-REQ */ - OSMO_CC_STATE_DISCONNECTING_IN, /* received CC-DISC-IND */ - OSMO_CC_STATE_DISC_COLLISION, /* received CC-DISC-IND after sending CC-DISC_REQ */ - OSMO_CC_STATE_RELEASING_OUT, /* sent CC-REL-REQ */ - /* attachment states */ - OSMO_CC_STATE_ATTACH_SENT, /* outgoing CC-ATT-REQ sent to socket */ - OSMO_CC_STATE_ATTACH_OUT, /* received CC-ATT-RSP on outgoing socket */ - OSMO_CC_STATE_ATTACH_WAIT, /* wait for outgoing attachment after failure */ - OSMO_CC_STATE_ATTACH_IN, /* incoming CC-ATT-REQ received from socket*/ -}; - -/* sample type */ -typedef int16_t osmo_cc_sample_t; - -#define OSMO_CC_SAMPLE_MILLIWATT 23170 /* peak sine at -3 dB of full sample range */ -#define OSMO_CC_SAMPLE_SPEECH 3672 /* peak speech at -16 dB of milliwatt */ -#define OSMO_CC_SAMPLE_MIN -32768 /* lowest level */ -#define OSMO_CC_SAMPLE_MAX 32767 /* highest level */ - -#include "session.h" - -struct osmo_cc_call; - -typedef struct osmo_cc_screen_list { - struct osmo_cc_screen_list *next; - int has_from_type; - uint8_t from_type; - int has_from_present; - uint8_t from_present; - char from[128]; - int has_to_type; - uint8_t to_type; - int has_to_present; - uint8_t to_present; - char to[128]; -} osmo_cc_screen_list_t; - -/* endpoint instance */ -typedef struct osmo_cc_endpoint { - struct osmo_cc_endpoint *next; - void *priv; - void (*ll_msg_cb)(struct osmo_cc_endpoint *ep, uint32_t callref, osmo_cc_msg_t *msg); - void (*ul_msg_cb)(struct osmo_cc_call *call, osmo_cc_msg_t *msg); - osmo_cc_msg_list_t *ll_queue; /* messages towards lower layer */ - struct osmo_cc_call *call_list; - const char *local_name; /* name of interface */ - const char *local_address; /* host+port */ - const char *local_host; - uint16_t local_port; - const char *remote_address; /* host+port */ - const char *remote_host; - uint16_t remote_port; - uint8_t serving_location; - osmo_cc_socket_t os; - osmo_cc_screen_list_t *screen_calling_in; - osmo_cc_screen_list_t *screen_called_in; - osmo_cc_screen_list_t *screen_calling_out; - osmo_cc_screen_list_t *screen_called_out; - int remote_auto; /* automatic remote address */ - struct timer attach_timer; /* timer to retry attachment */ - osmo_cc_session_config_t session_config; /* SDP/RTP default configuration */ -} osmo_cc_endpoint_t; - -extern osmo_cc_endpoint_t *osmo_cc_endpoint_list; - -/* call process */ -typedef struct osmo_cc_call { - struct osmo_cc_call *next; - osmo_cc_endpoint_t *ep; - enum osmo_cc_state state; - int lower_layer_released; /* when lower layer sent release, while upper layer gets a disconnect */ - int upper_layer_released; /* when upper layer sent release, while lower layer gets a disconnect */ - uint32_t callref; - osmo_cc_msg_list_t *sock_queue; /* messages from socket */ - const char *attached_host; /* host and port from remote peer that attached to us */ - uint16_t attached_port; - const char *attached_name; /* interface name from remote peer that attached to us */ -} osmo_cc_call_t; - -/* returns 0 if ok - * returns <0 for error as indicated - * returns >=1 to indicate osmo-cc error code - */ - -void osmo_cc_help(void); -int osmo_cc_new(osmo_cc_endpoint_t *ep, const char *version, const char *name, uint8_t serving_location, void (*ll_msg_cb)(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg), void (*ul_msg_cb)(osmo_cc_call_t *call, osmo_cc_msg_t *msg), void *priv, int argc, const char *argv[]); -void osmo_cc_delete(struct osmo_cc_endpoint *ep); -int osmo_cc_handle(void); -osmo_cc_call_t *osmo_cc_call_by_callref(osmo_cc_endpoint_t *ep, uint32_t callref); -osmo_cc_call_t *osmo_cc_get_attached_interface(osmo_cc_endpoint_t *ep, const char *interface); -void osmo_cc_ll_msg(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg); -void osmo_cc_ul_msg(void *priv, uint32_t callref, osmo_cc_msg_t *msg); -osmo_cc_call_t *osmo_cc_call_new(osmo_cc_endpoint_t *ep); -void osmo_cc_call_delete(struct osmo_cc_call *call); -enum osmo_cc_session_addrtype osmo_cc_address_type(const char *address); -const char *osmo_cc_host_of_address(const char *address); -const char *osmo_cc_port_of_address(const char *address); - -#include "rtp.h" -#include "sdp.h" -#include "screen.h" - -#endif /* OSMO_CC_ENDPOINT_H */ diff --git a/src/libosmocc/helper.c b/src/libosmocc/helper.c deleted file mode 100644 index f94d33c..0000000 --- a/src/libosmocc/helper.c +++ /dev/null @@ -1,194 +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 "../libselect/select.h" -#include "../libdebug/debug.h" -#include "endpoint.h" -#include "helper.h" - -osmo_cc_session_t *osmo_cc_helper_audio_offer(osmo_cc_session_config_t *conf, void *priv, struct osmo_cc_helper_audio_codecs *codecs, void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len), osmo_cc_msg_t *msg, int debug) -{ - osmo_cc_session_t *session; - osmo_cc_session_media_t *media; - const char *sdp; - int i; - - session = osmo_cc_new_session(conf, priv, NULL, NULL, NULL, 0, 0, NULL, NULL, debug); - if (!session) - return NULL; - - media = osmo_cc_add_media(session, 0, 0, NULL, osmo_cc_session_media_type_audio, 0, osmo_cc_session_media_proto_rtp, 1, 1, receiver, debug); - osmo_cc_rtp_open(media); - - for (i = 0; codecs[i].payload_name; i++) - osmo_cc_add_codec(media, codecs[i].payload_name, codecs[i].payload_rate, codecs[i].payload_channels, codecs[i].encoder, codecs[i].decoder, debug); - - sdp = osmo_cc_session_send_offer(session); - osmo_cc_add_ie_sdp(msg, sdp); - - return session; -} - -const char *osmo_cc_helper_audio_accept(osmo_cc_session_config_t *conf, void *priv, struct osmo_cc_helper_audio_codecs *codecs, void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len), osmo_cc_msg_t *msg, osmo_cc_session_t **session_p, osmo_cc_session_codec_t **codec_p, int force_our_codec) -{ - char offer_sdp[65536]; - const char *accept_sdp; - osmo_cc_session_media_t *media, *selected_media; - osmo_cc_session_codec_t *codec, *selected_codec, *telephone_event; - int rc; - int i, selected_codec_i, telephone_event_i; - - if (*session_p) { - LOGP(DCC, LOGL_ERROR, "Session already set, please fix!\n"); - abort(); - } - if (*codec_p) { - LOGP(DCC, LOGL_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) { - LOGP(DCC, LOGL_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) { - LOGP(DCC, LOGL_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) { - LOGP(DCC, LOGL_ERROR, "No codec found in setup message that we support.\n"); - osmo_cc_free_session(*session_p); - *session_p = NULL; - 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); - *session_p = NULL; - 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)) { - LOGP(DCC, LOGL_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)) { - LOGP(DCC, LOGL_ERROR, "No codec found in setup reply message that we support.\n"); - return -EIO; - } - - return 0; -} - diff --git a/src/libosmocc/helper.h b/src/libosmocc/helper.h deleted file mode 100644 index 9b18ac0..0000000 --- a/src/libosmocc/helper.h +++ /dev/null @@ -1,13 +0,0 @@ - -struct osmo_cc_helper_audio_codecs { - const char *payload_name; - uint32_t payload_rate; - int payload_channels; - void (*encoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv); - void (*decoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv); -}; - -osmo_cc_session_t *osmo_cc_helper_audio_offer(osmo_cc_session_config_t *conf, void *priv, struct osmo_cc_helper_audio_codecs *codecs, void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len), osmo_cc_msg_t *msg, int debug); -const char *osmo_cc_helper_audio_accept(osmo_cc_session_config_t *conf, void *priv, struct osmo_cc_helper_audio_codecs *codecs, void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len), osmo_cc_msg_t *msg, osmo_cc_session_t **session_p, osmo_cc_session_codec_t **codec_p, int force_our_codec); -int osmo_cc_helper_audio_negotiate(osmo_cc_msg_t *msg, osmo_cc_session_t **session_p, osmo_cc_session_codec_t **codec_p); - diff --git a/src/libosmocc/message.c b/src/libosmocc/message.c deleted file mode 100644 index 8f83343..0000000 --- a/src/libosmocc/message.c +++ /dev/null @@ -1,1294 +0,0 @@ -/* Osmo-CC: Message handling - * - * (C) 2016 by Andreas Eversberg - * All Rights Reserved - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include -#include -#include "../libdebug/debug.h" -#include "message.h" - -#define _OSMO_CC_VALUE2NAME(array) { \ - if (value < 0 || (size_t)value >= (sizeof(array) / sizeof(array[0])) || array[value] == NULL) \ - return ""; \ - else \ - return array[value]; \ -} - -#define _OSMO_CC_NAME2VALUE(array) { \ - int value; \ - for (value = 0; (size_t)value < (sizeof(array) / sizeof(array[0])); value++) { \ - if (!array[value]) \ - continue; \ - 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_R1_NONE] = "r1", - [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) { - LOGP(DCC, LOGL_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)) { - LOGP(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) { - LOGP(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; - LOGP(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; - LOGP(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; - LOGP(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; - LOGP(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; - LOGP(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; - LOGP(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; - LOGP(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; - LOGP(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; - LOGP(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; - LOGP(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; - LOGP(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; - LOGP(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; - LOGP(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; - LOGP(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; - LOGP(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; - LOGP(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; - LOGP(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; - LOGP(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'; - } - LOGP(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; - LOGP(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; - LOGP(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: - LOGP(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)) { - LOGP(DCC, LOGL_ERROR, "MSG short read\n"); - osmo_cc_debug_ie(msg, LOGL_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) { - LOGP(DCC, LOGL_ERROR, "MSG short read\n"); - osmo_cc_debug_ie(msg, LOGL_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) { - LOGP(DCC, LOGL_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) { - LOGP(DCC, LOGL_ERROR, "MSG overflow\n"); - return NULL; - } - msg->length_networkorder = htons(new_msg_len); - /* go to end of (unexpanded) message */ - ie = (osmo_cc_ie_t *)(p + msg_len); - /* add ie */ - ie->type = ie_type; - ie->length_networkorder = htons(ie_len); - memset(ie->data, 0, ie_len); /* just in case there is something, but it shouldn't */ - - return ie->data; -} - -/* gets the information element's data that *iep points to and returns that ie. - * if *iep points to msg->data, the first IE's data is returned. (must be set before first call.) - * if *iep points to the end of the message, NULL is returned. - * if there is no next IE, *iep is set to point to the end of message. - */ -void *osmo_cc_msg_sep_ie(osmo_cc_msg_t *msg, void **iep, uint8_t *ie_type, uint16_t *ie_length) -{ - uint16_t msg_len; - osmo_cc_ie_t *ie; - - /* in case that *iep points to start of message, make it point to first IE */ - if (*iep == msg) - *iep = msg->data; - /* case IE */ - ie = *iep; - /* check if it is NULL */ - if (ie == NULL) - return NULL; - /* check if it points to the end of message or there is not at least an IE header */ - msg_len = ntohs(msg->length_networkorder); - if ((int)((uint8_t *)ie - msg->data) > (int)(msg_len - sizeof(*ie))) - return NULL; - /* increment iep and return IE */ - *ie_type = ie->type; - *ie_length = ntohs(ie->length_networkorder); - *iep = (uint8_t *)ie + sizeof(*ie) + *ie_length; - return ie->data; -} - -/* copy given block to given string with given size */ -static void _ie2string(char *string, size_t string_size, const char *ie_string, int ie_size) -{ - int copy_size; - - copy_size = string_size - 1; - if (ie_size < copy_size) - copy_size = ie_size; - memcpy(string, ie_string, copy_size); - string[copy_size] = '\0'; -} - -/* helper to encode called party number (dialing) */ -void osmo_cc_add_ie_called(osmo_cc_msg_t *msg, uint8_t type, uint8_t plan, const char *dialing) -{ - struct osmo_cc_ie_called *ie_called; - - ie_called = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLED, sizeof(*ie_called) + strlen(dialing)); - ie_called->type = type; - ie_called->plan = plan; - memcpy(ie_called->digits, dialing, strlen(dialing)); -} - -/* helper to decode called party number (dialing) */ -int osmo_cc_get_ie_called(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, uint8_t *plan, char *dialing, size_t dialing_size) -{ - struct osmo_cc_ie_called *ie_called; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLED, ie_repeat, sizeof(*ie_called), (const void **)&ie_called); - if (rc < 0) - return rc; - *type = ie_called->type; - *plan = ie_called->plan; - _ie2string(dialing, dialing_size, ie_called->digits, rc); - return rc; -} - -/* helper to encode called party sub address (dialing) */ -void osmo_cc_add_ie_called_sub(osmo_cc_msg_t *msg, uint8_t type, const char *dialing) -{ - struct osmo_cc_ie_called_sub *ie_called_sub; - - ie_called_sub = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLED_SUB, sizeof(*ie_called_sub) + strlen(dialing)); - ie_called_sub->type = type; - memcpy(ie_called_sub->digits, dialing, strlen(dialing)); -} - -/* helper to decode called party sub address (dialing) */ -int osmo_cc_get_ie_called_sub(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, char *dialing, size_t dialing_size) -{ - struct osmo_cc_ie_called_sub *ie_called_sub; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLED_SUB, ie_repeat, sizeof(*ie_called_sub), (const void **)&ie_called_sub); - if (rc < 0) - return rc; - *type = ie_called_sub->type; - _ie2string(dialing, dialing_size, ie_called_sub->digits, rc); - return rc; -} - -/* helper to encode called party name (dialing) */ -void osmo_cc_add_ie_called_name(osmo_cc_msg_t *msg, const char *name) -{ - struct osmo_cc_ie_called_name *ie_called_name; - - ie_called_name = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLED_NAME, sizeof(*ie_called_name) + strlen(name)); - memcpy(ie_called_name->name, name, strlen(name)); -} - -/* helper to decode called party name (dialing) */ -int osmo_cc_get_ie_called_name(osmo_cc_msg_t *msg, int ie_repeat, char *name, size_t name_size) -{ - struct osmo_cc_ie_called_name *ie_called_name; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLED_NAME, ie_repeat, sizeof(*ie_called_name), (const void **)&ie_called_name); - if (rc < 0) - return rc; - _ie2string(name, name_size, ie_called_name->name, rc); - return rc; -} - -/* helper to encode called interface name */ -void osmo_cc_add_ie_called_interface(osmo_cc_msg_t *msg, const char *interface) -{ - struct osmo_cc_ie_called_interface *ie_interface; - - ie_interface = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLED_INTERFACE, sizeof(*ie_interface) + strlen(interface)); - memcpy(ie_interface->name, interface, strlen(interface)); -} - -/* helper to decode called interface name */ -int osmo_cc_get_ie_called_interface(osmo_cc_msg_t *msg, int ie_repeat, char *interface, size_t interface_size) -{ - struct osmo_cc_ie_called_interface *ie_interface; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLED_INTERFACE, ie_repeat, sizeof(*ie_interface), (const void **)&ie_interface); - if (rc < 0) - return rc; - _ie2string(interface, interface_size, ie_interface->name, rc); - return rc; -} - -/* helper to encode complete IE */ -void osmo_cc_add_ie_complete(osmo_cc_msg_t *msg) -{ - osmo_cc_add_ie(msg, OSMO_CC_IE_COMPLETE, 0); -} - -/* helper to decode complete IE */ -int osmo_cc_get_ie_complete(osmo_cc_msg_t *msg, int ie_repeat) -{ - int rc; - void *ie_complete; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_COMPLETE, ie_repeat, 0, (const void **)&ie_complete); - return rc; -} - -/* helper to encode calling/connected party number (caller ID or connected ID) */ -void osmo_cc_add_ie_calling(osmo_cc_msg_t *msg, uint8_t type, uint8_t plan, uint8_t present, uint8_t screen, const char *callerid) -{ - struct osmo_cc_ie_calling *ie_calling; - - ie_calling = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLING, sizeof(*ie_calling) + strlen(callerid)); - ie_calling->type = type; - ie_calling->plan = plan; - ie_calling->present = present; - ie_calling->screen = screen; - memcpy(ie_calling->digits, callerid, strlen(callerid)); -} - -/* helper to decode calling/connected party number (caller ID or connected ID) */ -int osmo_cc_get_ie_calling(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, uint8_t *plan, uint8_t *present, uint8_t *screen, char *callerid, size_t callerid_size) -{ - struct osmo_cc_ie_calling *ie_calling; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLING, ie_repeat, sizeof(*ie_calling), (const void **)&ie_calling); - if (rc < 0) - return rc; - *type = ie_calling->type; - *plan = ie_calling->plan; - *present = ie_calling->present; - *screen = ie_calling->screen; - _ie2string(callerid, callerid_size, ie_calling->digits, rc); - return rc; -} - -/* helper to encode calling/connected sub address (caller ID or connected ID) */ -void osmo_cc_add_ie_calling_sub(osmo_cc_msg_t *msg, uint8_t type, const char *callerid) -{ - struct osmo_cc_ie_calling_sub *ie_calling_sub; - - ie_calling_sub = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLING_SUB, sizeof(*ie_calling_sub) + strlen(callerid)); - ie_calling_sub->type = type; - memcpy(ie_calling_sub->digits, callerid, strlen(callerid)); -} - -/* helper to decode calling/connected sub address (caller ID or connected ID) */ -int osmo_cc_get_ie_calling_sub(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, char *callerid, size_t callerid_size) -{ - struct osmo_cc_ie_calling_sub *ie_calling_sub; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLING_SUB, ie_repeat, sizeof(*ie_calling_sub), (const void **)&ie_calling_sub); - if (rc < 0) - return rc; - *type = ie_calling_sub->type; - _ie2string(callerid, callerid_size, ie_calling_sub->digits, rc); - return rc; -} - -/* helper to encode calling/connected name (caller ID or connected ID) */ -void osmo_cc_add_ie_calling_name(osmo_cc_msg_t *msg, const char *name) -{ - struct osmo_cc_ie_calling_name *ie_calling_name; - - ie_calling_name = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLING_NAME, sizeof(*ie_calling_name) + strlen(name)); - memcpy(ie_calling_name->name, name, strlen(name)); -} - -/* helper to decode calling/connected name address (caller ID or connected ID) */ -int osmo_cc_get_ie_calling_name(osmo_cc_msg_t *msg, int ie_repeat, char *name, size_t name_size) -{ - struct osmo_cc_ie_calling_name *ie_calling_name; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLING_NAME, ie_repeat, sizeof(*ie_calling_name), (const void **)&ie_calling_name); - if (rc < 0) - return rc; - _ie2string(name, name_size, ie_calling_name->name, rc); - return rc; -} - -/* helper to encode calling interface name */ -void osmo_cc_add_ie_calling_interface(osmo_cc_msg_t *msg, const char *interface) -{ - struct osmo_cc_ie_calling_interface *ie_interface; - - ie_interface = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLING_INTERFACE, sizeof(*ie_interface) + strlen(interface)); - memcpy(ie_interface->name, interface, strlen(interface)); -} - -/* helper to decode calling interface name */ -int osmo_cc_get_ie_calling_interface(osmo_cc_msg_t *msg, int ie_repeat, char *interface, size_t interface_size) -{ - struct osmo_cc_ie_calling_interface *ie_interface; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLING_INTERFACE, ie_repeat, sizeof(*ie_interface), (const void **)&ie_interface); - if (rc < 0) - return rc; - _ie2string(interface, interface_size, ie_interface->name, rc); - return rc; -} - -/* helper to encode network specific caller/connected ID */ -void osmo_cc_add_ie_calling_network(osmo_cc_msg_t *msg, uint8_t type, const char *networkid) -{ - struct osmo_cc_ie_network *ie_network; - - ie_network = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLING_NETWORK, sizeof(*ie_network) + strlen(networkid)); - ie_network->type = type; - memcpy(ie_network->id, networkid, strlen(networkid)); -} - -/* helper to encode network specific caller/connected ID */ -int osmo_cc_get_ie_calling_network(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, char *networkid, size_t networkid_size) -{ - struct osmo_cc_ie_network *ie_network; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLING_NETWORK, ie_repeat, sizeof(*ie_network), (const void **)&ie_network); - if (rc < 0) - return rc; - *type = ie_network->type; - _ie2string(networkid, networkid_size, ie_network->id, rc); - return rc; -} - -/* helper to encode bearer capability */ -void osmo_cc_add_ie_bearer(osmo_cc_msg_t *msg, uint8_t coding, uint8_t capability, uint8_t mode) -{ - struct osmo_cc_ie_bearer *ie_bearer; - - ie_bearer = osmo_cc_add_ie(msg, OSMO_CC_IE_BEARER, sizeof(*ie_bearer)); - ie_bearer->coding = coding; - ie_bearer->capability = capability; - ie_bearer->mode = mode; -} - -/* helper to decode bearer capability */ -int osmo_cc_get_ie_bearer(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *coding, uint8_t *capability, uint8_t *mode) -{ - struct osmo_cc_ie_bearer *ie_bearer; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_BEARER, ie_repeat, sizeof(*ie_bearer), (const void **)&ie_bearer); - if (rc < 0) - return rc; - *coding = ie_bearer->coding; - *capability = ie_bearer->capability; - *mode = ie_bearer->mode; - return rc; -} - -/* helper to encode redirection and redirecting number */ -void osmo_cc_add_ie_redir(osmo_cc_msg_t *msg, uint8_t type, uint8_t plan, uint8_t present, uint8_t screen, uint8_t redir_reason, const char *callerid) -{ - struct osmo_cc_ie_redir *ie_redir; - - ie_redir = osmo_cc_add_ie(msg, OSMO_CC_IE_REDIR, sizeof(*ie_redir) + strlen(callerid)); - ie_redir->type = type; - ie_redir->plan = plan; - ie_redir->present = present; - ie_redir->screen = screen; - ie_redir->redir_reason = redir_reason; - memcpy(ie_redir->digits, callerid, strlen(callerid)); -} - -/* helper to decode redirection and redirecting number */ -int osmo_cc_get_ie_redir(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, uint8_t *plan, uint8_t *present, uint8_t *screen, uint8_t *reason, char *callerid, size_t callerid_size) -{ - struct osmo_cc_ie_redir *ie_redir; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_REDIR, ie_repeat, sizeof(*ie_redir), (const void **)&ie_redir); - if (rc < 0) - return rc; - *type = ie_redir->type; - *plan = ie_redir->plan; - *present = ie_redir->present; - *screen = ie_redir->screen; - *reason = ie_redir->redir_reason; - _ie2string(callerid, callerid_size, ie_redir->digits, rc); - return rc; -} - -/* helper to encode DTMF tones */ -void osmo_cc_add_ie_dtmf(osmo_cc_msg_t *msg, uint8_t duration_ms, uint8_t pause_ms, uint8_t dtmf_mode, const char *digits) -{ - struct osmo_cc_ie_dtmf *ie_dtmf; - - ie_dtmf = osmo_cc_add_ie(msg, OSMO_CC_IE_DTMF, sizeof(*ie_dtmf) + strlen(digits)); - ie_dtmf->duration_ms = duration_ms; - ie_dtmf->pause_ms = pause_ms; - ie_dtmf->dtmf_mode = dtmf_mode; - memcpy(ie_dtmf->digits, digits, strlen(digits)); -} - -/* helper to decode DTMF tones */ -int osmo_cc_get_ie_dtmf(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *duration_ms, uint8_t *pause_ms, uint8_t *dtmf_mode, char *digits, size_t digits_size) -{ - struct osmo_cc_ie_dtmf *ie_dtmf; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_DTMF, ie_repeat, sizeof(*ie_dtmf), (const void **)&ie_dtmf); - if (rc < 0) - return rc; - *duration_ms = ie_dtmf->duration_ms; - *pause_ms = ie_dtmf->pause_ms; - *dtmf_mode = ie_dtmf->dtmf_mode; - _ie2string(digits, digits_size, ie_dtmf->digits, rc); - return rc; -} - -/* helper to encode keypad press */ -void osmo_cc_add_ie_keypad(osmo_cc_msg_t *msg, const char *digits) -{ - struct osmo_cc_ie_keypad *ie_keypad; - - ie_keypad = osmo_cc_add_ie(msg, OSMO_CC_IE_KEYPAD, sizeof(*ie_keypad) + strlen(digits)); - memcpy(ie_keypad->digits, digits, strlen(digits)); -} - -/* helper to decode keypad press */ -int osmo_cc_get_ie_keypad(osmo_cc_msg_t *msg, int ie_repeat, char *digits, size_t digits_size) -{ - struct osmo_cc_ie_keypad *ie_keypad; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_KEYPAD, ie_repeat, sizeof(*ie_keypad), (const void **)&ie_keypad); - if (rc < 0) - return rc; - _ie2string(digits, digits_size, ie_keypad->digits, rc); - return rc; -} - -/* helper to encode call progress information */ -void osmo_cc_add_ie_progress(osmo_cc_msg_t *msg, uint8_t coding, uint8_t location, uint8_t progress) -{ - struct osmo_cc_ie_progress *ie_progress; - - ie_progress = osmo_cc_add_ie(msg, OSMO_CC_IE_PROGRESS, sizeof(*ie_progress)); - ie_progress->coding = coding; - ie_progress->location = location; - ie_progress->progress = progress; -} - -/* helper to decode call progress information */ -int osmo_cc_get_ie_progress(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *coding, uint8_t *location, uint8_t *progress) -{ - struct osmo_cc_ie_progress *ie_progress; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_PROGRESS, ie_repeat, sizeof(*ie_progress), (const void **)&ie_progress); - if (rc < 0) - return rc; - *coding = ie_progress->coding; - *location = ie_progress->location; - *progress = ie_progress->progress; - return rc; -} - -/* helper to encode notification */ -void osmo_cc_add_ie_notify(osmo_cc_msg_t *msg, uint8_t notify) -{ - struct osmo_cc_ie_notify *ie_notify; - - ie_notify = osmo_cc_add_ie(msg, OSMO_CC_IE_NOTIFY, sizeof(*ie_notify)); - ie_notify->notify = notify; -} - -/* helper to decode notification */ -int osmo_cc_get_ie_notify(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *notify) -{ - struct osmo_cc_ie_notify *ie_notify; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_NOTIFY, ie_repeat, sizeof(*ie_notify), (const void **)&ie_notify); - if (rc < 0) - return rc; - *notify = ie_notify->notify; - return rc; -} - -/* helper to encode cause */ -void osmo_cc_add_ie_cause(osmo_cc_msg_t *msg, uint8_t location, uint8_t isdn_cause, uint16_t sip_cause, uint8_t socket_cause) -{ - struct osmo_cc_ie_cause *ie_cause; - - ie_cause = osmo_cc_add_ie(msg, OSMO_CC_IE_CAUSE, sizeof(*ie_cause)); - ie_cause->location = location; - ie_cause->isdn_cause = isdn_cause; - ie_cause->sip_cause_networkorder = htons(sip_cause); - ie_cause->socket_cause = socket_cause; -} - -/* helper to deccode cause */ -int osmo_cc_get_ie_cause(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *location, uint8_t *isdn_cause, uint16_t *sip_cause, uint8_t *socket_cause) -{ - struct osmo_cc_ie_cause *ie_cause; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CAUSE, ie_repeat, sizeof(*ie_cause), (const void **)&ie_cause); - if (rc < 0) - return rc; - *location = ie_cause->location; - *isdn_cause = ie_cause->isdn_cause; - *sip_cause = ntohs(ie_cause->sip_cause_networkorder); - *socket_cause = ie_cause->socket_cause; - return rc; -} - -/* helper to encode DISPLAY information */ -void osmo_cc_add_ie_display(osmo_cc_msg_t *msg, const char *text) -{ - struct osmo_cc_ie_display *ie_display; - - ie_display = osmo_cc_add_ie(msg, OSMO_CC_IE_DISPLAY, sizeof(*ie_display) + strlen(text)); - memcpy(ie_display->text, text, strlen(text)); -} - -/* helper to decode DISPLAY information */ -int osmo_cc_get_ie_display(osmo_cc_msg_t *msg, int ie_repeat, char *text, size_t text_size) -{ - struct osmo_cc_ie_display *ie_display; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_DISPLAY, ie_repeat, sizeof(*ie_display), (const void **)&ie_display); - if (rc < 0) - return rc; - _ie2string(text, text_size, ie_display->text, rc); - return rc; -} - -/* helper to encode SDP */ -void osmo_cc_add_ie_sdp(osmo_cc_msg_t *msg, const char *sdp) -{ - struct osmo_cc_ie_sdp *ie_sdp; - - ie_sdp = osmo_cc_add_ie(msg, OSMO_CC_IE_SDP, sizeof(*ie_sdp) + strlen(sdp)); - memcpy(ie_sdp->sdp, sdp, strlen(sdp)); -} - -/* helper to decode SDP */ -int osmo_cc_get_ie_sdp(osmo_cc_msg_t *msg, int ie_repeat, char *sdp, size_t sdp_size) -{ - struct osmo_cc_ie_sdp *ie_sdp; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_SDP, ie_repeat, sizeof(*ie_sdp), (const void **)&ie_sdp); - if (rc < 0) - return rc; - _ie2string(sdp, sdp_size, ie_sdp->sdp, rc); - return rc; -} - -/* helper to encode socket address */ -void osmo_cc_add_ie_socket_address(osmo_cc_msg_t *msg, const char *address) -{ - struct osmo_cc_ie_socket_address *ie_socket_address; - - ie_socket_address = osmo_cc_add_ie(msg, OSMO_CC_IE_SOCKET_ADDRESS, sizeof(*ie_socket_address) + strlen(address)); - memcpy(ie_socket_address->address, address, strlen(address)); -} - -/* helper to decode socket address */ -int osmo_cc_get_ie_socket_address(osmo_cc_msg_t *msg, int ie_repeat, char *address, size_t address_size) -{ - struct osmo_cc_ie_socket_address *ie_socket_address; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_SOCKET_ADDRESS, ie_repeat, sizeof(*ie_socket_address), (const void **)&ie_socket_address); - if (rc < 0) - return rc; - _ie2string(address, address_size, ie_socket_address->address, rc); - return rc; -} - -/* helper to encode private information element */ -void osmo_cc_add_ie_private(osmo_cc_msg_t *msg, uint32_t unique, const uint8_t *data, size_t data_size) -{ - struct osmo_cc_ie_private *ie_private; - - ie_private = osmo_cc_add_ie(msg, OSMO_CC_IE_PRIVATE, sizeof(*ie_private) + data_size); - ie_private->unique_networkorder = htonl(unique); - memcpy(ie_private->data, data, data_size); -} - -/* helper to decode private information element */ -int osmo_cc_get_ie_private(osmo_cc_msg_t *msg, int ie_repeat, uint32_t *unique, uint8_t *data, size_t data_size) -{ - struct osmo_cc_ie_private *ie_private; - int rc; - - rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_PRIVATE, ie_repeat, sizeof(*ie_private), (const void **)&ie_private); - if (rc < 0) - return rc; - *unique = ntohl(ie_private->unique_networkorder); - if (rc > (int)data_size) - rc = data_size; - memcpy(data, ie_private->data, rc); - return rc; -} - diff --git a/src/libosmocc/message.h b/src/libosmocc/message.h deleted file mode 100644 index 2d7b39b..0000000 --- a/src/libosmocc/message.h +++ /dev/null @@ -1,513 +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_MODIFY_REQ = 0x90, - OSMO_CC_MSG_MODIFY_IND = 0x91, - OSMO_CC_MSG_MODIFY_RSP = 0x92, - OSMO_CC_MSG_MODIFY_CNF = 0x93, - OSMO_CC_MSG_ATTACH_REQ = 0xf8, - OSMO_CC_MSG_ATTACH_IND = 0xf9, - OSMO_CC_MSG_ATTACH_RSP = 0xfa, - OSMO_CC_MSG_ATTACH_CNF = 0xfb, - OSMO_CC_MSG_DUMMY_REQ = 0xfc, -}; -#define OSMO_CC_MSG_NUM 0x100 - -#define OSMO_CC_MSG_MASK 0x03, -#define OSMO_CC_MSG_REQ 0x00, -#define OSMO_CC_MSG_IND 0x01, -#define OSMO_CC_MSG_RSP 0x02, -#define OSMO_CC_MSG_CNF 0x03, - -const char *osmo_cc_msg_value2name(int value); -int osmo_cc_msg_name2value(const char *name); - -/* information elements */ -enum osmo_cc_ie_type { - OSMO_CC_IE_CALLED = 0x11, - OSMO_CC_IE_CALLED_SUB = 0x12, - OSMO_CC_IE_CALLED_NAME = 0x13, - OSMO_CC_IE_CALLED_INTERFACE = 0x14, - OSMO_CC_IE_DTMF = 0x1d, - OSMO_CC_IE_KEYPAD = 0x1e, - OSMO_CC_IE_COMPLETE = 0x1f, - OSMO_CC_IE_CALLING = 0x21, - OSMO_CC_IE_CALLING_SUB = 0x22, - OSMO_CC_IE_CALLING_NAME = 0x23, - OSMO_CC_IE_CALLING_INTERFACE = 0x24, - OSMO_CC_IE_CALLING_NETWORK = 0x2f, - OSMO_CC_IE_REDIR = 0x31, - OSMO_CC_IE_PROGRESS = 0x32, - OSMO_CC_IE_NOTIFY = 0x33, - OSMO_CC_IE_DISPLAY = 0x34, - OSMO_CC_IE_CAUSE = 0x41, - OSMO_CC_IE_BEARER = 0x51, - OSMO_CC_IE_SDP = 0x52, - OSMO_CC_IE_SOCKET_ADDRESS = 0x5e, - OSMO_CC_IE_PRIVATE = 0x5f, -}; -#define OSMO_CC_IE_NUM 0x100 - -const char *osmo_cc_ie_value2name(int value); -int osmo_cc_ie_name2value(const char *name); - -/* type of number, see ITU-T Rec. Q.931 */ -#define OSMO_CC_TYPE_UNKNOWN 0 -#define OSMO_CC_TYPE_INTERNATIONAL 1 -#define OSMO_CC_TYPE_NATIONAL 2 -#define OSMO_CC_TYPE_NETWORK 3 -#define OSMO_CC_TYPE_SUBSCRIBER 4 -#define OSMO_CC_TYPE_ABBREVIATED 5 -#define OSMO_CC_TYPE_RESERVED 7 -#define OSMO_CC_TYPE_NUM 8 - -const char *osmo_cc_type_value2name(int value); -int osmo_cc_type_name2value(const char *name); - -/* numbering plan, see ITU-T Rec. Q.931 */ -#define OSMO_CC_PLAN_UNKNOWN 0 -#define OSMO_CC_PLAN_TELEPHONY 1 -#define OSMO_CC_PLAN_DATA 3 -#define OSMO_CC_PLAN_TTY 4 -#define OSMO_CC_PLAN_NATIONAL_STANDARD 8 -#define OSMO_CC_PLAN_PRIVATE 9 -#define OSMO_CC_PLAN_RESERVED 15 -#define OSMO_CC_PLAN_NUM 16 - -const char *osmo_cc_plan_value2name(int value); -int osmo_cc_plan_name2value(const char *name); - -/* presentation indicator, see ITU-T Rec. Q.931 */ -#define OSMO_CC_PRESENT_ALLOWED 0 -#define OSMO_CC_PRESENT_RESTRICTED 1 -#define OSMO_CC_PRESENT_NOT_AVAIL 2 -#define OSMO_CC_PRESENT_RESERVED 3 -#define OSMO_CC_PRESENT_NUM 4 - -const char *osmo_cc_present_value2name(int value); -int osmo_cc_present_name2value(const char *name); - -/* screening indicator, see ITU-T Rec. Q.931 */ -#define OSMO_CC_SCREEN_USER_UNSCREENED 0 -#define OSMO_CC_SCREEN_USER_VERIFIED_PASSED 1 -#define OSMO_CC_SCREEN_USER_VERIFIED_FAILED 2 -#define OSMO_CC_SCREEN_NETWORK 3 -#define OSMO_CC_SCREEN_NUM 4 - -const char *osmo_cc_screen_value2name(int value); -int osmo_cc_screen_name2value(const char *name); - -/* screening indicator, see ITU-T Rec. Q.931 */ -#define OSMO_CC_REDIR_REASON_UNKNOWN 0 -#define OSMO_CC_REDIR_REASON_CFB 1 -#define OSMO_CC_REDIR_REASON_CFNR 2 -#define OSMO_CC_REDIR_REASON_CD 4 -#define OSMO_CC_REDIR_REASON_CF_OUTOFORDER 9 -#define OSMO_CC_REDIR_REASON_CF_BY_DTE 10 -#define OSMO_CC_REDIR_REASON_CFU 15 -#define OSMO_CC_REDIR_REASON_NUM 16 - -const char *osmo_cc_redir_reason_value2name(int value); -int osmo_cc_redir_reason_name2value(const char *name); - -/* notification indicator, see ITU-T Rec. Q.931 ff. */ -#define OSMO_CC_NOTIFY_USER_SUSPENDED 0x00 -#define OSMO_CC_NOTIFY_USER_RESUMED 0x01 -#define OSMO_CC_NOTIFY_BEARER_SERVICE_CHANGE 0x02 -#define OSMO_CC_NOTIFY_CALL_COMPLETION_DELAY 0x03 -#define OSMO_CC_NOTIFY_CONFERENCE_ESTABLISHED 0x42 -#define OSMO_CC_NOTIFY_CONFERENCE_DISCONNECTED 0x43 -#define OSMO_CC_NOTIFY_OTHER_PARTY_ADDED 0x44 -#define OSMO_CC_NOTIFY_ISOLATED 0x45 -#define OSMO_CC_NOTIFY_REATTACHED 0x46 -#define OSMO_CC_NOTIFY_OTHER_PARTY_ISOLATED 0x47 -#define OSMO_CC_NOTIFY_OTHER_PARTY_REATTACHED 0x48 -#define OSMO_CC_NOTIFY_OTHER_PARTY_SPLIT 0x49 -#define OSMO_CC_NOTIFY_OTHER_PARTY_DISCONNECTED 0x4a -#define OSMO_CC_NOTIFY_CONFERENCE_FLOATING 0x4b -#define OSMO_CC_NOTIFY_CONFERENCE_DISC_PREEMPT 0x4c /* disconnect preemted */ -#define OSMO_CC_NOTIFY_CONFERENCE_FLOATING_SUP 0x4f /* served user preemted */ -#define OSMO_CC_NOTIFY_CALL_IS_A_WAITING_CALL 0x60 -#define OSMO_CC_NOTIFY_DIVERSION_ACTIVATED 0x68 -#define OSMO_CC_NOTIFY_RESERVED_CT_1 0x69 -#define OSMO_CC_NOTIFY_RESERVED_CT_2 0x6a -#define OSMO_CC_NOTIFY_REVERSE_CHARGING 0x6e -#define OSMO_CC_NOTIFY_REMOTE_HOLD 0x79 -#define OSMO_CC_NOTIFY_REMOTE_RETRIEVAL 0x7a -#define OSMO_CC_NOTIFY_CALL_IS_DIVERTING 0x7b -#define OSMO_CC_NOTIFY_NUM 0x100 - -const char *osmo_cc_notify_value2name(int value); -int osmo_cc_notify_name2value(const char *name); - -/* coding standard, see ITU-T Rec. Q.931 */ -#define OSMO_CC_CODING_ITU_T 0 -#define OSMO_CC_CODING_ISO_IEC 1 -#define OSMO_CC_CODING_NATIONAL 2 -#define OSMO_CC_CODING_STANDARD_SPECIFIC 3 -#define OSMO_CC_CODING_NUM 4 - -const char *osmo_cc_coding_value2name(int value); -int osmo_cc_coding_name2value(const char *name); - -/* cause, see ITU-T Rec. Q.850 */ -#define OSMO_CC_ISDN_CAUSE_UNASSIGNED_NR 1 -#define OSMO_CC_ISDN_CAUSE_NO_ROUTE_TRANSIT 2 -#define OSMO_CC_ISDN_CAUSE_NO_ROUTE 3 -#define OSMO_CC_ISDN_CAUSE_CHAN_UNACCEPT 6 -#define OSMO_CC_ISDN_CAUSE_OP_DET_BARRING 8 -#define OSMO_CC_ISDN_CAUSE_NORM_CALL_CLEAR 16 -#define OSMO_CC_ISDN_CAUSE_USER_BUSY 17 -#define OSMO_CC_ISDN_CAUSE_USER_NOTRESPOND 18 -#define OSMO_CC_ISDN_CAUSE_USER_ALERTING_NA 19 -#define OSMO_CC_ISDN_CAUSE_CALL_REJECTED 21 -#define OSMO_CC_ISDN_CAUSE_NUMBER_CHANGED 22 -#define OSMO_CC_ISDN_CAUSE_PRE_EMPTION 25 -#define OSMO_CC_ISDN_CAUSE_NONSE_USER_CLR 26 -#define OSMO_CC_ISDN_CAUSE_DEST_OOO 27 -#define OSMO_CC_ISDN_CAUSE_INV_NR_FORMAT 28 -#define OSMO_CC_ISDN_CAUSE_FACILITY_REJ 29 -#define OSMO_CC_ISDN_CAUSE_RESP_STATUS_INQ 30 -#define OSMO_CC_ISDN_CAUSE_NORMAL_UNSPEC 31 -#define OSMO_CC_ISDN_CAUSE_NO_CIRCUIT_CHAN 34 -#define OSMO_CC_ISDN_CAUSE_NETWORK_OOO 38 -#define OSMO_CC_ISDN_CAUSE_TEMP_FAILURE 41 -#define OSMO_CC_ISDN_CAUSE_SWITCH_CONG 42 -#define OSMO_CC_ISDN_CAUSE_ACC_INF_DISCARD 43 -#define OSMO_CC_ISDN_CAUSE_REQ_CHAN_UNAVAIL 44 -#define OSMO_CC_ISDN_CAUSE_RESOURCE_UNAVAIL 47 -#define OSMO_CC_ISDN_CAUSE_QOS_UNAVAIL 49 -#define OSMO_CC_ISDN_CAUSE_REQ_FAC_NOT_SUBSC 50 -#define OSMO_CC_ISDN_CAUSE_INC_BARRED_CUG 55 -#define OSMO_CC_ISDN_CAUSE_BEARER_CAP_UNAUTH 57 -#define OSMO_CC_ISDN_CAUSE_BEARER_CA_UNAVAIL 58 -#define OSMO_CC_ISDN_CAUSE_SERV_OPT_UNAVAIL 63 -#define OSMO_CC_ISDN_CAUSE_BEARERSERV_UNIMPL 65 -#define OSMO_CC_ISDN_CAUSE_ACM_GE_ACM_MAX 68 -#define OSMO_CC_ISDN_CAUSE_REQ_FAC_NOTIMPL 69 -#define OSMO_CC_ISDN_CAUSE_RESTR_BCAP_AVAIL 70 -#define OSMO_CC_ISDN_CAUSE_SERV_OPT_UNIMPL 79 -#define OSMO_CC_ISDN_CAUSE_INVAL_CALLREF 81 -#define OSMO_CC_ISDN_CAUSE_USER_NOT_IN_CUG 87 -#define OSMO_CC_ISDN_CAUSE_INCOMPAT_DEST 88 -#define OSMO_CC_ISDN_CAUSE_INVAL_TRANS_NET 91 -#define OSMO_CC_ISDN_CAUSE_SEMANTIC_INCORR 95 -#define OSMO_CC_ISDN_CAUSE_INVAL_MAND_INF 96 -#define OSMO_CC_ISDN_CAUSE_MSGTYPE_NOTEXIST 97 -#define OSMO_CC_ISDN_CAUSE_MSGTYPE_INCOMPAT 98 -#define OSMO_CC_ISDN_CAUSE_IE_NOTEXIST 99 -#define OSMO_CC_ISDN_CAUSE_COND_IE_ERR 100 -#define OSMO_CC_ISDN_CAUSE_MSG_INCOMP_STATE 101 -#define OSMO_CC_ISDN_CAUSE_RECOVERY_TIMER 102 -#define OSMO_CC_ISDN_CAUSE_PROTO_ERR 111 -#define OSMO_CC_ISDN_CAUSE_INTERWORKING 127 -#define OSMO_CC_ISDN_CAUSE_NUM 128 - -const char *osmo_cc_isdn_cause_value2name(int value); -int osmo_cc_isdn_cause_name2value(const char *name); - -/* location, see ITU-T Rec. Q.931 */ -#define OSMO_CC_LOCATION_USER 0 -#define OSMO_CC_LOCATION_PRIV_SERV_LOC_USER 1 -#define OSMO_CC_LOCATION_PUB_SERV_LOC_USER 2 -#define OSMO_CC_LOCATION_TRANSIT 3 -#define OSMO_CC_LOCATION_PUB_SERV_REM_USER 4 -#define OSMO_CC_LOCATION_PRIV_SERV_REM_USER 5 -#define OSMO_CC_LOCATION_BEYOND_INTERWORKING 10 -#define OSMO_CC_LOCATION_NUM 16 - -const char *osmo_cc_location_value2name(int value); -int osmo_cc_location_name2value(const char *name); - -/* progress description, see ITU-T Rec. Q.931 */ -#define OSMO_CC_PROGRESS_NOT_END_TO_END_ISDN 1 -#define OSMO_CC_PROGRESS_DEST_NOT_ISDN 2 -#define OSMO_CC_PROGRESS_ORIG_NOT_ISDN 3 -#define OSMO_CC_PROGRESS_RETURN_TO_ISDN 4 -#define OSMO_CC_PROGRESS_INTERWORKING 5 -#define OSMO_CC_PROGRESS_INBAND_INFO_AVAILABLE 8 -#define OSMO_CC_PROGRESS_NUM 16 - -const char *osmo_cc_progress_value2name(int value); -int osmo_cc_progress_name2value(const char *name); - -/* information transfer capability, see ITU-T Rec. Q.931 */ -#define OSMO_CC_CAPABILITY_SPEECH 0 -#define OSMO_CC_CAPABILITY_DATA 8 -#define OSMO_CC_CAPABILITY_DATA_RESTRICTED 9 -#define OSMO_CC_CAPABILITY_AUDIO 16 -#define OSMO_CC_CAPABILITY_DATA_WITH_TONES 17 -#define OSMO_CC_CAPABILITY_VIDEO 24 -#define OSMO_CC_CAPABILITY_NUM 32 - -const char *osmo_cc_capability_value2name(int value); -int osmo_cc_capability_name2value(const char *name); - -/* transfer mode, see ITU-T Rec. Q.931 */ -#define OSMO_CC_MODE_CIRCUIT 0 -#define OSMO_CC_MODE_PACKET 2 -#define OSMO_CC_MODE_NUM 4 - -const char *osmo_cc_mode_value2name(int value); -int osmo_cc_mode_name2value(const char *name); - -#define OSMO_CC_DTMF_MODE_OFF 0 /* stop tone */ -#define OSMO_CC_DTMF_MODE_ON 1 /* start tone */ -#define OSMO_CC_DTMF_MODE_DIGITS 2 /* play tone(s) with duration and pauses */ -#define OSMO_CC_DTMF_MODE_NUM 3 - -const char *osmo_cc_dtmf_mode_value2name(int value); -int osmo_cc_dtmf_mode_name2value(const char *name); - -#define OSMO_CC_SOCKET_CAUSE_VERSION_MISMATCH 1 /* version mismatch */ -#define OSMO_CC_SOCKET_CAUSE_FAILED 2 /* connection failed */ -#define OSMO_CC_SOCKET_CAUSE_BROKEN_PIPE 3 /* connected socket failed */ -#define OSMO_CC_SOCKET_CAUSE_TIMEOUT 4 /* keepalive packets timeout */ -// if you add causes here, add them in process_cause.c also! -#define OSMO_CC_SOCKET_CAUSE_NUM 5 - -const char *osmo_cc_socket_cause_value2name(int value); -int osmo_cc_socket_cause_name2value(const char *name); - -/* network type (network IE) and meaning of 'id' */ -#define OSMO_CC_NETWORK_UNDEFINED 0x00 -#define OSMO_CC_NETWORK_ALSA_NONE 0x01 -#define OSMO_CC_NETWORK_POTS_NONE 0x02 -#define OSMO_CC_NETWORK_ISDN_NONE 0x03 -#define OSMO_CC_NETWORK_SIP_NONE 0x04 -#define OSMO_CC_NETWORK_GSM_IMSI 0x05 /* id has decimal IMSI */ -#define OSMO_CC_NETWORK_GSM_IMEI 0x06 /* id has decimal IMEI */ -#define OSMO_CC_NETWORK_WEB_NONE 0x07 -#define OSMO_CC_NETWORK_DECT_NONE 0x08 -#define OSMO_CC_NETWORK_BLUETOOTH_NONE 0x09 -#define OSMO_CC_NETWORK_SS5_NONE 0x0a -#define OSMO_CC_NETWORK_R1_NONE 0x0b -#define OSMO_CC_NETWORK_ANETZ_NONE 0x80 -#define OSMO_CC_NETWORK_BNETZ_MUENZ 0x81 /* id starts with 'M' */ -#define OSMO_CC_NETWORK_CNETZ_NONE 0x82 -#define OSMO_CC_NETWORK_NMT_NONE 0x83 /* id has decimal password */ -#define OSMO_CC_NETWORK_R2000_NONE 0x84 -#define OSMO_CC_NETWORK_AMPS_ESN 0x85 /* if has decimal ESN (TACS also) */ -#define OSMO_CC_NETWORK_MTS_NONE 0x86 -#define OSMO_CC_NETWORK_IMTS_NONE 0x87 -#define OSMO_CC_NETWORK_EUROSIGNAL_NONE 0x88 -#define OSMO_CC_NETWORK_JOLLYCOM_NONE 0x89 /* call from JollyCom... */ -#define OSMO_CC_NETWORK_MPT1327_PSTN 0x8a /* call from MPT1327 */ -#define OSMO_CC_NETWORK_MPT1327_PBX 0x8b /* id is selected PBX number */ -#define OSMO_CC_NETWORK_NUM 0x100 - -const char *osmo_cc_network_value2name(int value); -int osmo_cc_network_name2value(const char *name); - -typedef struct osmo_cc_msg { - uint8_t type; - uint16_t length_networkorder; - uint8_t data[0]; -} __attribute__((packed)) osmo_cc_msg_t; - -typedef struct osmo_cc_msg_list { - struct osmo_cc_msg_list *next; - struct osmo_cc_msg *msg; - uint32_t callref; - char host[128]; - uint16_t port; -} osmo_cc_msg_list_t; - -typedef struct osmo_cc_ie { - uint8_t type; - uint16_t length_networkorder; - uint8_t data[0]; -} __attribute__((packed)) osmo_cc_ie_t; - -struct osmo_cc_ie_called { - uint8_t type; - uint8_t plan; - char digits[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_called_sub { - uint8_t type; - char digits[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_called_name { - char name[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_called_interface { - char name[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_calling { - uint8_t type; - uint8_t plan; - uint8_t present; - uint8_t screen; - char digits[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_calling_sub { - uint8_t type; - char digits[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_calling_name { - char name[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_calling_interface { - char name[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_network { - uint8_t type; - char id[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_bearer { - uint8_t coding; - uint8_t capability; - uint8_t mode; -} __attribute__((packed)); - -struct osmo_cc_ie_redir { - uint8_t type; - uint8_t plan; - uint8_t present; - uint8_t screen; - uint8_t redir_reason; - char digits[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_dtmf { - uint8_t duration_ms; - uint8_t pause_ms; - uint8_t dtmf_mode; - char digits[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_keypad { - char digits[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_progress { - uint8_t coding; - uint8_t location; - uint8_t progress; -} __attribute__((packed)); - -struct osmo_cc_ie_notify { - uint8_t notify; -} __attribute__((packed)); - -struct osmo_cc_ie_cause { - uint8_t location; - uint8_t isdn_cause; - uint16_t sip_cause_networkorder; - uint8_t socket_cause; -} __attribute__((packed)); - -struct osmo_cc_ie_display { - char text[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_sdp { - char sdp[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_socket_address { - char address[0]; -} __attribute__((packed)); - -struct osmo_cc_ie_private { - uint32_t unique_networkorder; - uint8_t data[0]; -} __attribute__((packed)); - -uint32_t osmo_cc_new_callref(void); -osmo_cc_msg_t *osmo_cc_new_msg(uint8_t msg_type); -osmo_cc_msg_t *osmo_cc_clone_msg(osmo_cc_msg_t *msg); -osmo_cc_msg_t *osmo_cc_msg_list_dequeue(osmo_cc_msg_list_t **mlp, uint32_t *callref_p); -osmo_cc_msg_list_t *osmo_cc_msg_list_enqueue(osmo_cc_msg_list_t **mlp, osmo_cc_msg_t *msg, uint32_t callref); -void osmo_cc_free_msg(osmo_cc_msg_t *msg); -void osmo_cc_debug_ie(osmo_cc_msg_t *msg, int level); -int osmo_cc_get_ie_struct(osmo_cc_msg_t *msg, uint8_t ie_type, int ie_repeat, int ie_len, const osmo_cc_ie_t **ie_struct); -int osmo_cc_get_ie_data(osmo_cc_msg_t *msg, uint8_t ie_type, int ie_repeat, int ie_len, const void **ie_data); -int osmo_cc_has_ie(osmo_cc_msg_t *msg, uint8_t ie_type, int ie_repeat); -int osmo_cc_remove_ie(osmo_cc_msg_t *msg, uint8_t ie_type, int ie_repeat); -void *osmo_cc_add_ie(osmo_cc_msg_t *msg, uint8_t ie_type, int ie_len); -void *osmo_cc_msg_sep_ie(osmo_cc_msg_t *msg, void **iep, uint8_t *ie_type, uint16_t *ie_length); - -void osmo_cc_add_ie_called(osmo_cc_msg_t *msg, uint8_t type, uint8_t plan, const char *dialing); -int osmo_cc_get_ie_called(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, uint8_t *plan, char *dialing, size_t dialing_size); -void osmo_cc_add_ie_called_sub(osmo_cc_msg_t *msg, uint8_t type, const char *dialing); -int osmo_cc_get_ie_called_sub(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, char *dialing, size_t dialing_size); -void osmo_cc_add_ie_called_name(osmo_cc_msg_t *msg, const char *name); -int osmo_cc_get_ie_called_name(osmo_cc_msg_t *msg, int ie_repeat, char *name, size_t name_size); -void osmo_cc_add_ie_called_interface(osmo_cc_msg_t *msg, const char *interface); -int osmo_cc_get_ie_called_interface(osmo_cc_msg_t *msg, int ie_repeat, char *interface, size_t interface_size); -void osmo_cc_add_ie_complete(osmo_cc_msg_t *msg); -int osmo_cc_get_ie_complete(osmo_cc_msg_t *msg, int ie_repeat); -void osmo_cc_add_ie_calling(osmo_cc_msg_t *msg, uint8_t type, uint8_t plan, uint8_t present, uint8_t screen, const char *callerid); -int osmo_cc_get_ie_calling(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, uint8_t *plan, uint8_t *present, uint8_t *screen, char *callerid, size_t callerid_size); -void osmo_cc_add_ie_calling_sub(osmo_cc_msg_t *msg, uint8_t type, const char *callerid); -int osmo_cc_get_ie_calling_sub(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, char *callerid, size_t callerid_size); -void osmo_cc_add_ie_calling_name(osmo_cc_msg_t *msg, const char *name); -int osmo_cc_get_ie_calling_name(osmo_cc_msg_t *msg, int ie_repeat, char *name, size_t name_size); -void osmo_cc_add_ie_calling_interface(osmo_cc_msg_t *msg, const char *interface); -int osmo_cc_get_ie_calling_interface(osmo_cc_msg_t *msg, int ie_repeat, char *interface, size_t interface_size); -void osmo_cc_add_ie_calling_network(osmo_cc_msg_t *msg, uint8_t type, const char *networkid); -int osmo_cc_get_ie_calling_network(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, char *networkid, size_t networkid_size); -void osmo_cc_add_ie_bearer(osmo_cc_msg_t *msg, uint8_t coding, uint8_t capability, uint8_t mode); -int osmo_cc_get_ie_bearer(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *coding, uint8_t *capability, uint8_t *mode); -void osmo_cc_add_ie_redir(osmo_cc_msg_t *msg, uint8_t type, uint8_t plan, uint8_t present, uint8_t screen, uint8_t redir_reason, const char *callerid); -int osmo_cc_get_ie_redir(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, uint8_t *plan, uint8_t *present, uint8_t *screen, uint8_t *reason, char *callerid, size_t callerid_size); -void osmo_cc_add_ie_dtmf(osmo_cc_msg_t *msg, uint8_t duration_ms, uint8_t pause_ms, uint8_t dtmf_mode, const char *digits); -int osmo_cc_get_ie_dtmf(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *duration_ms, uint8_t *pause_ms, uint8_t *dtmf_mode, char *digits, size_t digits_size); -void osmo_cc_add_ie_keypad(osmo_cc_msg_t *msg, const char *digits); -int osmo_cc_get_ie_keypad(osmo_cc_msg_t *msg, int ie_repeat, char *digits, size_t digits_size); -void osmo_cc_add_ie_progress(osmo_cc_msg_t *msg, uint8_t coding, uint8_t location, uint8_t progress); -int osmo_cc_get_ie_progress(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *coding, uint8_t *location, uint8_t *progress); -void osmo_cc_add_ie_notify(osmo_cc_msg_t *msg, uint8_t notify); -int osmo_cc_get_ie_notify(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *notify); -void osmo_cc_add_ie_cause(osmo_cc_msg_t *msg, uint8_t location, uint8_t isdn_cause, uint16_t sip_cause, uint8_t socket_cause); -int osmo_cc_get_ie_cause(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *location, uint8_t *isdn_cause, uint16_t *sip_cause, uint8_t *socket_cause); -void osmo_cc_add_ie_display(osmo_cc_msg_t *msg, const char *text); -int osmo_cc_get_ie_display(osmo_cc_msg_t *msg, int ie_repeat, char *text, size_t text_size); -void osmo_cc_add_ie_sdp(osmo_cc_msg_t *msg, const char *sdp); -int osmo_cc_get_ie_sdp(osmo_cc_msg_t *msg, int ie_repeat, char *sdp, size_t sdp_size); -void osmo_cc_add_ie_socket_address(osmo_cc_msg_t *msg, const char *address); -int osmo_cc_get_ie_socket_address(osmo_cc_msg_t *msg, int ie_repeat, char *address, size_t address_size); -void osmo_cc_add_ie_private(osmo_cc_msg_t *msg, uint32_t unique, const uint8_t *data, size_t data_size); -int osmo_cc_get_ie_private(osmo_cc_msg_t *msg, int ie_repeat, uint32_t *unique, uint8_t *data, size_t data_size); - -#endif /* OSMO_CC_MSG_H */ diff --git a/src/libosmocc/rtp.c b/src/libosmocc/rtp.c deleted file mode 100644 index 31104b7..0000000 --- a/src/libosmocc/rtp.c +++ /dev/null @@ -1,484 +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 "../libdebug/debug.h" -#include "../libtimer/timer.h" -#include "../libselect/select.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(struct sockaddr_storage *sa, socklen_t *slen, int sock, uint8_t **payload_p, int *payload_len_p, uint8_t *marker_p, uint8_t *pt_p, uint16_t *sequence_p, uint32_t *timestamp_p, uint32_t *ssrc_p) -{ - static uint8_t data[2048]; - int len; - struct rtp_hdr *rtph = (struct rtp_hdr *)data; - uint8_t version, padding, extension, csrc_count, marker, payload_type; - struct rtp_x_hdr *rtpxh; - uint8_t *payload; - int payload_len; - int x_len; - - len = recvfrom(sock, data, sizeof(data), 0, (struct sockaddr *)sa, slen); - if (len < 0) { - if (errno == EAGAIN) - return -EAGAIN; - LOGP(DCC, LOGL_DEBUG, "Read errno = %d (%s)\n", errno, strerror(errno)); - return -EIO; - } - if (len < 12) { - LOGP(DCC, LOGL_NOTICE, "Received RTP frame too short (len = %d).\n", len); - return -EINVAL; - } - - version = rtph->byte0 >> 6; - padding = (rtph->byte0 >> 5) & 1; - extension = (rtph->byte0 >> 4) & 1; - csrc_count = rtph->byte0 & 0x0f; - marker = rtph->byte1 >> 7; - payload_type = rtph->byte1 & 0x7f; - *sequence_p = ntohs(rtph->sequence); - *timestamp_p = ntohl(rtph->timestamp); - *ssrc_p = ntohl(rtph->ssrc); - - if (version != RTP_VERSION) { - LOGP(DCC, LOGL_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) { - LOGP(DCC, LOGL_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)) { - LOGP(DCC, LOGL_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)) { - LOGP(DCC, LOGL_NOTICE, "Received RTP frame too short, extension header exceeds frame length.\n"); - return -EINVAL; - } - } - - if (padding) { - if (payload_len < 1) { - LOGP(DCC, LOGL_NOTICE, "Received RTP frame too short for padding length.\n"); - return -EINVAL; - } - payload_len -= payload[payload_len - 1]; - if (payload_len < 0) { - LOGP(DCC, LOGL_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 int rtcp_receive(struct sockaddr_storage *sa, socklen_t *slen, int sock) -{ - static uint8_t data[2048]; - int len; - - len = recvfrom(sock, data, sizeof(data), 0, (struct sockaddr *)sa, slen); - if (len < 0) { - if (errno == EAGAIN) - return -EAGAIN; - LOGP(DCC, LOGL_DEBUG, "Read errno = %d (%s)\n", errno, strerror(errno)); - return -EIO; - } - - return 0; -} - -static void rtp_send(struct sockaddr_storage *sa, socklen_t slen, int sock, uint8_t *payload, int payload_len, uint8_t marker, uint8_t pt, uint16_t sequence, uint32_t timestamp, uint32_t ssrc) -{ - struct rtp_hdr *rtph; - char data[sizeof(*rtph) + payload_len]; - int len, rc; - - rtph = (struct rtp_hdr *)data; - len = sizeof(*rtph); - rtph->byte0 = RTP_VERSION << 6; - rtph->byte1 = pt | (marker << 7); - rtph->sequence = htons(sequence); - rtph->timestamp = htonl(timestamp); - rtph->ssrc = htonl(ssrc); - len += payload_len; - if (len > (int)sizeof(data)) { - LOGP(DCC, LOGL_NOTICE, "Buffer overflow, please fix!.\n"); - abort(); - } - memcpy(data + sizeof(*rtph), payload, payload_len); - - rc = sendto(sock, data, len, 0, (struct sockaddr *)sa, slen); - if (rc < 0) - LOGP(DCC, LOGL_DEBUG, "sendto errno = %d (%s)\n", errno, strerror(errno)); -} - -static int rtp_listen_cb(struct osmo_fd *ofd, unsigned int when); -static int rtcp_listen_cb(struct osmo_fd *ofd, unsigned int when); - -/* 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; - socklen_t slen = 0; // make GCC happy - struct sockaddr_in6 *sa6; - struct sockaddr_in *sa4; - uint16_t *sport; - int flags; - int rc; - - media->tx_ssrc = rand(); - - osmo_cc_rtp_close(media); - - switch (media->connection_data_local.addrtype) { - case osmo_cc_session_addrtype_ipv4: - domain = AF_INET; - memset(&sa, 0, sizeof(sa)); - sa4 = (struct sockaddr_in *)&sa; - sa4->sin_family = domain; - rc = inet_pton(AF_INET, media->connection_data_local.address, &sa4->sin_addr); - if (rc < 1) { -pton_error: - LOGP(DCC, LOGL_NOTICE, "Cannot bind to address '%s'.\n", media->connection_data_local.address); - return -EINVAL; - } - sport = &sa4->sin_port; - slen = sizeof(*sa4); - break; - case osmo_cc_session_addrtype_ipv6: - domain = AF_INET6; - memset(&sa, 0, sizeof(sa)); - sa6 = (struct sockaddr_in6 *)&sa; - sa6->sin6_family = domain; - rc = inet_pton(AF_INET6, media->connection_data_local.address, &sa6->sin6_addr); - if (rc < 1) - goto pton_error; - sport = &sa6->sin6_port; - slen = sizeof(*sa6); - break; - case osmo_cc_session_addrtype_unknown: - LOGP(DCC, LOGL_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: - LOGP(DCC, LOGL_ERROR, "Cannot create socket (domain=%d, errno=%d(%s))\n", domain, errno, strerror(errno)); - osmo_cc_rtp_close(media); - return -EIO; - } - media->rtp_ofd.fd = rc; - media->rtp_ofd.cb = rtp_listen_cb; - media->rtp_ofd.data = media; - media->rtp_ofd.when = OSMO_FD_READ; - osmo_fd_register(&media->rtp_ofd); - rc = socket(domain, SOCK_DGRAM, IPPROTO_UDP); - if (rc < 0) - goto socket_error; - media->rtcp_ofd.fd = rc; - media->rtcp_ofd.cb = rtcp_listen_cb; - media->rtcp_ofd.data = media; - media->rtcp_ofd.when = OSMO_FD_READ; - osmo_fd_register(&media->rtcp_ofd); - - /* bind sockets */ - *sport = htons(conf->rtp_port_next); - rc = bind(media->rtp_ofd.fd, (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) { - LOGP(DCC, LOGL_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_ofd.fd, (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, to prevent write to block */ - flags = fcntl(media->rtp_ofd.fd, F_GETFL); - flags |= O_NONBLOCK; - fcntl(media->rtp_ofd.fd, F_SETFL, flags); - flags = fcntl(media->rtcp_ofd.fd, F_GETFL); - flags |= O_NONBLOCK; - fcntl(media->rtcp_ofd.fd, F_SETFL, flags); - break; - } - - LOGP(DCC, LOGL_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_in6 *sa6; - struct sockaddr_in *sa4; - int rc; - - LOGP(DCC, LOGL_DEBUG, "Connecting media port %d->%d (remote %s)\n", media->description.port_local, media->description.port_remote, media->connection_data_remote.address); - - switch (media->connection_data_remote.addrtype) { - case osmo_cc_session_addrtype_ipv4: - memset(&media->rtp_sa, 0, sizeof(media->rtp_sa)); - sa4 = (struct sockaddr_in *)&media->rtp_sa; - sa4->sin_family = AF_INET; - rc = inet_pton(AF_INET, media->connection_data_remote.address, &sa4->sin_addr); - if (rc < 1) { -pton_error: - LOGP(DCC, LOGL_NOTICE, "Cannot connect to address '%s'.\n", media->connection_data_remote.address); - return -EINVAL; - } - media->rtp_sport = &sa4->sin_port; - media->rtp_slen = sizeof(*sa4); - memcpy(&media->rtcp_sa, &media->rtp_sa, sizeof(*sa4)); - sa4 = (struct sockaddr_in *)&media->rtcp_sa; - media->rtcp_sport = &sa4->sin_port; - media->rtcp_slen = sizeof(*sa4); - break; - case osmo_cc_session_addrtype_ipv6: - memset(&media->rtp_sa, 0, sizeof(media->rtp_sa)); - sa6 = (struct sockaddr_in6 *)&media->rtp_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; - media->rtp_sport = &sa6->sin6_port; - media->rtp_slen = sizeof(*sa6); - memcpy(&media->rtcp_sa, &media->rtp_sa, sizeof(*sa6)); - sa6 = (struct sockaddr_in6 *)&media->rtcp_sa; - media->rtcp_sport = &sa6->sin6_port; - media->rtcp_slen = sizeof(*sa6); - break; - case osmo_cc_session_addrtype_unknown: - LOGP(DCC, LOGL_NOTICE, "Unsupported address type '%s'.\n", media->connection_data_local.addrtype_name); - return -EINVAL; - } - - *media->rtp_sport = htons(media->description.port_remote); - *media->rtcp_sport = htons(media->description.port_remote + 1); - - return 0; -} - -/* send rtp data with given codec */ -void osmo_cc_rtp_send(osmo_cc_session_codec_t *codec, uint8_t *data, int len, uint8_t marker, int inc_sequence, int inc_timestamp, void *priv) -{ - uint8_t *payload = NULL; - int payload_len = 0; - - if (!codec || !codec->media->rtp_ofd.fd) - return; - - if (codec->encoder) - codec->encoder(data, len, &payload, &payload_len, priv); - else { - payload = data; - payload_len = len; - } - - rtp_send(&codec->media->rtp_sa, codec->media->rtp_slen, codec->media->rtp_ofd.fd, payload, payload_len, marker, codec->payload_type_remote, codec->media->tx_sequence, codec->media->tx_timestamp, codec->media->tx_ssrc); - codec->media->tx_sequence += inc_sequence; - codec->media->tx_timestamp += inc_timestamp; - - if (codec->encoder) - free(payload); -} - -static void check_port_translation(struct sockaddr_storage *sa, struct sockaddr_storage *media_sa, const char *what) -{ - struct sockaddr_in6 *sa6, *sa6_2; - struct sockaddr_in *sa4, *sa4_2; - int from = 0, to = 0; - - if (sa->ss_family != media_sa->ss_family) - return; - - switch (sa->ss_family) { - case AF_INET: - sa4 = (struct sockaddr_in *)sa; - sa4_2 = (struct sockaddr_in *)media_sa; - if (sa4->sin_port != sa4_2->sin_port) { - if (!!memcmp(&sa4->sin_addr, &sa4_2->sin_addr, sizeof(struct in_addr))) - break; - from = ntohs(sa4_2->sin_port); - to = ntohs(sa4->sin_port); - sa4_2->sin_port = sa4->sin_port; - } - break; - case AF_INET6: - sa6 = (struct sockaddr_in6 *)sa; - sa6_2 = (struct sockaddr_in6 *)media_sa; - if (sa6->sin6_port != sa6_2->sin6_port) { - if (!!memcmp(&sa6->sin6_addr, &sa6_2->sin6_addr, sizeof(struct in6_addr))) - break; - from = ntohs(sa6_2->sin6_port); - to = ntohs(sa6->sin6_port); - sa6_2->sin6_port = sa6->sin6_port; - } - break; - } - - if (from) - LOGP(DCC, LOGL_NOTICE, "Remote sends with different %s port, changing from %d to %d!\n", what, from, to); -} - -static int rtp_listen_cb(struct osmo_fd *ofd, unsigned int when) -{ - osmo_cc_session_media_t *media = ofd->data; - 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; - struct sockaddr_storage sa; - socklen_t slen = sizeof(sa); // must be initialized and will be overwritten - - if (when & OSMO_FD_READ) { - rc = rtp_receive(&sa, &slen, media->rtp_ofd.fd, &payload, &payload_len, &marker, &payload_type, &media->rx_sequence, &media->rx_timestamp, &media->rx_ssrc); - if (rc < 0) - return rc; - check_port_translation(&sa, &media->rtp_sa, "RTP"); - - /* search for codec */ - for (codec = media->codec_list; codec; codec = codec->next) { - if (codec->payload_type_local == payload_type) - break; - } - if (!codec) { - LOGP(DCC, LOGL_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, media->session->priv); - else { - data = payload; - len = payload_len; - } - - if (codec->media->receive) - codec->media->receiver(codec, marker, media->rx_sequence, media->rx_timestamp, media->rx_ssrc, data, len); - - if (codec->decoder) - free(data); - } - - return 0; -} - -static int rtcp_listen_cb(struct osmo_fd *ofd, unsigned int when) -{ - osmo_cc_session_media_t *media = ofd->data; - int rc; - struct sockaddr_storage sa; - socklen_t slen = sizeof(sa); // must be initialized and will be overwritten - - if (when & OSMO_FD_READ) { - rc = rtcp_receive(&sa, &slen, media->rtcp_ofd.fd); - if (rc < 0) - return rc; - check_port_translation(&sa, &media->rtcp_sa, "RTCP"); - } - - return 0; -} - -void osmo_cc_rtp_close(osmo_cc_session_media_t *media) -{ - if (media->rtp_ofd.fd) { - osmo_fd_unregister(&media->rtp_ofd); - close(media->rtp_ofd.fd); - media->rtp_ofd.fd = 0; - } - if (media->rtcp_ofd.fd) { - osmo_fd_unregister(&media->rtcp_ofd); - close(media->rtcp_ofd.fd); - media->rtcp_ofd.fd = 0; - } -} - diff --git a/src/libosmocc/rtp.h b/src/libosmocc/rtp.h deleted file mode 100644 index ea1b31f..0000000 --- a/src/libosmocc/rtp.h +++ /dev/null @@ -1,7 +0,0 @@ - -void osmo_cc_set_rtp_ports(osmo_cc_session_config_t *conf, uint16_t from, uint16_t to); -int osmo_cc_rtp_open(osmo_cc_session_media_t *media); -int osmo_cc_rtp_connect(osmo_cc_session_media_t *media); -void osmo_cc_rtp_send(osmo_cc_session_codec_t *codec, uint8_t *data, int len, uint8_t marker, int inc_sequence, int inc_timestamp, void *priv); -void osmo_cc_rtp_close(osmo_cc_session_media_t *media); - diff --git a/src/libosmocc/screen.c b/src/libosmocc/screen.c deleted file mode 100644 index be12f08..0000000 --- a/src/libosmocc/screen.c +++ /dev/null @@ -1,694 +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 "../libselect/select.h" -#include "../libdebug/debug.h" -#include "endpoint.h" -#include "message.h" - -#define SCREEN_QUESTIONMARK 1 -#define SCREEN_STAR 2 -#define SCREEN_AT 3 - -void osmo_cc_help_screen(void) -{ - printf("Screening options:\n\n"); - - printf("screen-calling-in [attrs] [attrs] \n"); - printf("screen-called-in [attrs] [attrs] \n"); - printf("screen-calling-out [attrs] [attrs] \n"); - printf("screen-called-out [attrs] [attrs] \n\n"); - - printf("These options allow to screen an incoming or outgoing caller ID or dialed\n"); - printf("number. If 'the current caller ID' or 'current dialed number' matches, it will\n"); - printf("be replaced by 'new caller ID' or 'new dialed number'. 'incoming' means from\n"); - printf(" the interface and 'outgoing' means towards the interface.\n\n"); - - printf("Attributes prior 'current caller ID' or 'new dialed number' may be used to\n"); - printf("perform screening only if the attribute match. Attributes prior\n"); - printf("'new caller ID' or 'new dialed number' may be used to alter them. Attribute to\n"); - printf("define the type of number can be: 'unknown', 'international', 'national',\n"); - printf("'network', 'subscriber', 'abbreviated' Attribute to define the restriction of a\n"); - printf("caller ID: 'allowed', 'restricted'\n\n"); - - printf("The current caller ID or dialed number may contain one or more '?', to allow\n"); - printf("any digit to match. The current caller ID or dialed number may contain a '*',\n"); - printf("to allow any suffix to match from now on. The new caller ID or dialed number\n"); - printf("may contain a '*', to append the suffix from the current caller ID or dialed\n"); - printf("number.\n\n"); - - printf("When screening an incoming caller ID or dialed number, the '@' can be appended\n"); - printf("to the 'new caller ID', followed by a 'host:port', to route call to a special\n"); - printf("Osmo-CC endpoint. This way it is possible to do simple routing.\n\n"); -} - -char *osmo_cc_strtok_quotes(const char **text_p) -{ - static char token[1024]; - const char *text = *text_p; - int i, quote; - - /* skip spaces */ - while (*text) { - if (*text > 32) - break; - text++; - } - - /* if eol, return NULL */ - if (!(*text)) - return NULL; - - i = 0; - quote = 0; - while (*text) { - /* escape allows all following characters */ - if (*text == '\\') { - text++; - if (*text) - token[i++] = *text++; - continue; - } - /* no quote, check for them or break on white space */ - if (quote == 0) { - if (*text == '\'') { - quote = 1; - text++; - continue; - } - if (*text == '\"') { - quote = 2; - text++; - continue; - } - if (*text <= ' ') - break; - } - /* single quote, check for unquote */ - if (quote == 1 && *text == '\'') { - quote = 0; - text++; - continue; - } - /* double quote, check for unquote */ - if (quote == 2 && *text == '\"') { - quote = 0; - text++; - continue; - } - /* copy character */ - token[i++] = *text++; - } - token[i] = '\0'; - - *text_p = text; - return token; -} - -int osmo_cc_add_screen(osmo_cc_endpoint_t *ep, const char *text) -{ - osmo_cc_screen_list_t **list_p = NULL, *list; - const char *token; - int no_present = 0, calling_in = 0, star_used, at_used; - int i, j; - - star_used = 0; - if (!strncasecmp(text, "screen-calling-in", 17)) { - text += 17; - list_p = &ep->screen_calling_in; - no_present = 1; - calling_in = 1; - } else if (!strncasecmp(text, "screen-called-in", 16)) { - text += 16; - list_p = &ep->screen_called_in; - calling_in = 1; - } else if (!strncasecmp(text, "screen-calling-out", 18)) { - text += 18; - list_p = &ep->screen_calling_out; - no_present = 1; - } else if (!strncasecmp(text, "screen-called-out", 17)) { - text += 17; - list_p = &ep->screen_called_out; - } else { - LOGP(DCC, LOGL_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); - LOGP(DCC, LOGL_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); - LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text); - LOGP(DCC, LOGL_ERROR, "Keyword '%s' not allowed in screen entry for called number\n", token); - return -EINVAL; - } - list->has_from_present = 1; - list->from_present = OSMO_CC_PRESENT_ALLOWED; - goto next_from; - } else - if (!strcasecmp(token, "restricted")) { - if (no_present) - goto no_present_error; - list->has_from_present = 1; - list->from_present = OSMO_CC_PRESENT_RESTRICTED; - goto next_from; - } else { - star_used = 0; - for (i = j = 0; token[i] && j < (int)sizeof(list->from) - 1; i++, j++) { - if (token[i] == '?') - list->from[j] = SCREEN_QUESTIONMARK; - else - if (token[i] == '*') { - if (star_used) { - free(list); - LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text); - LOGP(DCC, LOGL_ERROR, "The '*' may be used only once.\n"); - return -EINVAL; - } - list->from[j] = SCREEN_STAR; - star_used = 1; - } else - if (token[i] == '\\' && token[i + 1] != '\0') - list->from[j] = token[++i]; - else - list->from[j] = token[i]; - } - list->from[j] = '\0'; - } - -next_to: - token = osmo_cc_strtok_quotes(&text); - if (!token) { - free(list); - LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text); - LOGP(DCC, LOGL_ERROR, "Missing screening result. If the string shall be empty, use double quotes. (\'\' or \"\")\n"); - return -EINVAL; - } - if (!strcasecmp(token, "unknown")) { - list->has_to_type = 1; - list->to_type = OSMO_CC_TYPE_UNKNOWN; - goto next_to; - } else - if (!strcasecmp(token, "international")) { - list->has_to_type = 1; - list->to_type = OSMO_CC_TYPE_INTERNATIONAL; - goto next_to; - } else - if (!strcasecmp(token, "national")) { - list->has_to_type = 1; - list->to_type = OSMO_CC_TYPE_NATIONAL; - goto next_to; - } else - if (!strcasecmp(token, "network")) { - list->has_to_type = 1; - list->to_type = OSMO_CC_TYPE_NETWORK; - goto next_to; - } else - if (!strcasecmp(token, "subscriber")) { - list->has_to_type = 1; - list->to_type = OSMO_CC_TYPE_SUBSCRIBER; - goto next_to; - } else - if (!strcasecmp(token, "abbreviated")) { - list->has_to_type = 1; - list->to_type = OSMO_CC_TYPE_ABBREVIATED; - goto next_to; - } else - if (!strcasecmp(token, "allowed")) { - if (no_present) - goto no_present_error; - list->has_to_present = 1; - list->to_present = OSMO_CC_PRESENT_ALLOWED; - goto next_to; - } else - if (!strcasecmp(token, "restricted")) { - if (no_present) - goto no_present_error; - list->has_to_present = 1; - list->to_present = OSMO_CC_PRESENT_RESTRICTED; - goto next_to; - } else { - at_used = star_used = 0; - for (i = j = 0; token[i] && j < (int)sizeof(list->to) - 1; i++, j++) { - if (token[i] == '*') { - if (star_used) { - free(list); - LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text); - LOGP(DCC, LOGL_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); - LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text); - LOGP(DCC, LOGL_ERROR, "The '@' may be used only for incoming calls from interface.\n"); - return -EINVAL; - } - if (at_used) { - free(list); - LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text); - LOGP(DCC, LOGL_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); - LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text); - LOGP(DCC, LOGL_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; - - LOGP(DCC, LOGL_INFO, "Screening %s '%s':\n", what, id_from); - switch (*type) { - case OSMO_CC_TYPE_UNKNOWN: - LOGP(DCC, LOGL_INFO, " -> type = unknown\n"); - break; - case OSMO_CC_TYPE_INTERNATIONAL: - LOGP(DCC, LOGL_INFO, " -> type = international\n"); - break; - case OSMO_CC_TYPE_NATIONAL: - LOGP(DCC, LOGL_INFO, " -> type = national\n"); - break; - case OSMO_CC_TYPE_NETWORK: - LOGP(DCC, LOGL_INFO, " -> type = network\n"); - break; - case OSMO_CC_TYPE_SUBSCRIBER: - LOGP(DCC, LOGL_INFO, " -> type = subscriber\n"); - break; - case OSMO_CC_TYPE_ABBREVIATED: - LOGP(DCC, LOGL_INFO, " -> type = abbreviated\n"); - break; - } - if (present) switch (*present) { - case OSMO_CC_PRESENT_ALLOWED: - LOGP(DCC, LOGL_INFO, " -> present = allowed\n"); - break; - case OSMO_CC_PRESENT_RESTRICTED: - LOGP(DCC, LOGL_INFO, " -> present = restricted\n"); - break; - } - - rule = 0; - while (list) { - rule++; - LOGP(DCC, LOGL_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: - LOGP(DCC, LOGL_INFO, " -> type = unknown\n"); - break; - case OSMO_CC_TYPE_INTERNATIONAL: - LOGP(DCC, LOGL_INFO, " -> type = international\n"); - break; - case OSMO_CC_TYPE_NATIONAL: - LOGP(DCC, LOGL_INFO, " -> type = national\n"); - break; - case OSMO_CC_TYPE_NETWORK: - LOGP(DCC, LOGL_INFO, " -> type = network\n"); - break; - case OSMO_CC_TYPE_SUBSCRIBER: - LOGP(DCC, LOGL_INFO, " -> type = subscriber\n"); - break; - case OSMO_CC_TYPE_ABBREVIATED: - LOGP(DCC, LOGL_INFO, " -> type = abbreviated\n"); - break; - } - if (list->has_from_present) switch (list->from_present) { - case OSMO_CC_PRESENT_ALLOWED: - LOGP(DCC, LOGL_INFO, " -> present = allowed\n"); - break; - case OSMO_CC_PRESENT_RESTRICTED: - LOGP(DCC, LOGL_INFO, " -> present = restricted\n"); - break; - } - suffix = NULL; - /* attributes do not match */ - if (list->has_from_type && list->from_type != *type) { - LOGP(DCC, LOGL_INFO, "Rule does not match, because 'type' is different.\n"); - continue; - } - if (present && list->has_from_present && list->from_present != *present) { - LOGP(DCC, LOGL_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; - LOGP(DCC, LOGL_INFO, "Rule does not match, because %s is different.\n", what); - list = list->next; - } - - /* if no list entry matches */ - if (!list) - return -1; - - /* replace ID */ - if (list->has_to_type) { - *type = list->to_type; - } - if (present && list->has_to_present) { - *present = list->to_present; - } - for (i = j = 0; list->to[i]; i++) { - if (j == id_to_size - 1) - break; - /* '*' means to use suffix of input string */ - if (list->to[i] == SCREEN_STAR && suffix) { - while (*suffix) { - id_to[j++] = *suffix++; - if (j == id_to_size - 1) - break; - } - continue; - /* '@' means to stop and return routing also */ - } else if (list->to[i] == SCREEN_AT) { - if (routing_p) - *routing_p = &list->to[i + 1]; - break; - } - /* copy output digit */ - id_to[j++] = list->to[i]; - } - id_to[j] = '\0'; - - LOGP(DCC, LOGL_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: - LOGP(DCC, LOGL_INFO, " -> type = unknown\n"); - break; - case OSMO_CC_TYPE_INTERNATIONAL: - LOGP(DCC, LOGL_INFO, " -> type = international\n"); - break; - case OSMO_CC_TYPE_NATIONAL: - LOGP(DCC, LOGL_INFO, " -> type = national\n"); - break; - case OSMO_CC_TYPE_NETWORK: - LOGP(DCC, LOGL_INFO, " -> type = network\n"); - break; - case OSMO_CC_TYPE_SUBSCRIBER: - LOGP(DCC, LOGL_INFO, " -> type = subscriber\n"); - break; - case OSMO_CC_TYPE_ABBREVIATED: - LOGP(DCC, LOGL_INFO, " -> type = abbreviated\n"); - break; - } - if (list->has_to_present) switch (list->to_present) { - case OSMO_CC_PRESENT_ALLOWED: - LOGP(DCC, LOGL_INFO, " -> present = allowed\n"); - break; - case OSMO_CC_PRESENT_RESTRICTED: - LOGP(DCC, LOGL_INFO, " -> present = restricted\n"); - break; - } - if (routing_p && *routing_p) - LOGP(DCC, LOGL_INFO, " -> remote = %s\n", *routing_p); - - return 0; -} - -osmo_cc_msg_t *osmo_cc_screen_msg(osmo_cc_endpoint_t *ep, osmo_cc_msg_t *old_msg, int in, const char **routing_p) -{ - osmo_cc_msg_t *new_msg; - char id[256], calling[256], called[256], redir[256]; - uint8_t calling_type, calling_plan, calling_present, calling_screen; - uint8_t called_type, called_plan; - uint8_t redir_type, redir_plan, redir_present, redir_screen, redir_reason; - int calling_status = 0, called_status = 0, redir_status = 0; - int rc; - void *ie, *to_ie; - uint8_t ie_type; - uint16_t ie_length; - void *ie_value; - - if (in && ep->screen_calling_in) { - rc = osmo_cc_get_ie_calling(old_msg, 0, &calling_type, &calling_plan, &calling_present, &calling_screen, id, sizeof(id)); - if (rc >= 0) { - rc = osmo_cc_screen("incoming caller ID", ep->screen_calling_in, &calling_type, &calling_present, calling, sizeof(calling), id, routing_p); - if (rc >= 0) - calling_status = 1; - } else { - calling_type = OSMO_CC_TYPE_UNKNOWN; - calling_plan = OSMO_CC_PLAN_TELEPHONY; - calling_present = OSMO_CC_PRESENT_ALLOWED; - calling_screen = OSMO_CC_SCREEN_NETWORK; - rc = osmo_cc_screen("incoming caller ID", ep->screen_calling_in, &calling_type, &calling_present, calling, sizeof(calling), "", routing_p); - if (rc >= 0) - calling_status = 1; - } - rc = osmo_cc_get_ie_redir(old_msg, 0, &redir_type, &redir_plan, &redir_present, &redir_screen, &redir_reason, id, sizeof(id)); - if (rc >= 0) { - rc = osmo_cc_screen("incoming redirecting number", ep->screen_calling_in, &redir_type, &redir_present, redir, sizeof(redir), id, NULL); - if (rc >= 0) - redir_status = 1; - } - } - if (in && ep->screen_called_in) { - rc = osmo_cc_get_ie_called(old_msg, 0, &called_type, &called_plan, id, sizeof(id)); - if (rc >= 0) { - rc = osmo_cc_screen("incoming dialed number", ep->screen_called_in, &called_type, NULL, called, sizeof(called), id, routing_p); - if (rc >= 0) - called_status = 1; - } else { - called_type = OSMO_CC_TYPE_UNKNOWN; - called_plan = OSMO_CC_PLAN_TELEPHONY; - rc = osmo_cc_screen("incoming dialed number", ep->screen_called_in, &called_type, NULL, called, sizeof(called), "", routing_p); - if (rc >= 0) - called_status = 1; - } - } - if (!in && ep->screen_calling_out) { - rc = osmo_cc_get_ie_calling(old_msg, 0, &calling_type, &calling_plan, &calling_present, &calling_screen, id, sizeof(id)); - if (rc >= 0) { - rc = osmo_cc_screen("outgoing caller ID", ep->screen_calling_out, &calling_type, &calling_present, calling, sizeof(calling), id, NULL); - if (rc >= 0) - calling_status = 1; - } else { - calling_type = OSMO_CC_TYPE_UNKNOWN; - calling_plan = OSMO_CC_PLAN_TELEPHONY; - calling_present = OSMO_CC_PRESENT_ALLOWED; - calling_screen = OSMO_CC_SCREEN_NETWORK; - rc = osmo_cc_screen("outgoing caller ID", ep->screen_calling_out, &calling_type, &calling_present, calling, sizeof(calling), "", NULL); - if (rc >= 0) - calling_status = 1; - } - rc = osmo_cc_get_ie_redir(old_msg, 0, &redir_type, &redir_plan, &redir_present, &redir_screen, &redir_reason, id, sizeof(id)); - if (rc >= 0) { - rc = osmo_cc_screen("outgoing redirecting number", ep->screen_calling_out, &redir_type, &redir_present, redir, sizeof(redir), id, NULL); - if (rc >= 0) - redir_status = 1; - } - } - if (!in && ep->screen_called_out) { - rc = osmo_cc_get_ie_called(old_msg, 0, &called_type, &called_plan, id, sizeof(id)); - if (rc >= 0) { - rc = osmo_cc_screen("outgoing dialed number", ep->screen_called_out, &called_type, NULL, called, sizeof(called), id, NULL); - if (rc >= 0) - called_status = 1; - } else { - called_type = OSMO_CC_TYPE_UNKNOWN; - called_plan = OSMO_CC_PLAN_TELEPHONY; - rc = osmo_cc_screen("outgoing dialed number", ep->screen_called_out, &called_type, NULL, called, sizeof(called), "", NULL); - if (rc >= 0) - called_status = 1; - } - } - - /* nothing screened */ - if (!calling_status && !called_status && !redir_status) - return old_msg; - - new_msg = osmo_cc_new_msg(old_msg->type); - - /* copy and replace */ - ie = old_msg->data; - while ((ie_value = osmo_cc_msg_sep_ie(old_msg, &ie, &ie_type, &ie_length))) { - switch (ie_type) { - case OSMO_CC_IE_CALLING: - if (calling_status) { - osmo_cc_add_ie_calling(new_msg, calling_type, calling_plan, calling_present, calling_screen, calling); - calling_status = 0; - break; - } - goto copy; - case OSMO_CC_IE_CALLED: - if (called_status) { - osmo_cc_add_ie_called(new_msg, called_type, called_plan, called); - called_status = 0; - break; - } - goto copy; - case OSMO_CC_IE_REDIR: - if (redir_status) { - osmo_cc_add_ie_redir(new_msg, redir_type, redir_plan, redir_present, redir_screen, redir_reason, redir); - redir_status = 0; - break; - } - goto copy; - default: - copy: - to_ie = osmo_cc_add_ie(new_msg, ie_type, ie_length); - memcpy(to_ie, ie_value, ie_length); - } - } - - /* applend, if not yet in message (except redir, since it must exist) */ - if (calling_status) - osmo_cc_add_ie_calling(new_msg, calling_type, calling_plan, calling_present, calling_screen, calling); - if (called_status) - osmo_cc_add_ie_called(new_msg, called_type, called_plan, called); - - free(old_msg); - return new_msg; -} - diff --git a/src/libosmocc/screen.h b/src/libosmocc/screen.h deleted file mode 100644 index 29f4515..0000000 --- a/src/libosmocc/screen.h +++ /dev/null @@ -1,7 +0,0 @@ - -void osmo_cc_help_screen(void); -char *osmo_cc_strtok_quotes(const char **text_p); -int osmo_cc_add_screen(osmo_cc_endpoint_t *ep, const char *text); -void osmo_cc_flush_screen(osmo_cc_screen_list_t *list); -osmo_cc_msg_t *osmo_cc_screen_msg(osmo_cc_endpoint_t *ep, osmo_cc_msg_t *old_msg, int in, const char **routing_p); - diff --git a/src/libosmocc/sdp.c b/src/libosmocc/sdp.c deleted file mode 100644 index e350d52..0000000 --- a/src/libosmocc/sdp.c +++ /dev/null @@ -1,545 +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 "../libselect/select.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) { - LOGP(DCC, LOGL_ERROR, "Fatal error: Allocated SDP buffer with %d bytes is too small, please fix!\n", (int)sizeof(sdp)); - return NULL; - } - return sdp; -} - -/* separate a word from string that is delimited with one or more space characters */ -static char *wordsep(char **text_p) -{ - char *text = *text_p; - static char word[256]; - int i; - - /* no text */ - if (text == NULL || *text == '\0') - return NULL; - /* skip spaces before text */ - while (*text && *text <= ' ') - text++; - /* copy content */ - i = 0; - while (*text > ' ' && i < (int)sizeof(word)) - word[i++] = *text++; - word[i] = '\0'; - /* set next */ - *text_p = text; - return word; -} - -/* - * codecs and their default values - * - * if format is -1, payload type is dynamic - * if rate is 0, rate may be any rate - */ -struct codec_defaults { - int fmt; - char *name; - uint32_t rate; - int channels; -} codec_defaults[] = { - { 0, "PCMU", 8000, 1 }, - { 3, "GSM", 8000, 1 }, - { 4, "G723", 8000, 1 }, - { 5, "DVI4", 8000, 1 }, - { 6, "DVI4", 16000, 1 }, - { 7, "LPC", 8000, 1 }, - { 8, "PCMA", 8000, 1 }, - { 9, "G722", 8000, 1 }, - { 10, "L16", 44100, 2 }, - { 11, "L16", 44100, 1 }, - { 12, "QCELP", 8000, 1 }, - { 13, "CN", 8000, 1 }, - { 14, "MPA", 90000, 1 }, - { 15, "G728", 8000, 1 }, - { 16, "DVI4", 11025, 1 }, - { 17, "DVI4", 22050, 1 }, - { 18, "G729", 8000, 1 }, - { 25, "CELB", 90000, 0 }, - { 26, "JPEG", 90000, 0 }, - { 28, "nv", 90000, 0 }, - { 31, "H261", 90000, 0 }, - { 32, "MPV", 90000, 0 }, - { 33, "MP2T", 90000, 0 }, - { 34, "H263", 90000, 0 }, - { -1, NULL, 0, 0 }, -}; - -static void complete_codec_by_fmt(uint8_t fmt, const char **name, uint32_t *rate, int *channels) -{ - int i; - - for (i = 0; codec_defaults[i].name; i++) { - if (codec_defaults[i].fmt == fmt) - break; - } - if (!codec_defaults[i].name) - return; - - free((char *)*name); - *name = strdup(codec_defaults[i].name); - *rate = codec_defaults[i].rate; - *channels = codec_defaults[i].channels; -} - -int osmo_cc_payload_type_by_attrs(uint8_t *fmt, const char *name, uint32_t *rate, int *channels) -{ - int i; - - for (i = 0; codec_defaults[i].name; i++) { - if (!strcmp(codec_defaults[i].name, name) - && (*rate == 0 || codec_defaults[i].rate == *rate) - && (*channels == 0 || codec_defaults[i].channels == *channels)) - break; - } - if (!codec_defaults[i].name) - return -EINVAL; - - *fmt = codec_defaults[i].fmt; - *rate = codec_defaults[i].rate; - *channels = codec_defaults[i].channels; - - return 0; -} - -/* parses data and codec list from SDP - * - * sdp = given SDP text - * return: SDP session description structure */ -struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf, void *priv, const char *_sdp) -{ - char buffer[strlen(_sdp) + 1], *sdp = buffer; - char *line, *p, *word, *next_word; - int line_no = 0; - struct osmo_cc_session_connection_data ccd, *cd; - int csend = 1, creceive = 1; /* common default */ - struct osmo_cc_session *session = NULL; - struct osmo_cc_session_media *media = NULL; - struct osmo_cc_session_codec *codec = NULL; - - /* prepare data */ - strcpy(sdp, _sdp); - memset(&ccd, 0, sizeof(ccd)); - - /* create SDP session description */ - session = osmo_cc_new_session(conf, priv, NULL, NULL, NULL, 0, 0, NULL, NULL, 0); - - /* check every line of SDP and parse its data */ - while(*sdp) { - if ((p = strchr(sdp, '\r'))) { - *p++ = '\0'; - if (*p == '\n') - p++; - line = sdp; - sdp = p; - } else if ((p = strchr(sdp, '\n'))) { - *p++ = '\0'; - line = sdp; - sdp = p; - } else { - line = sdp; - sdp = strchr(sdp, '\0'); - } - next_word = line + 2; - line_no++; - - if (line[0] == '\0') - continue; - - if (line[1] != '=') { - LOGP(DCC, LOGL_NOTICE, "SDP line %d = '%s' is garbage, expecting '=' as second character.\n", line_no, line); - continue; - } - - switch(line[0]) { - case 'v': - LOGP(DCC, LOGL_DEBUG, " -> Version: %s\n", next_word); - if (atoi(next_word) != 0) { - LOGP(DCC, LOGL_NOTICE, "SDP line %d = '%s' describes unsupported version.\n", line_no, line); - osmo_cc_free_session(session); - return NULL; - } - break; - case 'o': - LOGP(DCC, LOGL_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 */ - LOGP(DCC, LOGL_DEBUG, " -> Session Name: %s\n", next_word); - free((char *)session->name); // if already set - session->name = strdup(next_word); - break; - case 'c': /* Connection Data */ - LOGP(DCC, LOGL_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 { - LOGP(DCC, LOGL_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; - LOGP(DCC, LOGL_DEBUG, " -> Address Type = IPv4\n"); - } else - if (!strcmp(word, "IP6")) { - cd->addrtype = osmo_cc_session_addrtype_ipv6; - LOGP(DCC, LOGL_DEBUG, " -> Address Type = IPv6\n"); - } else { - LOGP(DCC, LOGL_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); - LOGP(DCC, LOGL_DEBUG, " -> Address = %s\n", word); - break; - case 'm': /* Media Description */ - LOGP(DCC, LOGL_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); - LOGP(DCC, LOGL_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); - LOGP(DCC, LOGL_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); - LOGP(DCC, LOGL_DEBUG, " -> payload type = %d\n", codec->payload_type_remote); - if (codec->payload_name) - LOGP(DCC, LOGL_DEBUG, " -> payload name = %s\n", codec->payload_name); - if (codec->payload_rate) - LOGP(DCC, LOGL_DEBUG, " -> payload rate = %d\n", codec->payload_rate); - if (codec->payload_channels) - LOGP(DCC, LOGL_DEBUG, " -> payload channels = %d\n", codec->payload_channels); - } - break; - case 'a': - LOGP(DCC, LOGL_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) { - LOGP(DCC, LOGL_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) { - LOGP(DCC, LOGL_NOTICE, "Attribute without previously defined codec in SDP line %d = '%s'\n", line_no, line); - break; - } - LOGP(DCC, LOGL_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); - LOGP(DCC, LOGL_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); - LOGP(DCC, LOGL_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); - LOGP(DCC, LOGL_DEBUG, " -> (rtpmap) payload channels = %d\n", codec->payload_channels); - rtpmap_done: - if (!codec->payload_name || !codec->payload_rate || !codec->payload_channels) { - LOGP(DCC, LOGL_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)) { - LOGP(DCC, LOGL_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'; - LOGP(DCC, LOGL_DEBUG, " | %s\n", text); - while (*sdp > 0 && *sdp < 32) - sdp++; - } -} - diff --git a/src/libosmocc/sdp.h b/src/libosmocc/sdp.h deleted file mode 100644 index c9bc721..0000000 --- a/src/libosmocc/sdp.h +++ /dev/null @@ -1,6 +0,0 @@ - -char *osmo_cc_session_gensdp(struct osmo_cc_session *session); -struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf, void *priv, const char *_sdp); -int osmo_cc_payload_type_by_attrs(uint8_t *fmt, const char *name, uint32_t *rate, int *channels); -void osmo_cc_debug_sdp(const char *sdp); - diff --git a/src/libosmocc/session.c b/src/libosmocc/session.c deleted file mode 100644 index f4e7b88..0000000 --- a/src/libosmocc/session.c +++ /dev/null @@ -1,625 +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 "../libselect/select.h" -#include "../libdebug/debug.h" -#include "../liboptions/options.h" -#include "endpoint.h" - -#define NTP_OFFSET 2208988800U - -void osmo_cc_set_local_peer(osmo_cc_session_config_t *conf, enum osmo_cc_session_nettype nettype, enum osmo_cc_session_addrtype addrtype, const char *address) -{ - conf->default_nettype = nettype; - conf->default_addrtype = addrtype; - conf->default_unicast_address = options_strdup(address); -} - -osmo_cc_session_t *osmo_cc_new_session(osmo_cc_session_config_t *conf, void *priv, const char *username, const char *sess_id, const char *sess_version, enum osmo_cc_session_nettype nettype, enum osmo_cc_session_addrtype addrtype, const char *unicast_address, const char *session_name, int debug) -{ - osmo_cc_session_t *session; - - if (debug) LOGP(DCC, LOGL_DEBUG, "Creating session structure.\n"); - - session = calloc(1, sizeof(*session)); - if (!session) { - LOGP(DCC, LOGL_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) { - LOGP(DCC, LOGL_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) LOGP(DCC, LOGL_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) LOGP(DCC, LOGL_DEBUG, " -> session ID = %s\n", session->origin_local.sess_id); - if (debug) LOGP(DCC, LOGL_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) LOGP(DCC, LOGL_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) LOGP(DCC, LOGL_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) LOGP(DCC, LOGL_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) LOGP(DCC, LOGL_DEBUG, " -> session name = %s\n", session->name); - - return session; -} - -void osmo_cc_free_session(osmo_cc_session_t *session) -{ - LOGP(DCC, LOGL_DEBUG, "Free session structure.\n"); - - free((char *)session->origin_local.username); - free((char *)session->origin_local.sess_id); - free((char *)session->origin_local.sess_version); - free((char *)session->origin_local.nettype); - free((char *)session->origin_local.addrtype); - free((char *)session->origin_local.unicast_address); - free((char *)session->origin_remote.username); - free((char *)session->origin_remote.sess_id); - free((char *)session->origin_remote.sess_version); - free((char *)session->origin_remote.nettype); - free((char *)session->origin_remote.addrtype); - free((char *)session->origin_remote.unicast_address); - free((char *)session->name); - while (session->media_list) - osmo_cc_free_media(session->media_list); - free(session); -} - -osmo_cc_session_media_t *osmo_cc_add_media(osmo_cc_session_t *session, enum osmo_cc_session_nettype nettype, enum osmo_cc_session_addrtype addrtype, const char *address, enum osmo_cc_session_media_type type, uint16_t port, enum osmo_cc_session_media_proto proto, int send, int receive, void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len), int debug) -{ - osmo_cc_session_config_t *conf = session->config; - osmo_cc_session_media_t *media, **mediap; - - media = calloc(1, sizeof(*media)); - if (!media) { - LOGP(DCC, LOGL_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) LOGP(DCC, LOGL_DEBUG, "Adding session media.\n"); - if (debug) LOGP(DCC, LOGL_DEBUG, " -> network type = %s\n", osmo_cc_session_nettype2string(media->connection_data_local.nettype)); - if (debug) LOGP(DCC, LOGL_DEBUG, " -> address type = %s\n", osmo_cc_session_addrtype2string(media->connection_data_local.addrtype)); - if (debug) LOGP(DCC, LOGL_DEBUG, " -> address = %s\n", media->connection_data_local.address); - if (debug) LOGP(DCC, LOGL_DEBUG, " -> media type = %s\n", osmo_cc_session_media_type2string(media->description.type)); - if (debug) LOGP(DCC, LOGL_DEBUG, " -> media port = %d\n", media->description.port_local); - if (debug) LOGP(DCC, LOGL_DEBUG, " -> media proto = %s\n", osmo_cc_session_media_proto2string(media->description.proto)); - if (debug) LOGP(DCC, LOGL_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; - - LOGP(DCC, LOGL_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 *priv), void (*decoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv), int debug) -{ - osmo_cc_session_codec_t *codec, **codecp; - int rc; - - codec = calloc(1, sizeof(*codec)); - if (!codec) { - LOGP(DCC, LOGL_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) LOGP(DCC, LOGL_DEBUG, "Adding session codec.\n"); - if (debug) LOGP(DCC, LOGL_DEBUG, " -> payload type = %d\n", codec->payload_type_local); - if (debug) LOGP(DCC, LOGL_DEBUG, " -> payload name = %s\n", codec->payload_name); - if (debug) LOGP(DCC, LOGL_DEBUG, " -> payload rate = %d\n", codec->payload_rate); - if (debug) LOGP(DCC, LOGL_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; - - LOGP(DCC, LOGL_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) { - LOGP(DCC, LOGL_NOTICE, "Missing data in session origin\n"); - return -EINVAL; - } - if (!session->name) { - LOGP(DCC, LOGL_NOTICE, "Missing data in session origin\n"); - return -EINVAL; - } - if (!session->media_list) { - LOGP(DCC, LOGL_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) { - LOGP(DCC, LOGL_NOTICE, "Session with media #%d is missing connection network type\n", i); - return -EINVAL; - } - if (!cd->addrtype && !cd->addrtype_name) { - LOGP(DCC, LOGL_NOTICE, "Session with media #%d is missing connection address type\n", i); - return -EINVAL; - } - if (!cd->address) { - LOGP(DCC, LOGL_NOTICE, "Session with media #%d is missing connection address\n", i); - return -EINVAL; - } - md = &media->description; - if (!md->type && !md->type_name) { - LOGP(DCC, LOGL_NOTICE, "Session with media #%d is missing media type\n", i); - return -EINVAL; - } - if (!md->proto && !md->proto_name) { - LOGP(DCC, LOGL_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) { - LOGP(DCC, LOGL_NOTICE, "Session with media #%d, codec #%d is missing name\n", i, j); - return -EINVAL; - } - if (!codec->payload_rate) { - LOGP(DCC, LOGL_NOTICE, "Session with media #%d, codec #%d is missing rate\n", i, j); - return -EINVAL; - } - if (!codec->payload_channels) { - LOGP(DCC, LOGL_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; - - LOGP(DCC, LOGL_DEBUG, "Generating session offer and opening RTP stream.\n"); - - rc = osmo_cc_session_check(session, 0); - if (rc < 0) { - LOGP(DCC, LOGL_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; - - LOGP(DCC, LOGL_DEBUG, "Parsing session offer.\n"); - - osmo_cc_debug_sdp(sdp); - session = osmo_cc_session_parsesdp(conf, priv, sdp); - if (!session) - return NULL; - - rc = osmo_cc_session_check(session, 0); - if (rc < 0) { - osmo_cc_free_session(session); - return NULL; - } - - return session; -} - -void osmo_cc_session_accept_media(osmo_cc_session_media_t *media, enum osmo_cc_session_nettype nettype, enum osmo_cc_session_addrtype addrtype, const char *address, int send, int receive, void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len)) -{ - osmo_cc_session_config_t *conf = media->session->config; - - media->accepted = 1; - if (nettype) - media->connection_data_local.nettype = nettype; - else - media->connection_data_local.nettype = conf->default_nettype; - if (addrtype) - media->connection_data_local.addrtype = addrtype; - else - media->connection_data_local.addrtype = conf->default_addrtype; - free((char *)media->connection_data_local.address); - if (address) - media->connection_data_local.address = strdup(address); - else - media->connection_data_local.address = strdup(conf->default_unicast_address); - media->send = send; - media->receive = receive; - media->receiver = receiver; - - LOGP(DCC, LOGL_DEBUG, "Accepting session media.\n"); - LOGP(DCC, LOGL_DEBUG, " -> network type = %s\n", osmo_cc_session_nettype2string(media->connection_data_local.nettype)); - LOGP(DCC, LOGL_DEBUG, " -> address type = %s\n", osmo_cc_session_addrtype2string(media->connection_data_local.addrtype)); - LOGP(DCC, LOGL_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 *priv), void (*decoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv)) -{ - 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; - - LOGP(DCC, LOGL_DEBUG, "Accepting session codec.\n"); - LOGP(DCC, LOGL_DEBUG, " -> payload type = %d\n", codec->payload_type_local); - LOGP(DCC, LOGL_DEBUG, " -> payload name = %s\n", codec->payload_name); - LOGP(DCC, LOGL_DEBUG, " -> payload rate = %d\n", codec->payload_rate); - LOGP(DCC, LOGL_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; - - LOGP(DCC, LOGL_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) { - LOGP(DCC, LOGL_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; - - LOGP(DCC, LOGL_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) { - LOGP(DCC, LOGL_NOTICE, "Negotiation failed, because remote endpoint returns less media streams than we offered.\n"); - return -EINVAL; - } - if (media_remote) { - LOGP(DCC, LOGL_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; - - LOGP(DCC, LOGL_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); -} - diff --git a/src/libosmocc/session.h b/src/libosmocc/session.h deleted file mode 100644 index 1317f4c..0000000 --- a/src/libosmocc/session.h +++ /dev/null @@ -1,134 +0,0 @@ -#include - -/* configuration */ - -enum osmo_cc_session_nettype { - osmo_cc_session_nettype_unknown = 0, - osmo_cc_session_nettype_inet, -}; - -enum osmo_cc_session_addrtype { - osmo_cc_session_addrtype_unknown = 0, - osmo_cc_session_addrtype_ipv4, - osmo_cc_session_addrtype_ipv6, -}; - -typedef struct osmo_cc_session_config { - enum osmo_cc_session_nettype default_nettype; - enum osmo_cc_session_addrtype default_addrtype; - const char *default_unicast_address; - uint16_t rtp_port_next; - uint16_t rtp_port_from; - uint16_t rtp_port_to; -} osmo_cc_session_config_t; - -/* session description, global part: */ - -typedef struct osmo_cc_session_origin { - const char *username; - const char *sess_id; - const char *sess_version; - const char *nettype; - const char *addrtype; - const char *unicast_address; -} osmo_cc_session_origin_t; - -/* session instance */ -typedef struct osmo_cc_session { - osmo_cc_session_config_t *config; - void *priv; - osmo_cc_session_origin_t origin_local, origin_remote; - const char *name; - struct osmo_cc_session_media *media_list; -} osmo_cc_session_t; - -/* connection description: */ - -typedef struct osmo_cc_session_connection_data { - enum osmo_cc_session_nettype nettype; - const char *nettype_name; - enum osmo_cc_session_addrtype addrtype; - const char *addrtype_name; - const char *address; -} osmo_cc_session_connection_data_t; - -/* one media of session description: */ - -enum osmo_cc_session_media_type { - osmo_cc_session_media_type_unknown, - osmo_cc_session_media_type_audio, - osmo_cc_session_media_type_video, -}; - -enum osmo_cc_session_media_proto { - osmo_cc_session_media_proto_unknown, - osmo_cc_session_media_proto_rtp, -}; - -typedef struct osmo_cc_session_media_description { - enum osmo_cc_session_media_type type; - const char *type_name; - uint16_t port_local, port_remote; - enum osmo_cc_session_media_proto proto; - const char *proto_name; -} osmo_cc_session_media_description_t; - -/* media entry */ -typedef struct osmo_cc_session_media { - struct osmo_cc_session_media *next; - osmo_cc_session_t *session; - osmo_cc_session_media_description_t description; - osmo_cc_session_connection_data_t connection_data_local, connection_data_remote; - struct osmo_cc_session_codec *codec_list; - int send, receive; - void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len); - struct sockaddr_storage rtp_sa, rtcp_sa; - socklen_t rtp_slen, rtcp_slen; - uint16_t *rtp_sport, *rtcp_sport; // pointers to the port inside sa sockaddr - struct osmo_fd rtp_ofd; - struct osmo_fd rtcp_ofd; - uint32_t tx_ssrc, rx_ssrc; - uint16_t tx_sequence, rx_sequence; - uint32_t tx_timestamp, rx_timestamp; - int accepted; -} osmo_cc_session_media_t; - -/* codec entry */ -typedef struct osmo_cc_session_codec { - struct osmo_cc_session_codec *next; - osmo_cc_session_media_t *media; - uint8_t payload_type_local, payload_type_remote; /* local = towards local, remote = toward remote */ - const char *payload_name; - uint32_t payload_rate; - int payload_channels; - void (*encoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv); - void (*decoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv); - int accepted; -} osmo_cc_session_codec_t; - -#define osmo_cc_session_for_each_media(head, m) \ - for (m = (head); m; m = m->next) - -#define osmo_cc_session_for_each_codec(head, c) \ - for (c = (head); c; c = c->next) - -void osmo_cc_set_local_peer(osmo_cc_session_config_t *conf, enum osmo_cc_session_nettype nettype, enum osmo_cc_session_addrtype addrtype, const char *address); -osmo_cc_session_t *osmo_cc_new_session(osmo_cc_session_config_t *conf, void *priv, const char *username, const char *sess_id, const char *sess_version, enum osmo_cc_session_nettype nettype, enum osmo_cc_session_addrtype addrtype, const char *unicast_address, const char *session_name, int debug); -void osmo_cc_free_session(osmo_cc_session_t *session); -osmo_cc_session_media_t *osmo_cc_add_media(osmo_cc_session_t *session, enum osmo_cc_session_nettype nettype, enum osmo_cc_session_addrtype addrtype, const char *address, enum osmo_cc_session_media_type type, uint16_t port, enum osmo_cc_session_media_proto proto, int send, int receive, void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len), int debug); -void osmo_cc_free_media(osmo_cc_session_media_t *media); -osmo_cc_session_codec_t *osmo_cc_add_codec(osmo_cc_session_media_t *media, const char *playload_name, uint32_t playload_rate, int playload_channels, void (*encoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv), void (*decoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv), int debug); -void osmo_cc_free_codec(osmo_cc_session_codec_t *codec); -int osmo_cc_session_check(struct osmo_cc_session *session, int remote); -const char *osmo_cc_session_send_offer(osmo_cc_session_t *session); -osmo_cc_session_t *osmo_cc_session_receive_offer(osmo_cc_session_config_t *conf, void *priv, const char *sdp); -void osmo_cc_session_accept_media(osmo_cc_session_media_t *media, enum osmo_cc_session_nettype nettype, enum osmo_cc_session_addrtype addrtype, const char *address, int send, int receive, void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len)); -void osmo_cc_session_accept_codec(osmo_cc_session_codec_t *codec, void (*encoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv), void (*decoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv)); -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); - diff --git a/src/libosmocc/socket.c b/src/libosmocc/socket.c deleted file mode 100644 index 9d8f30a..0000000 --- a/src/libosmocc/socket.c +++ /dev/null @@ -1,619 +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 "../libselect/select.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) { - LOGP(DCC, LOGL_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); -} - -static void tx_keepalive_timeout(void *data) -{ - osmo_cc_conn_t *conn = data; - 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); - -static void rx_keepalive_timeout(void *data) -{ - osmo_cc_conn_t *conn = data; - - LOGP(DCC, LOGL_ERROR, "OsmoCC-Socket failed due to timeout.\n"); - close_conn(conn, OSMO_CC_SOCKET_CAUSE_TIMEOUT); -} - -static int socket_listen_cb(struct osmo_fd *ofd, unsigned int when); - -/* 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; - - 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; - } - - LOGP(DCC, LOGL_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) { - LOGP(DCC, LOGL_DEBUG, "Failed to bind host %s port %d, trying again.\n", host, port); - goto try_again; - } - LOGP(DCC, LOGL_ERROR, "Failed to bind given host %s port %d.\n", host, port); - return -EIO; - } - - /* listen to socket */ - rc = listen(sock, 10); - if (rc < 0) { - LOGP(DCC, LOGL_ERROR, "Failed to listen on socket.\n"); - close(sock); - return rc; - } - - /* register */ - os->ofd.fd = sock; - os->ofd.cb = socket_listen_cb; - os->ofd.data = os; - os->ofd.when = OSMO_FD_READ; - osmo_fd_register(&os->ofd); - os->recv_msg_cb = recv_msg_cb; - os->priv = priv; - os->location = location; - - return port; -} - -static int socket_conn_cb(struct osmo_fd *ofd, unsigned int when); - -/* 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) { - LOGP(DCC, LOGL_ERROR, "No mem!\n"); - abort(); - } - conn->os = os; - conn->ofd.fd = sock; - conn->ofd.cb = socket_conn_cb; - conn->ofd.data = conn; - conn->ofd.when = OSMO_FD_READ; - osmo_fd_register(&conn->ofd); - 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); - - LOGP(DCC, LOGL_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); - } - - LOGP(DCC, LOGL_DEBUG, "Destroy socket connection (callref %d).\n", conn->callref); - - /* close socket */ - if (conn->ofd.fd) { - osmo_fd_unregister(&conn->ofd); - close(conn->ofd.fd); - } - /* 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; - - LOGP(DCC, LOGL_DEBUG, "Destroy socket.\n"); - - /* free all connections */ - while (os->conn_list) - close_conn(os->conn_list, 0); - /* close socket */ - if (os->ofd.fd > 0) { - osmo_fd_unregister(&os->ofd); - close(os->ofd.fd); - os->ofd.fd = 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->ofd.fd, 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)) { - LOGP(DCC, LOGL_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]) { - LOGP(DCC, LOGL_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->ofd.fd, ((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->ofd.fd, 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) { - LOGP(DCC, LOGL_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: - LOGP(DCC, LOGL_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->ofd.fd, version_string, strlen(version_string)); - if (rc < 0 && errno == EAGAIN) - return work; - work = 1; - if (rc <= 0) { - goto close; - } - if (rc != strlen(version_string)) { - LOGP(DCC, LOGL_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->ofd.fd, msg, len); - if (rc < 0 && errno == EAGAIN) - return work; - work = 1; - if (rc <= 0) { - goto close; - } - if (rc != len) { - LOGP(DCC, LOGL_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) { - LOGP(DCC, LOGL_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: - LOGP(DCC, LOGL_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) -{ - 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; - conn->ofd.when |= OSMO_FD_WRITE; - /* 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) { - LOGP(DCC, LOGL_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, to prevent connect() and subsequent reads from blocking */ - 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) { - LOGP(DCC, LOGL_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; - conn->ofd.when |= OSMO_FD_WRITE; - /* done with (setup) message */ - } - - return work; -} - -static int socket_listen_cb(struct osmo_fd *ofd, unsigned int when) -{ - osmo_cc_socket_t *os = ofd->data; - struct sockaddr_storage sa; - socklen_t slen = sizeof(sa); - int sock; - int flags; - - if (when & OSMO_FD_READ) { - /* handle new socket connection */ - if ((sock = accept(os->ofd.fd, (struct sockaddr *)&sa, &slen)) > 0) { - /* set nonblocking io, to prevent subsequent reads from blocking */ - flags = fcntl(sock, F_GETFL); - flags |= O_NONBLOCK; - fcntl(sock, F_SETFL, flags); - /* create connection */ - open_conn(os, sock, 0, 1); - } - } - - return 0; -} - -static int socket_conn_cb(struct osmo_fd *ofd, unsigned int when) -{ - osmo_cc_conn_t *conn = ofd->data; - int work; - - if (when & OSMO_FD_READ) { - /* check for rx */ - work = receive_conn(conn); - /* if "change" is set, connection list might have changed, so we restart processing the list */ - if (work) - return 0; - } - if (when & OSMO_FD_WRITE) { - /* check for tx */ - work = transmit_conn(conn); - /* if "change" is set, connection list might have changed, so we restart processing the list */ - if (work) - return 0; - else - conn->ofd.when &= ~OSMO_FD_WRITE; - } - - return 0; -} - diff --git a/src/libosmocc/socket.h b/src/libosmocc/socket.h deleted file mode 100644 index a3cc046..0000000 --- a/src/libosmocc/socket.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef OSMO_CC_SOCKET_H -#define OSMO_CC_SOCKET_H - -#define OSMO_CC_DEFAULT_PORT 4200 -#define OSMO_CC_DEFAULT_PORT_MAX 4219 - -#define OSMO_CC_SOCKET_TX_KEEPALIVE 10.0 -#define OSMO_CC_SOCKET_RX_KEEPALIVE 20.0 - -struct osmo_cc_socket; - -typedef struct osmo_cc_conn { - struct osmo_cc_conn *next; - struct osmo_cc_socket *os; - struct osmo_fd ofd; - 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 { - struct osmo_fd ofd; - 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/libph_socket/ph_socket.c b/src/libph_socket/ph_socket.c index 28ec30f..7aaf529 100644 --- a/src/libph_socket/ph_socket.c +++ b/src/libph_socket/ph_socket.c @@ -3,9 +3,11 @@ * (C) 2022 by Andreas Eversberg * All Rights Reserved * - * This program is free software: you can redistribute it and/or modify + * SPDX-License-Identifier: GPL-2.0+ + * + * 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 + * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, @@ -13,8 +15,10 @@ * 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 . + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * */ #include @@ -26,9 +30,10 @@ #include #include #include -#include "../libtimer/timer.h" -#include "../libselect/select.h" -#include "../libdebug/debug.h" +#include +#include +#include +#include "../liblogging/logging.h" #include "ph_socket.h" static int ph_socket_listen_cb(struct osmo_fd *ofd, unsigned int __attribute__((unused)) what); diff --git a/src/libph_socket/ph_socket.h b/src/libph_socket/ph_socket.h index 97293c3..0d8cb6a 100644 --- a/src/libph_socket/ph_socket.h +++ b/src/libph_socket/ph_socket.h @@ -4,12 +4,12 @@ /* * Procedure: * - * If socket connection is establised, a PH_PRIM_CTRL_REQ message with + * If socket connection is established, a PH_PRIM_CTRL_REQ message with * PH_CTRL_ENABLE information is received by the socket server user. * If the socket connection is lost, a PH_PRIM_CTRL_REQ message with * PH_CTRL_DISABLE information is received by the user. - * - * If socket connection is establised, a PH_PRIM_CTRL_IND message with + * + * If socket connection is established, a PH_PRIM_CTRL_IND message with * PH_CTRL_ENABLE information is received by the socket client user. * If the socket connection is lost, a PH_PRIM_CTRL_IND message with * PH_CTRL_DISABLE information is received by the user. @@ -24,14 +24,14 @@ * PH_PRIM_DACT_IND, if the socket is currently unavailable. * * PH_PRIM_CTRL_REQ and PH_PRIM_CTRL_IND messages with PH_CTRL_ENABLE - * and PH_CTRL_DISABLE informations are not assoicated with a channel + * and PH_CTRL_DISABLE information are not associated with a channel * number. The socket sender shall set it to 0, the receiver shall * ignore it. * - * A missing MODE in PH_PRIM_ACT_REQ is interepreted as default: + * A missing MODE in PH_PRIM_ACT_REQ is interpreted as default: * HDLC on D-channel, TRANS on B-channel. * - * Each packet on the socket shall have the follwoing header: + * Each packet on the socket shall have the following header: * uint8_t channel; * uint8_t prim; * uint16_t length; @@ -65,8 +65,8 @@ #define PH_CTRL_BLOCK 0x00 /* disable (block) interface, when socket is disconnected */ #define PH_CTRL_UNBLOCK 0x01 /* enable (unblock) interface, when socket is connected */ #define PH_CTRL_LOOP_DISABLE 0x04 /* disable loopback */ -#define PH_CTRL_LOOP1_ENABLE 0x05 /* enable LT transceier loopback */ -#define PH_CTRL_LOOP2_ENABLE 0x06 /* enable NT transceier loopback */ +#define PH_CTRL_LOOP1_ENABLE 0x05 /* enable LT transceiver loopback */ +#define PH_CTRL_LOOP2_ENABLE 0x06 /* enable NT transceiver loopback */ #define PH_CTRL_LOOP_ERROR 0x10 /* frame error report (loopback test) */ #define PH_CTRL_VIOLATION_LT 0x11 /* code violation received by LT */ #define PH_CTRL_VIOLATION_NT 0x12 /* code violation received by NT */ diff --git a/src/libselect/Makefile.am b/src/libselect/Makefile.am deleted file mode 100644 index 76ff4d6..0000000 --- a/src/libselect/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) - -noinst_LIBRARIES = libselect.a - -libselect_a_SOURCES = \ - select.c diff --git a/src/libselect/select.c b/src/libselect/select.c deleted file mode 100644 index 3a4c0b1..0000000 --- a/src/libselect/select.c +++ /dev/null @@ -1,168 +0,0 @@ -/* Timer handling - * - * (C) 2023 by Andreas Eversberg - * All Rights Reserved - * - * Inspired by libosmocore - * - * 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 "select.h" - -//#define DEBUG - -#define MAX_OFD 1024 - -struct osmo_fd *ofd_list = NULL; -int ofd_changed = 0; - -int osmo_fd_register(struct osmo_fd *ofd) -{ - struct osmo_fd **ofdp; - - /* attach to list, if not already */ - ofdp = &ofd_list; - while (*ofdp) { - if (*ofdp == ofd) - break; - ofdp = &((*ofdp)->next); - } - if (!*ofdp) { -#ifdef DEBUG - fprintf(stderr, "%s: ofd=%p fd=%d registers.\n", __func__, ofd, ofd->fd); -#endif - ofd->next = NULL; - *ofdp = ofd; - ofd_changed = 1; - } - - return 0; -} - -void osmo_fd_unregister(struct osmo_fd *ofd) -{ - struct osmo_fd **ofdp; - - /* detach from list, if not already */ - ofdp = &ofd_list; - while (*ofdp) { - if (*ofdp == ofd) - break; - ofdp = &((*ofdp)->next); - } - if (*ofdp) { -#ifdef DEBUG - fprintf(stderr, "%s: ofd=%p fd=%d unregisters.\n", __func__, ofd, ofd->fd); -#endif - *ofdp = ofd->next; - ofd->next = NULL; - ofd_changed = 1; - } -} - -int osmo_fd_select(double timeout) -{ - fd_set readset; - fd_set writeset; - fd_set exceptset; - struct osmo_fd *ofd; - struct timeval tv; - int max_fd; - unsigned int what; - int work = 0; - int rc; - - /* init event sets */ - FD_ZERO(&readset); - FD_ZERO(&writeset); - FD_ZERO(&exceptset); - - /* populate event set with all file descriptios */ - ofd = ofd_list; - max_fd = 0; - while (ofd) { - if (ofd->fd > max_fd) - max_fd = ofd->fd; - if (ofd->when & OSMO_FD_READ) - FD_SET(ofd->fd, &readset); - if (ofd->when & OSMO_FD_WRITE) - FD_SET(ofd->fd, &writeset); - if (ofd->when & OSMO_FD_EXCEPT) - FD_SET(ofd->fd, &exceptset); - ofd = ofd->next; - } - - if (timeout >= 0) { - /* prepare timeout */ - tv.tv_sec = floor(timeout); - tv.tv_usec = (timeout - tv.tv_sec) * 1000000.0; - /* wait for event or timeout */ - rc = select(max_fd + 1, &readset, &writeset, &exceptset, &tv); - } else { - /* wait for event */ - rc = select(max_fd + 1, &readset, &writeset, &exceptset, NULL); - } - if (rc < 0) { - if (errno != EINTR) - fprintf(stderr, "%s: select() failed: '%d' with errno %d (%s) Please fix!\n", __func__, rc, errno, strerror(errno)); - return 0; - } - -again: - /* check the result and call handler */ - ofd_changed = 0; - ofd = ofd_list; - while (ofd) { - what = 0; - if (FD_ISSET(ofd->fd, &readset)) { -#ifdef DEBUG - fprintf(stderr, "%s: ofd=%p fd=%d get READ event.\n", __func__, ofd, ofd->fd); -#endif - what |= OSMO_FD_READ; - FD_CLR(ofd->fd, &readset); - } - if (FD_ISSET(ofd->fd, &writeset)) { -#ifdef DEBUG - fprintf(stderr, "%s: ofd=%p fd=%d get WRITE event.\n", __func__, ofd, ofd->fd); -#endif - what |= OSMO_FD_WRITE; - FD_CLR(ofd->fd, &writeset); - } - if (FD_ISSET(ofd->fd, &exceptset)) { -#ifdef DEBUG - fprintf(stderr, "%s: ofd=%p fd=%d get EXCEPTION event.\n", __func__, ofd, ofd->fd); -#endif - what |= OSMO_FD_EXCEPT; - FD_CLR(ofd->fd, &exceptset); - } - if (what) { - work = 1; - ofd->cb(ofd, what); - /* list has changed */ - if (ofd_changed) - goto again; - } - ofd = ofd->next; - } - - return work; -} - diff --git a/src/libselect/select.h b/src/libselect/select.h deleted file mode 100644 index def1000..0000000 --- a/src/libselect/select.h +++ /dev/null @@ -1,20 +0,0 @@ - -#define OSMO_FD_READ 0x0001 -#define OSMO_FD_WRITE 0x0002 -#define OSMO_FD_EXCEPT 0x0004 -#define BSC_FD_READ 0x0001 -#define BSC_FD_WRITE 0x0002 -#define BSC_FD_EXCEPT 0x0004 - -struct osmo_fd { - struct osmo_fd *next; - int fd; - unsigned int when; - int (*cb)(struct osmo_fd *fd, unsigned int what); - void *data; -}; - -int osmo_fd_register(struct osmo_fd *ofd); -void osmo_fd_unregister(struct osmo_fd *ofd); -int osmo_fd_select(double timeout); - diff --git a/src/libtimer/Makefile.am b/src/libtimer/Makefile.am deleted file mode 100644 index 538670a..0000000 --- a/src/libtimer/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) - -noinst_LIBRARIES = libtimer.a - -libtimer_a_SOURCES = \ - timer.c diff --git a/src/libtimer/timer.c b/src/libtimer/timer.c deleted file mode 100644 index a5fa85c..0000000 --- a/src/libtimer/timer.c +++ /dev/null @@ -1,165 +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" - -//#define DEBUG - -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)(void *data), void *priv) -{ - if (timer->linked) { - fprintf(stderr, "Timer is already initialized, aborting!\n"); - abort(); - } - - timer->timeout = 0; - timer->cb = fn; - timer->data = priv; - timer->next = NULL; - *timer_tail_p = timer; - timer_tail_p = &timer->next; - timer->linked = 1; -#ifdef DEBUG - fprintf(stderr, "%s: timer=%p linked.\n", __func__, timer); -#endif -} - -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; -#ifdef DEBUG - fprintf(stderr, "%s: timer=%p unlinked.\n", __func__, timer); -#endif -} - -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; -#ifdef DEBUG - fprintf(stderr, "%s: timer=%p started %.3f seconds.\n", __func__, timer, duration); -#endif -} - -void timer_stop(struct timer *timer) -{ - if (!timer->linked) { - fprintf(stderr, "Timer is not initialized, aborting!\n"); - abort(); - } - - timer->timeout = 0; -#ifdef DEBUG - fprintf(stderr, "%s: timer=%p stopped.\n", __func__, timer); -#endif -} - -int timer_running(struct timer *timer) -{ - if (!timer->linked) { - fprintf(stderr, "Timer is not initialized, aborting!\n"); - abort(); - } - - return (timer->timeout != 0); -} - -double process_timer(void) -{ - struct timer *timer; - double now, timeout = -1.0; - - now = get_time(); - -again: - timer = timer_head; - while (timer) { - if (timer->linked && timer->timeout > 0) { - /* timeout, handle it, set timeout to 0 */ - if (now >= timer->timeout) { - timer->timeout = 0; -#ifdef DEBUG - fprintf(stderr, "%s: timer=%p fired.\n", __func__, timer); -#endif - if (!timer->cb) - abort(); - timer->cb(timer->data); - timeout = 0.0; - goto again; - } - /* in the future, set timeout to future */ - if (timeout < 0.0 || (timer->timeout - now) < timeout) - timeout = timer->timeout - now; - } - timer = timer->next; - } - - return timeout; -} - -void osmo_timer_schedule(struct osmo_timer_list *ti, time_t sec, suseconds_t usec) -{ - if (!ti->linked) - timer_init(ti, ti->cb, ti->data); - timer_start(ti, (double)sec + (double)usec / 1000000.0); -} - -void osmo_timer_del(struct osmo_timer_list *ti) -{ - timer_exit(ti); -} - -int osmo_timer_pending(struct osmo_timer_list *ti) -{ - if (!ti->linked) - return 0; - return (ti->timeout != 0); -} - diff --git a/src/libtimer/timer.h b/src/libtimer/timer.h deleted file mode 100644 index f7dbbbc..0000000 --- a/src/libtimer/timer.h +++ /dev/null @@ -1,23 +0,0 @@ - -struct timer { - struct timer *next; - int linked; /* set is timer is initialized and linked */ - double duration; - double timeout; - void (*cb)(void *data); - void *data; -}; - -double get_time(void); -void timer_init(struct timer *timer, void (*fn)(void *data), 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); -double process_timer(void); - -#define osmo_timer_list timer -void osmo_timer_schedule(struct osmo_timer_list *ti, time_t sec, long usec); -void osmo_timer_del(struct osmo_timer_list *ti); -int osmo_timer_pending(struct osmo_timer_list *ti); - From ea6f1bec84ac3d91f1f3779a8fa01a244c5a38a8 Mon Sep 17 00:00:00 2001 From: Dennis Grunert Date: Tue, 9 Jan 2024 13:28:05 +0100 Subject: [PATCH 3/9] AOC-D and AOC-S facility generation from CC metering information If metering details via IE_METERING are received from osmo-cc, AOC-S and/or AOC-D facility IEs are attached to PROCEEDING/ALERTING/CONNECT messages, and AOC-D facility messages are generated during the call. This feature can be enabled by setting 'aocs' and/or 'aocd' within the mISDN endpoint configuration. --- src/isdn/dss1.c | 172 ++++++++++++++++++++ src/isdn/isdn.c | 7 +- src/isdn/isdn.h | 12 +- src/isdn/main.c | 18 ++- src/libmisdnuser/include/mISDN/suppserv.h | 31 ++++ src/libmisdnuser/suppserv/fac.c | 182 ++++++++++++++++++++++ 6 files changed, 419 insertions(+), 3 deletions(-) diff --git a/src/isdn/dss1.c b/src/isdn/dss1.c index 51517e5..1272d4c 100644 --- a/src/isdn/dss1.c +++ b/src/isdn/dss1.c @@ -184,6 +184,107 @@ static void split_3pty(call_t *call) } } +/* Generate AOC-S facility IE from metering information */ +#define AOCS_CURRENCY_AMOUNT_PER_UNIT 5 +static void generate_aocs_ie(call_t *call, struct l3_msg *l3m) +{ + uint8_t fac_ie[256]; + struct asn1_parm fac; + + if (call->isdn_ep->ntmode && call->isdn_ep->aocs && call->metering_info_received) { + memset(&fac, 0, sizeof(fac)); + fac.Valid = 1; + fac.comp = CompInvoke; + fac.u.inv.invokeId = 2; /* doesn't matter since no response is expected */ + fac.u.inv.operationValue = Fac_AOCSCurrency; + + LOGP(DISDN, LOGL_DEBUG, "Sending AOC-S information from metering data: connect_units=%d unit_period_decisecs=%d\n", call->metering_connect_units, call->metering_unit_period_decisecs); + + if(call->metering_connect_units == 0) { // Free call + LOGP(DISDN, LOGL_DEBUG, "AOC-S currencyInfoList: BasicComm FreeOfCharge\n"); + fac.u.inv.o.AOCcuril.currencyInfoCount = 1; + fac.u.inv.o.AOCcuril.currencyInfo[0].chargedItem = 0x00; // basic comm + fac.u.inv.o.AOCcuril.currencyInfo[0].currencyType = 0x84; // free + } + else if(call->metering_unit_period_decisecs == 0) { // setup/connect FlatRate + /* note some payphones (e.g. BluePhone) only interpret 'basic comm' charged item, therefore we don't use 'call setup' charged item */ + LOGP(DISDN, LOGL_DEBUG, "AOC-S currencyInfoList: BasicComm FlatRate\n"); + fac.u.inv.o.AOCcuril.currencyInfoCount = 1; + fac.u.inv.o.AOCcuril.currencyInfo[0].chargedItem = 0x00; // basic comm + fac.u.inv.o.AOCcuril.currencyInfo[0].currencyType = 0xA2; // FlatRate + strncpy((char *)fac.u.inv.o.AOCcuril.currencyInfo[0].FlatRateCurrency.currency, "EUR", 10); // Currency value + fac.u.inv.o.AOCcuril.currencyInfo[0].FlatRateCurrency.currencyAmount = AOCS_CURRENCY_AMOUNT_PER_UNIT * call->metering_connect_units; + fac.u.inv.o.AOCcuril.currencyInfo[0].FlatRateCurrency.multiplier = 1; // 1/100 EUR + } + else if(call->metering_connect_units == 1) { // Normal call + LOGP(DISDN, LOGL_DEBUG, "AOC-S currencyInfoList: BasicComm DurationCurrency\n"); + fac.u.inv.o.AOCcuril.currencyInfoCount = 1; + fac.u.inv.o.AOCcuril.currencyInfo[0].chargedItem = 0x00; // basic comm + fac.u.inv.o.AOCcuril.currencyInfo[0].currencyType = 0xA1; // DurationCurrency + strncpy((char *)fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.currency, "EUR", 10); // Currency value + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.currencyAmount = AOCS_CURRENCY_AMOUNT_PER_UNIT; + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.multiplier = 1; // 1/100 EUR + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.typeOfCharging = 0x00; // Contin. Charging + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.durLengthTimeUnit = call->metering_unit_period_decisecs * 10; // Unit duration + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.durLengthTimeScale = 0x00; // 1/100 s + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.granLengthTimeUnit = 1; // Granularity 1 + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.granLengthTimeScale = 2; // 1/1 s + } + else { // Special call with setup/connect FlatRate + /* note some payphones (e.g. BluePhone) only interpret 'basic comm' charged item */ + LOGP(DISDN, LOGL_DEBUG, "AOC-S currencyInfoList: BasicComm DurationCurrency / CallSetup FlatRate\n"); + fac.u.inv.o.AOCcuril.currencyInfoCount = 2; + fac.u.inv.o.AOCcuril.currencyInfo[0].chargedItem = 0x00; // basic comm + fac.u.inv.o.AOCcuril.currencyInfo[0].currencyType = 0xA1; // DurationCurrency + strncpy((char *)fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.currency, "EUR", 10); // Currency value + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.currencyAmount = AOCS_CURRENCY_AMOUNT_PER_UNIT; + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.multiplier = 1; // 1/100 EUR + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.typeOfCharging = 0x00; // Contin. Charging + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.durLengthTimeUnit = call->metering_unit_period_decisecs * 10; // Unit duration + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.durLengthTimeScale = 0x00; // 1/100 s + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.granLengthTimeUnit = 1; // Granularity 1 + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.granLengthTimeScale = 2; // 1/1 s + fac.u.inv.o.AOCcuril.currencyInfo[1].chargedItem = 0x02; // call setup + fac.u.inv.o.AOCcuril.currencyInfo[1].currencyType = 0xA2; // FlatRate + strncpy((char *)fac.u.inv.o.AOCcuril.currencyInfo[1].FlatRateCurrency.currency, "EUR", 10); // Currency value + fac.u.inv.o.AOCcuril.currencyInfo[1].FlatRateCurrency.currencyAmount = AOCS_CURRENCY_AMOUNT_PER_UNIT * call->metering_connect_units; + fac.u.inv.o.AOCcuril.currencyInfo[1].FlatRateCurrency.multiplier = 1; // 1/100 EUR + } + + encodeFac(fac_ie, &fac); + enc_ie_facility(l3m, fac_ie + 2, fac_ie[1]); + } +} + +/* AOC-D timer callback */ +static void aocd_timer_cb(void *data) +{ + uint8_t fac_ie[256]; + struct asn1_parm fac; + struct l3_msg *l3m; + call_t *call = data; + + call->metering_total_units++; + + LOGP(DISDN, LOGL_DEBUG, "Sending next AOC-D unit information, total_units=%d\n", call->metering_total_units); + + osmo_timer_schedule(&call->aocd_unit_timer, call->metering_unit_period_decisecs / 10, (call->metering_unit_period_decisecs % 10) * 100000); + + memset(&fac, 0, sizeof(fac)); + fac.Valid = 1; + fac.comp = CompInvoke; + fac.u.inv.invokeId = 2; /* doesn't matter since no response is expected */ + fac.u.inv.operationValue = Fac_AOCDChargingUnit; + fac.u.inv.o.AOCchu.recordedUnits = call->metering_total_units; + + encodeFac(fac_ie, &fac); + + // sending facility + l3m = create_l3msg(); + enc_ie_facility(l3m, fac_ie + 2, fac_ie[1]); + call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_FACILITY, call->l3_pid, l3m); +} + /* * handles all indications from ISDN stack */ @@ -354,6 +455,10 @@ void setup_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) call->cc_callref = cc_call->callref; LOGP(DDSS1, LOGL_DEBUG, " -> new callref assigned (callref = %d)\n", call->cc_callref); + /* reset AOC information */ + call->metering_info_received = 0; + call->aocd_unit_timer_started = 0; + new_state(call, ISDN_STATE_IN_SETUP); /* send message to osmo-cc */ @@ -766,6 +871,13 @@ void disconnect_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) /* send message to osmo-cc */ osmo_cc_ll_msg(&call->isdn_ep->cc_ep, call->cc_callref, msg); + + /* stop AOC-D timer */ + if(call->aocd_unit_timer_started) + { + osmo_timer_del(&call->aocd_unit_timer); + call->aocd_unit_timer_started = 0; + } } /* CC-DISCONNECT INDICATION of child instance */ @@ -1981,6 +2093,13 @@ void proc_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg, int with_ies) if (rc >= 0 && call->isdn_ep->ntmode) enc_ie_redirection(l3m, type, plan, 1, present, redir); + /* Metering handling and AOC-S generation */ + rc = osmo_cc_get_ie_metering(msg, 0, &(call->metering_connect_units), &(call->metering_unit_period_decisecs)); + if(rc >= 0) { + call->metering_info_received = 1; + generate_aocs_ie(call, l3m); + } + skip_ies: new_state(call, ISDN_STATE_IN_PROCEEDING); @@ -2038,6 +2157,13 @@ void alert_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg) if (rc >= 0 && call->isdn_ep->ntmode) enc_ie_redirection(l3m, type, plan, 1, present, redir); + /* Metering handling and AOC-S generation */ + rc = osmo_cc_get_ie_metering(msg, 0, &(call->metering_connect_units), &(call->metering_unit_period_decisecs)); + if(rc >= 0) { + call->metering_info_received = 1; + generate_aocs_ie(call, l3m); + } + new_state(call, ISDN_STATE_IN_ALERTING); /* send message to ISDN */ @@ -2054,6 +2180,8 @@ void setup_rsp(call_t *call, uint32_t pid, osmo_cc_msg_t *msg) char connected[33]; char display[128]; int rc; + uint8_t fac_ie[256]; + struct asn1_parm fac; /* NT-MODE in setup state we must send PROCEEDING first */ if (!call->proceeding_sent && call->isdn_ep->ntmode) { @@ -2109,8 +2237,39 @@ void setup_rsp(call_t *call, uint32_t pid, osmo_cc_msg_t *msg) enc_ie_connected_pn(l3m, type, plan, 1, present, screen, connected); } + /* Metering handling and AOC-S generation */ + rc = osmo_cc_get_ie_metering(msg, 0, &(call->metering_connect_units), &(call->metering_unit_period_decisecs)); + if(rc >= 0) { + call->metering_info_received = 1; + generate_aocs_ie(call, l3m); + } + new_state(call, ISDN_STATE_IN_CONNECTING); + /* AOC-D handling on connect */ + if(call->isdn_ep->ntmode && call->isdn_ep->aocd && call->metering_info_received && call->metering_connect_units > 0) + { + LOGP(DISDN, LOGL_DEBUG, "Attaching AOC-D connect facility, units: %d\n", call->metering_connect_units); + call->metering_total_units = call->metering_connect_units; + + memset(&fac, 0, sizeof(fac)); + fac.Valid = 1; + fac.comp = CompInvoke; + fac.u.inv.invokeId = 2; /* doesn't matter since no response is expected */ + fac.u.inv.operationValue = Fac_AOCDChargingUnit; + + fac.u.inv.o.AOCchu.recordedUnits = call->metering_total_units; + encodeFac(fac_ie, &fac); + enc_ie_facility(l3m, fac_ie + 2, fac_ie[1]); + + if(call->metering_unit_period_decisecs > 0) { + LOGP(DISDN, LOGL_DEBUG, "Scheduling AOC-D unit information every %d deciseconds.\n", call->metering_unit_period_decisecs); + call->aocd_unit_timer_started = 1; + osmo_timer_setup(&call->aocd_unit_timer, aocd_timer_cb, call); + osmo_timer_schedule(&call->aocd_unit_timer, call->metering_unit_period_decisecs / 10, (call->metering_unit_period_decisecs % 10) * 100000); + } + } + /* send message to ISDN */ call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_CONNECT, call->l3_pid, l3m); @@ -2209,6 +2368,12 @@ void progress_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg) /* progress information */ rc = process_progress(call, msg, l3m, call->state, 0); + /* Metering handling and AOC-S generation */ + rc = osmo_cc_get_ie_metering(msg, 0, &(call->metering_connect_units), &(call->metering_unit_period_decisecs)); + if(rc >= 0) { + call->metering_info_received = 1; + generate_aocs_ie(call, l3m); + } /* send message to ISDN */ if (rc) call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_PROGRESS, call->l3_pid, l3m); @@ -2337,6 +2502,13 @@ void disc_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg) enc_ie_display(l3m, display); } + /* stop AOC-D timer */ + if(call->aocd_unit_timer_started) + { + osmo_timer_del(&call->aocd_unit_timer); + call->aocd_unit_timer_started = 0; + } + new_state(call, ISDN_STATE_OUT_DISCONNECT); /* send message to ISDN */ diff --git a/src/isdn/isdn.c b/src/isdn/isdn.c index 7be94e1..45646bf 100644 --- a/src/isdn/isdn.c +++ b/src/isdn/isdn.c @@ -690,7 +690,7 @@ void isdn_destroy(isdn_t *isdn_ep) static void clock_timeout(void *data); /* initialization and configuration to isdn interface instance */ -int isdn_initialize(isdn_t *isdn_ep, ph_socket_t *ph_socket, char law, const char *portname, int ntmode, int ptp, int layer1hold, int layer2hold, const char *channel_out, const char *channel_in, const char *timeouts, int tx_delay, int local_tones, int serving_location) +int isdn_initialize(isdn_t *isdn_ep, ph_socket_t *ph_socket, char law, const char *portname, int ntmode, int ptp, int layer1hold, int layer2hold, const char *channel_out, const char *channel_in, const char *timeouts, int tx_delay, int local_tones, int serving_location, int aocd, int aocs) { int rc; void *mui; @@ -726,6 +726,8 @@ int isdn_initialize(isdn_t *isdn_ep, ph_socket_t *ph_socket, char law, const cha isdn_ep->tx_delay = tx_delay; isdn_ep->local_tones = local_tones; isdn_ep->serving_location = serving_location; + isdn_ep->aocd = aocd; + isdn_ep->aocs = aocs; /* channel selection list */ if (channel_out) { @@ -850,6 +852,9 @@ void call_destroy(call_t *call) osmo_cc_free_session(call->cc_session); free((char *)call->sdp); + /* remove metering timer, if still active */ + osmo_timer_del(&call->aocd_unit_timer); + /* detach */ call_p = &call->isdn_ep->call_list; while (*call_p) { diff --git a/src/isdn/isdn.h b/src/isdn/isdn.h index 7f92298..801d0df 100644 --- a/src/isdn/isdn.h +++ b/src/isdn/isdn.h @@ -89,6 +89,9 @@ typedef struct isdn { const char *timeouts; int tx_delay; int local_tones; + /* metering/AOC-D/AOC-S */ + int aocd; + int aocs; /* osmo-cc */ struct osmo_cc_endpoint cc_ep; @@ -180,6 +183,13 @@ typedef struct call_list { int conference_3pty; /* if call is the active call in a 3pty conference */ int park_len; uint8_t park_callid[8]; + /* metering/AOC-D/AOC-S */ + struct osmo_timer_list aocd_unit_timer; + int aocd_unit_timer_started; + int metering_info_received; + uint16_t metering_connect_units; + uint16_t metering_unit_period_decisecs; + uint16_t metering_total_units; /* bridge states */ int can_bridge; /* last state sent to the server */ @@ -204,7 +214,7 @@ int open_bchannel_out(call_t *call, unsigned int cmd, int channel, int exclusive /* isdn instance */ isdn_t *isdn_create(void); void isdn_destroy(isdn_t *isdn_ep); -int isdn_initialize(isdn_t *isdn_ep, ph_socket_t *ph_socket, char law, const char *portname, int ntmode, int ptp, int layer1hold, int layer2hold, const char *channel_out, const char *channel_in, const char *timeouts, int tx_delay, int local_tones, int serving_location); +int isdn_initialize(isdn_t *isdn_ep, ph_socket_t *ph_socket, char law, const char *portname, int ntmode, int ptp, int layer1hold, int layer2hold, const char *channel_out, const char *channel_in, const char *timeouts, int tx_delay, int local_tones, int serving_location, int aocd, int aocs); int isdn_open(isdn_t *isdn_ep); void isdn_close(isdn_t *isdn_ep); void isdn_add_msn(isdn_t *isdn_ep, const char *msn); diff --git a/src/isdn/main.c b/src/isdn/main.c index ed9a59a..1e966cd 100644 --- a/src/isdn/main.c +++ b/src/isdn/main.c @@ -46,6 +46,8 @@ static int ntmode = 0; static int ptp = 0; static int layer1hold = 0; static int layer2hold = 0; +static int aocd = 0; +static int aocs = 0; static const char *channel_out = NULL; static const char *channel_in = NULL; static const char *timeouts = NULL; @@ -125,6 +127,10 @@ static void print_help() printf(" Give a delay in milliseconds. This is required for modem/fax. Audio\n"); printf(" toward ISDN interface is buffered with the given delay.\n"); printf(" This feature alters dejittering strategy.\n"); + printf(" --aocd\n"); + printf(" Send AOC-D charging information\n"); + printf(" --aocs\n"); + printf(" Send AOC-S charging information\n"); printf(" -T --local-tones german | oldgerman | american\n"); printf(" Send locally generated tones, if not provided by remote interface.\n"); printf(" -D --debug-misdn\n"); @@ -154,6 +160,8 @@ static void print_help() #define OPT_SERVING 265 #define OPT_PCM_SLOTS 266 #define OPT_BR_ONLY 267 +#define OPT_AOCD 268 +#define OPT_AOCS 269 static void add_options(void) { @@ -172,6 +180,8 @@ static void add_options(void) option_add(OPT_TIMEOUTS, "timeouts", 1); option_add(OPT_TX_DELAY, "tx-delay", 1); option_add('T', "local-tones", 1); + option_add(OPT_AOCD, "aocd", 0); + option_add(OPT_AOCS, "aocs", 0); option_add('D', "debug-misdn", 0); option_add(OPT_SERVING, "serving-location", 1); option_add('B', "bridging", 1); @@ -237,6 +247,12 @@ static int handle_options(int short_option, int argi, char **argv) case OPT_TX_DELAY: tx_delay = atoi(argv[argi]); break; + case OPT_AOCD: + aocd = 1; + break; + case OPT_AOCS: + aocs = 1; + break; case 'T': if (!strcasecmp(argv[argi], "american")) local_tones = TONES_TYPE_AMERICAN; @@ -376,7 +392,7 @@ int main(int argc, char *argv[]) isdn_tone_generate_ulaw_samples(); /* init instance */ - rc = isdn_initialize(isdn_ep, (misdn_user) ? &ph_drv.ph_socket : NULL, law, portname, ntmode, ptp, layer1hold, layer2hold, channel_out, channel_in, timeouts, tx_delay, local_tones, serving_location); + rc = isdn_initialize(isdn_ep, (misdn_user) ? &ph_drv.ph_socket : NULL, law, portname, ntmode, ptp, layer1hold, layer2hold, channel_out, channel_in, timeouts, tx_delay, local_tones, serving_location, aocd, aocs); if (rc) { LOGP(DISDN, LOGL_ERROR, "mISDN initializing failed!\n"); goto error; diff --git a/src/libmisdnuser/include/mISDN/suppserv.h b/src/libmisdnuser/include/mISDN/suppserv.h index ebf3794..d03bc91 100644 --- a/src/libmisdnuser/include/mISDN/suppserv.h +++ b/src/libmisdnuser/include/mISDN/suppserv.h @@ -309,6 +309,36 @@ extern "C" { __u32 billingId; struct ChargingAssociation chargeAssoc; }; + + struct FacAOCSDurationCurrency { + __u8 currency[10+1]; + __u16 currencyAmount; + __u8 multiplier; + __u8 typeOfCharging; + __u16 durLengthTimeUnit; + __u8 durLengthTimeScale; + __u8 granLengthTimeUnit; + __u8 granLengthTimeScale; + }; + + struct FacAOCSFlatRateCurrency { + __u8 currency[10+1]; + __u16 currencyAmount; + __u8 multiplier; + }; + + struct FacAOCSCurrencyInfo { + __u8 chargedItem; + __u8 currencyType; + struct FacAOCSDurationCurrency durationCurrency; + struct FacAOCSFlatRateCurrency FlatRateCurrency; + }; + + struct FacAOCSCurrencyInfoList { + __u8 currencyInfoCount; + struct FacAOCSCurrencyInfo currencyInfo[4]; + }; + struct Q931_BearerCapability { __u8 Length; @@ -1105,6 +1135,7 @@ extern "C" { union { struct FacAOCChargingUnit AOCchu; struct FacAOCCurrency AOCcur; + struct FacAOCSCurrencyInfoList AOCcuril; struct FacStatusRequest StatusRequest; diff --git a/src/libmisdnuser/suppserv/fac.c b/src/libmisdnuser/suppserv/fac.c index 9e682f4..dd55857 100644 --- a/src/libmisdnuser/suppserv/fac.c +++ b/src/libmisdnuser/suppserv/fac.c @@ -191,6 +191,185 @@ __u8 *encodeComponentInvoke_Head_Long_u8(__u8 * Dest, int InvokeID, enum Operati return p; } /* end encodeComponentInvoke_Head_Long_u8() */ +static int encodeAOCSChargingUnitOperation(__u8 * dest, const struct asn1_parm *pc, const struct FacAOCSCurrencyInfoList *currinfolist) +{ + /* Manually encoded ASN.1 */ + int i = 0, fac_len_index, supp_len_index, cil_len_index, ci, ci_len_index, ci_len, c_len_index, c_len, cval_len; + int result = -1; + + __u8 *p = dest; + + if ((p != NULL)) { + p[i++] = IE_FACILITY; // IE identifier + fac_len_index = i; + p[i++] = 0x00; // length -- not known yet + p[i++] = SUPPLEMENTARY_SERVICE; // remote operations protocol + p[i++] = 0xa1; // invoke component + supp_len_index = i; + p[i++] = 0x00; // length -- not known yet + p[i++] = 0x02; // Invoke ID + p[i++] = 0x01; // InvokeId Length + p[i++] = pc->u.inv.invokeId; + p[i++] = 0x02; // Operation Tag + p[i++] = 0x01; // Tag Length + p[i++] = Fac_AOCSCurrency; // Operation Value 31 AOCS Currency + p[i++] = 0x30; // AOCS Currency Info List + cil_len_index = i; + p[i++] = 0x00; // Length -- not known yet + + for(ci = 0; ci < currinfolist->currencyInfoCount; ci++) { + /* iterate through available currencyInfos within currencyInfoList */ + ci_len = 0; // CurrencyInfoLength + + p[i++] = 0x30; // APDU AOCS Currency Info + ci_len_index = i; + p[i++] = 0x00; // Length -- not known yet + p[i++] = 0x0A; // ChargedItem + ci_len++; + p[i++] = 0x01; // Length + ci_len++; + p[i++] = currinfolist->currencyInfo[ci].chargedItem; + ci_len++; + p[i++] = currinfolist->currencyInfo[ci].currencyType; + ci_len++; + if(currinfolist->currencyInfo[ci].currencyType == 0xA1) { // DurationCurrency + c_len = 0; // CurrencyLength + c_len_index = i; + p[i++] = 0x00; // Length -- not known yet + ci_len++; + p[i++] = 0x81; // CurrencySpec + ci_len++; c_len++; + cval_len = strlen((char *)currinfolist->currencyInfo[ci].durationCurrency.currency); + if(cval_len > 10) + cval_len = 10; + p[i++] = cval_len; + ci_len++; c_len++; + memcpy(p + i, currinfolist->currencyInfo[ci].durationCurrency.currency, cval_len); + i += cval_len; ci_len += cval_len; c_len += cval_len; + p[i++] = 0xA2; // dAmount + ci_len++; c_len++; + p[i++] = 0x06; // Length + ci_len++; c_len++; + p[i++] = 0x81; // CurrencyAmount + ci_len++; c_len++; + p[i++] = 0x01; // Length + ci_len++; c_len++; + p[i++] = currinfolist->currencyInfo[ci].durationCurrency.currencyAmount; + ci_len++; c_len++; + p[i++] = 0x82; // Multiplier + ci_len++; c_len++; + p[i++] = 0x01; // Length + ci_len++; c_len++; + p[i++] = currinfolist->currencyInfo[ci].durationCurrency.multiplier; + ci_len++; c_len++; + p[i++] = 0x83; // ChargeType + ci_len++; c_len++; + p[i++] = 0x01; // Length + ci_len++; c_len++; + p[i++] = currinfolist->currencyInfo[ci].durationCurrency.typeOfCharging; + ci_len++; c_len++; + p[i++] = 0xA4; // dTime + ci_len++; c_len++; + p[i++] = 0x07; // Length + ci_len++; c_len++; + p[i++] = 0x81; // durationLengthOfTimeUnit + ci_len++; c_len++; + if(currinfolist->currencyInfo[ci].durationCurrency.durLengthTimeUnit > 0xff) { + p[i++] = 0x02; // Length + ci_len++; c_len++; + p[i++] = ((currinfolist->currencyInfo[ci].durationCurrency.durLengthTimeUnit) >> 8) & 0xff; + ci_len++; c_len++; + } + else { + p[i++] = 0x01; // Length + ci_len++; c_len++; + } + p[i++] = ((currinfolist->currencyInfo[ci].durationCurrency.durLengthTimeUnit) >> 0) & 0xff; + ci_len++; c_len++; + p[i++] = 0x82; // durationScaleOfTimeUnit + ci_len++; c_len++; + p[i++] = 0x01; // Length + ci_len++; c_len++; + p[i++] = currinfolist->currencyInfo[ci].durationCurrency.durLengthTimeScale; + ci_len++; c_len++; + p[i++] = 0xA5; // dGranularity + ci_len++; c_len++; + p[i++] = 0x06; // Length + ci_len++; c_len++; + p[i++] = 0x81; // granuLengthOfTimeUnit + ci_len++; c_len++; + p[i++] = 0x01; // Length + ci_len++; c_len++; + p[i++] = currinfolist->currencyInfo[ci].durationCurrency.granLengthTimeUnit; + ci_len++; c_len++; + p[i++] = 0x82; // granuScaleOfTimeUnit + ci_len++; c_len++; + p[i++] = 0x01; // Length + ci_len++; c_len++; + p[i++] = currinfolist->currencyInfo[ci].durationCurrency.granLengthTimeScale; + ci_len++; c_len++; + p[c_len_index] = c_len; + } + else if(currinfolist->currencyInfo[ci].currencyType == 0xA2) { // FlatRateCurrency + c_len = 0; // CurrencyLength + c_len_index = i; + p[i++] = 0x00; // Length -- not known yet + ci_len++; + p[i++] = 0x81; // CurrencySpec + ci_len++; c_len++; + cval_len = strlen((char *)currinfolist->currencyInfo[ci].FlatRateCurrency.currency); + if(cval_len > 10) + cval_len = 10; + p[i++] = cval_len; + ci_len++; c_len++; + memcpy(p + i, currinfolist->currencyInfo[ci].FlatRateCurrency.currency, cval_len); + i += cval_len; ci_len += cval_len; c_len += cval_len; + p[i++] = 0xA2; // dAmount + ci_len++; c_len++; + p[i++] = 0x06; // Length + ci_len++; c_len++; + p[i++] = 0x81; // CurrencyAmount + ci_len++; c_len++; + if(currinfolist->currencyInfo[ci].FlatRateCurrency.currencyAmount > 0xff) { + p[i++] = 0x02; // Length + ci_len++; c_len++; + p[i++] = ((currinfolist->currencyInfo[ci].FlatRateCurrency.currencyAmount) >> 8) & 0xff; + ci_len++; c_len++; + } + else { + p[i++] = 0x01; // Length + ci_len++; c_len++; + } + p[i++] = ((currinfolist->currencyInfo[ci].FlatRateCurrency.currencyAmount) >> 0) & 0xff; + ci_len++; c_len++; + p[i++] = 0x82; // Multiplier + ci_len++; c_len++; + p[i++] = 0x01; // Length + ci_len++; c_len++; + p[i++] = currinfolist->currencyInfo[ci].FlatRateCurrency.multiplier; + ci_len++; c_len++; + p[c_len_index] = c_len; + } + else if(currinfolist->currencyInfo[ci].currencyType == 0x84) { // FreeOfCharge + p[i++] = 0x00; + ci_len++; + } + else { + result = 0; + return(result); + } + p[ci_len_index] = ci_len; + } + + p[fac_len_index] = i - 2; + p[supp_len_index] = p[fac_len_index] - 3; + p[cil_len_index] = p[supp_len_index] - 8; + + result = p[fac_len_index] + 2; // Total Length of IE + } + return result; +} + static int encodeAOCDChargingUnitOperation(__u8 * dest, const struct asn1_parm *pc, int numberOfUnits) { /* Manually encoded ASN.1 */ @@ -567,7 +746,10 @@ static int encodeFacInvoke(__u8 * dest, const struct asn1_parm *pc) /* AOC support */ case Fac_ChargingRequest: + break; case Fac_AOCSCurrency: + len = encodeAOCSChargingUnitOperation(dest, pc, &inv->o.AOCcuril); + break; case Fac_AOCSSpecialArr: case Fac_AOCDCurrency: case Fac_AOCECurrency: From 1e83fdfaad57f28714cf4d3ae7bb2db949ec1df9 Mon Sep 17 00:00:00 2001 From: Dennis Grunert Date: Wed, 10 Jan 2024 12:25:57 +0100 Subject: [PATCH 4/9] Changed AOC-D encoding value of TypeOfChargingInfo from Total to SubTotal encodeAOCDChargingUnitOperation() set the value of TypeOfChargingInfo to Total, which results in ISDN phones not correctly displaying increasing units. Setting it to SubTotal fixed the issue. --- src/libmisdnuser/suppserv/fac.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libmisdnuser/suppserv/fac.c b/src/libmisdnuser/suppserv/fac.c index dd55857..43c588a 100644 --- a/src/libmisdnuser/suppserv/fac.c +++ b/src/libmisdnuser/suppserv/fac.c @@ -406,7 +406,7 @@ static int encodeAOCDChargingUnitOperation(__u8 * dest, const struct asn1_parm * p[i++] = 0x30; p[i++] = (0x02 + len); p[i++] = 0x02; // Operation Tag - p[i++] = 0x01; // AOC-D so Sub-Total + p[i++] = 0x01; // Recorded units could take up as much as 3 bytes (0xFFFFFF) p[i] = numberOfUnits & 0xFF; @@ -416,9 +416,9 @@ static int encodeAOCDChargingUnitOperation(__u8 * dest, const struct asn1_parm * p[i+2] = (numberOfUnits >> 16) & 0xFF; i += len; - p[i++] = 0x82; - p[i++] = 0x01; + p[i++] = 0x82; // Type of charging info p[i++] = 0x01; + p[i++] = 0x00; // AOC-D so Sub-Total p[1] = (AOCD_CHARGE_UNIT_IE_LENGTH + len); // IE Payload Length p[4] = p[1] - 3; // Invoke Component Length From 3779fd30346734e0a26ee192ec7297c68ef48a62 Mon Sep 17 00:00:00 2001 From: Dennis Grunert Date: Wed, 10 Jan 2024 17:57:50 +0100 Subject: [PATCH 5/9] Handling of unknown facility indications from terminals --- src/isdn/dss1.c | 131 +++++++++++++++++++++++++----------------------- 1 file changed, 67 insertions(+), 64 deletions(-) diff --git a/src/isdn/dss1.c b/src/isdn/dss1.c index 1272d4c..491e963 100644 --- a/src/isdn/dss1.c +++ b/src/isdn/dss1.c @@ -1323,80 +1323,83 @@ void facility_ind(call_t *call, uint32_t pid, struct l3_msg *l3m) set_3pty = 0; break; default: - ; + LOGP(DDSS1, LOGL_DEBUG, "Facility Operation=%x of Component=%x not implemented\n", fac.u.inv.operationValue, fac.comp); + break; } break; default: - ; + LOGP(DDSS1, LOGL_DEBUG, "Facility Operation=%x of Component=%x not implemented\n", fac.u.inv.operationValue, fac.comp); + break; } - /* find other terminal on hold */ - other = call->isdn_ep->call_list; - while (other) { -// printf("check: call=%p other=%p call_ces=%x other_ces=%x other_hold=%d\n", call, other, call->l3_ces, other->l3_ces, other->hold); - if (other != call - && other->l3_ces == call->l3_ces) { - /* if we got facility on active call */ - if (other->hold && !call->hold) - break; - /* if we got facility on active call */ - if (!other->hold && call->hold) - break; + if(set_3pty >= 0) { + /* find other terminal on hold */ + other = call->isdn_ep->call_list; + while (other) { + // printf("check: call=%p other=%p call_ces=%x other_ces=%x other_hold=%d\n", call, other, call->l3_ces, other->l3_ces, other->hold); + if (other != call + && other->l3_ces == call->l3_ces) { + /* if we got facility on active call */ + if (other->hold && !call->hold) + break; + /* if we got facility on active call */ + if (!other->hold && call->hold) + break; + } + other = other->next; + } + if (other) { + other->conference_3pty = call->conference_3pty = set_3pty; + /* process local briding capability */ + bridge_socket_client_update(call, 0); + bridge_socket_client_update(other, 0); + jitter_reset(&call->conf_dejitter); + jitter_reset(&call->tx_dejitter); + jitter_reset(&other->conf_dejitter); + jitter_reset(&other->tx_dejitter); + } else { + LOGP(DDSS1, LOGL_NOTICE, "Phone requests conference, but no call on hold!\n"); + notify = 0; } - other = other->next; - } - if (set_3pty >= 0 && other) { - other->conference_3pty = call->conference_3pty = set_3pty; - /* process local briding capability */ - bridge_socket_client_update(call, 0); - bridge_socket_client_update(other, 0); - jitter_reset(&call->conf_dejitter); - jitter_reset(&call->tx_dejitter); - jitter_reset(&other->conf_dejitter); - jitter_reset(&other->tx_dejitter); - } else { - LOGP(DDSS1, LOGL_NOTICE, "Phone requests conference, but no call on hold!\n"); - notify = 0; - } - /* encode 3PTY facility */ - memset(&fac, 0, sizeof(fac)); - fac.Valid = 1; - if (notify) { - fac.comp = CompReturnResult; - fac.u.retResult.invokeId = invokeid; - fac.u.retResult.operationValuePresent = 1; - if (notify == OSMO_CC_NOTIFY_CONFERENCE_ESTABLISHED) - fac.u.retResult.operationValue = Fac_Begin3PTY; - if (notify == OSMO_CC_NOTIFY_CONFERENCE_DISCONNECTED) - fac.u.retResult.operationValue = Fac_End3PTY; - } else { - fac.comp = CompReturnError; - fac.u.retError.invokeId = invokeid; - fac.u.retError.errorValue = FacError_Gen_InvalidCallState; - } - encodeFac(fac_ie, &fac); + /* encode 3PTY facility */ + memset(&fac, 0, sizeof(fac)); + fac.Valid = 1; + if (notify) { + fac.comp = CompReturnResult; + fac.u.retResult.invokeId = invokeid; + fac.u.retResult.operationValuePresent = 1; + if (notify == OSMO_CC_NOTIFY_CONFERENCE_ESTABLISHED) + fac.u.retResult.operationValue = Fac_Begin3PTY; + if (notify == OSMO_CC_NOTIFY_CONFERENCE_DISCONNECTED) + fac.u.retResult.operationValue = Fac_End3PTY; + } else { + fac.comp = CompReturnError; + fac.u.retError.invokeId = invokeid; + fac.u.retError.errorValue = FacError_Gen_InvalidCallState; + } + encodeFac(fac_ie, &fac); + /* sending facility */ + l3m = create_l3msg(); + enc_ie_facility(l3m, fac_ie + 2, fac_ie[1]); + call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_FACILITY, call->l3_pid, l3m); - /* sending facility */ - l3m = create_l3msg(); - enc_ie_facility(l3m, fac_ie + 2, fac_ie[1]); - call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_FACILITY, call->l3_pid, l3m); + if (notify) { + /* create osmo-cc message */ + msg = osmo_cc_new_msg(OSMO_CC_MSG_NOTIFY_IND); + /* notify the facility */ + osmo_cc_add_ie_notify(msg, notify); + /* send message to osmo-cc */ + osmo_cc_ll_msg(&call->isdn_ep->cc_ep, call->cc_callref, msg); - if (notify) { - /* create osmo-cc message */ - msg = osmo_cc_new_msg(OSMO_CC_MSG_NOTIFY_IND); - /* notify the facility */ - osmo_cc_add_ie_notify(msg, notify); - /* send message to osmo-cc */ - osmo_cc_ll_msg(&call->isdn_ep->cc_ep, call->cc_callref, msg); - - /* create osmo-cc message */ - msg = osmo_cc_new_msg(OSMO_CC_MSG_NOTIFY_IND); - /* notify the facility */ - osmo_cc_add_ie_notify(msg, notify); - /* send message to osmo-cc */ - osmo_cc_ll_msg(&other->isdn_ep->cc_ep, call->cc_callref, msg); + /* create osmo-cc message */ + msg = osmo_cc_new_msg(OSMO_CC_MSG_NOTIFY_IND); + /* notify the facility */ + osmo_cc_add_ie_notify(msg, notify); + /* send message to osmo-cc */ + osmo_cc_ll_msg(&other->isdn_ep->cc_ep, call->cc_callref, msg); + } } } From cd7f1f8590de1d6b0c251aa354cce831513401f3 Mon Sep 17 00:00:00 2001 From: Dennis Grunert Date: Wed, 10 Jan 2024 18:13:14 +0100 Subject: [PATCH 6/9] AOC information as separate facility messages for compatibility (CONNECT-attached AOC-D IE ignored by NT1plus) --- src/isdn/dss1.c | 70 ++++++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/src/isdn/dss1.c b/src/isdn/dss1.c index 491e963..3f4a812 100644 --- a/src/isdn/dss1.c +++ b/src/isdn/dss1.c @@ -186,8 +186,9 @@ static void split_3pty(call_t *call) /* Generate AOC-S facility IE from metering information */ #define AOCS_CURRENCY_AMOUNT_PER_UNIT 5 -static void generate_aocs_ie(call_t *call, struct l3_msg *l3m) +static void generate_aocs_fac(call_t *call) { + struct l3_msg *l3m; uint8_t fac_ie[256]; struct asn1_parm fac; @@ -198,7 +199,7 @@ static void generate_aocs_ie(call_t *call, struct l3_msg *l3m) fac.u.inv.invokeId = 2; /* doesn't matter since no response is expected */ fac.u.inv.operationValue = Fac_AOCSCurrency; - LOGP(DISDN, LOGL_DEBUG, "Sending AOC-S information from metering data: connect_units=%d unit_period_decisecs=%d\n", call->metering_connect_units, call->metering_unit_period_decisecs); + LOGP(DISDN, LOGL_DEBUG, "Sending AOC-S facility from metering data: connect_units=%d unit_period_decisecs=%d\n", call->metering_connect_units, call->metering_unit_period_decisecs); if(call->metering_connect_units == 0) { // Free call LOGP(DISDN, LOGL_DEBUG, "AOC-S currencyInfoList: BasicComm FreeOfCharge\n"); @@ -252,7 +253,11 @@ static void generate_aocs_ie(call_t *call, struct l3_msg *l3m) } encodeFac(fac_ie, &fac); + + // sending facility + l3m = create_l3msg(); enc_ie_facility(l3m, fac_ie + 2, fac_ie[1]); + call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_FACILITY, call->l3_pid, l3m); } } @@ -266,7 +271,7 @@ static void aocd_timer_cb(void *data) call->metering_total_units++; - LOGP(DISDN, LOGL_DEBUG, "Sending next AOC-D unit information, total_units=%d\n", call->metering_total_units); + LOGP(DISDN, LOGL_DEBUG, "Sending next AOC-D facility, total_units=%d\n", call->metering_total_units); osmo_timer_schedule(&call->aocd_unit_timer, call->metering_unit_period_decisecs / 10, (call->metering_unit_period_decisecs % 10) * 100000); @@ -2096,18 +2101,18 @@ void proc_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg, int with_ies) if (rc >= 0 && call->isdn_ep->ntmode) enc_ie_redirection(l3m, type, plan, 1, present, redir); - /* Metering handling and AOC-S generation */ - rc = osmo_cc_get_ie_metering(msg, 0, &(call->metering_connect_units), &(call->metering_unit_period_decisecs)); - if(rc >= 0) { - call->metering_info_received = 1; - generate_aocs_ie(call, l3m); - } - skip_ies: new_state(call, ISDN_STATE_IN_PROCEEDING); /* send message to ISDN */ call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_CALL_PROCEEDING, call->l3_pid, l3m); + + /* Metering handling and AOC-S generation */ + rc = osmo_cc_get_ie_metering(msg, 0, &(call->metering_connect_units), &(call->metering_unit_period_decisecs)); + if(rc >= 0) { + call->metering_info_received = 1; + generate_aocs_fac(call); + } } /* CC-ALERTING REQUEST */ @@ -2160,17 +2165,17 @@ void alert_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg) if (rc >= 0 && call->isdn_ep->ntmode) enc_ie_redirection(l3m, type, plan, 1, present, redir); - /* Metering handling and AOC-S generation */ - rc = osmo_cc_get_ie_metering(msg, 0, &(call->metering_connect_units), &(call->metering_unit_period_decisecs)); - if(rc >= 0) { - call->metering_info_received = 1; - generate_aocs_ie(call, l3m); - } - new_state(call, ISDN_STATE_IN_ALERTING); /* send message to ISDN */ call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_ALERTING, call->l3_pid, l3m); + + /* Metering handling and AOC-S generation */ + rc = osmo_cc_get_ie_metering(msg, 0, &(call->metering_connect_units), &(call->metering_unit_period_decisecs)); + if(rc >= 0) { + call->metering_info_received = 1; + generate_aocs_fac(call); + } } /* CC-CONNECT REQUEST */ @@ -2240,19 +2245,22 @@ void setup_rsp(call_t *call, uint32_t pid, osmo_cc_msg_t *msg) enc_ie_connected_pn(l3m, type, plan, 1, present, screen, connected); } + new_state(call, ISDN_STATE_IN_CONNECTING); + + /* send message to ISDN */ + call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_CONNECT, call->l3_pid, l3m); + /* Metering handling and AOC-S generation */ rc = osmo_cc_get_ie_metering(msg, 0, &(call->metering_connect_units), &(call->metering_unit_period_decisecs)); if(rc >= 0) { call->metering_info_received = 1; - generate_aocs_ie(call, l3m); + generate_aocs_fac(call); } - new_state(call, ISDN_STATE_IN_CONNECTING); - /* AOC-D handling on connect */ if(call->isdn_ep->ntmode && call->isdn_ep->aocd && call->metering_info_received && call->metering_connect_units > 0) { - LOGP(DISDN, LOGL_DEBUG, "Attaching AOC-D connect facility, units: %d\n", call->metering_connect_units); + LOGP(DISDN, LOGL_DEBUG, "Sending first AOC-D facility, units: %d\n", call->metering_connect_units); call->metering_total_units = call->metering_connect_units; memset(&fac, 0, sizeof(fac)); @@ -2263,7 +2271,11 @@ void setup_rsp(call_t *call, uint32_t pid, osmo_cc_msg_t *msg) fac.u.inv.o.AOCchu.recordedUnits = call->metering_total_units; encodeFac(fac_ie, &fac); + + // sending facility + l3m = create_l3msg(); enc_ie_facility(l3m, fac_ie + 2, fac_ie[1]); + call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_FACILITY, call->l3_pid, l3m); if(call->metering_unit_period_decisecs > 0) { LOGP(DISDN, LOGL_DEBUG, "Scheduling AOC-D unit information every %d deciseconds.\n", call->metering_unit_period_decisecs); @@ -2273,9 +2285,6 @@ void setup_rsp(call_t *call, uint32_t pid, osmo_cc_msg_t *msg) } } - /* send message to ISDN */ - call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_CONNECT, call->l3_pid, l3m); - /* in NT mode we might not receive CONNECT ACKNOWLEDGE */ if (call->isdn_ep->ntmode) { new_state(call, ISDN_STATE_CONNECT); @@ -2371,17 +2380,18 @@ void progress_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg) /* progress information */ rc = process_progress(call, msg, l3m, call->state, 0); - /* Metering handling and AOC-S generation */ - rc = osmo_cc_get_ie_metering(msg, 0, &(call->metering_connect_units), &(call->metering_unit_period_decisecs)); - if(rc >= 0) { - call->metering_info_received = 1; - generate_aocs_ie(call, l3m); - } /* send message to ISDN */ if (rc) call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_PROGRESS, call->l3_pid, l3m); else free_l3msg(l3m); + + /* Metering handling and AOC-S generation */ + rc = osmo_cc_get_ie_metering(msg, 0, &(call->metering_connect_units), &(call->metering_unit_period_decisecs)); + if(rc >= 0) { + call->metering_info_received = 1; + generate_aocs_fac(call); + } } /* CC-NOTIFY REQUEST */ From dfa07323c304e29bc0fdca842c7e51f0c66bd9fc Mon Sep 17 00:00:00 2001 From: Dennis Grunert Date: Wed, 10 Jan 2024 20:27:10 +0100 Subject: [PATCH 7/9] AOC-S time scale adjusted --- src/isdn/dss1.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/isdn/dss1.c b/src/isdn/dss1.c index 3f4a812..d682d61 100644 --- a/src/isdn/dss1.c +++ b/src/isdn/dss1.c @@ -226,10 +226,10 @@ static void generate_aocs_fac(call_t *call) fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.currencyAmount = AOCS_CURRENCY_AMOUNT_PER_UNIT; fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.multiplier = 1; // 1/100 EUR fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.typeOfCharging = 0x00; // Contin. Charging - fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.durLengthTimeUnit = call->metering_unit_period_decisecs * 10; // Unit duration - fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.durLengthTimeScale = 0x00; // 1/100 s - fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.granLengthTimeUnit = 1; // Granularity 1 - fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.granLengthTimeScale = 2; // 1/1 s + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.durLengthTimeUnit = call->metering_unit_period_decisecs; // Unit duration + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.durLengthTimeScale = 1; // 1/10 s + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.granLengthTimeUnit = call->metering_unit_period_decisecs; // Granularity + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.granLengthTimeScale = 1; // 1/10 s } else { // Special call with setup/connect FlatRate /* note some payphones (e.g. BluePhone) only interpret 'basic comm' charged item */ @@ -241,10 +241,10 @@ static void generate_aocs_fac(call_t *call) fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.currencyAmount = AOCS_CURRENCY_AMOUNT_PER_UNIT; fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.multiplier = 1; // 1/100 EUR fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.typeOfCharging = 0x00; // Contin. Charging - fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.durLengthTimeUnit = call->metering_unit_period_decisecs * 10; // Unit duration - fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.durLengthTimeScale = 0x00; // 1/100 s - fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.granLengthTimeUnit = 1; // Granularity 1 - fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.granLengthTimeScale = 2; // 1/1 s + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.durLengthTimeUnit = call->metering_unit_period_decisecs; // Unit duration + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.durLengthTimeScale = 1; // 1/10 s + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.granLengthTimeUnit = call->metering_unit_period_decisecs; // Granularity + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.granLengthTimeScale = 1; // 1/10 s fac.u.inv.o.AOCcuril.currencyInfo[1].chargedItem = 0x02; // call setup fac.u.inv.o.AOCcuril.currencyInfo[1].currencyType = 0xA2; // FlatRate strncpy((char *)fac.u.inv.o.AOCcuril.currencyInfo[1].FlatRateCurrency.currency, "EUR", 10); // Currency value From a390e93d9a220e36a8e2cea21b13eb8dcfc23f0c Mon Sep 17 00:00:00 2001 From: Dennis Grunert Date: Thu, 11 Jan 2024 02:27:02 +0100 Subject: [PATCH 8/9] AOC-S: Use variable time unit length (1...3 Bytes). Fixes wrong time calculation on Clubtelefon 5 ISDN --- src/isdn/dss1.c | 43 ++++++++++------------- src/libmisdnuser/include/mISDN/suppserv.h | 4 +-- src/libmisdnuser/suppserv/fac.c | 32 ++++++++++++++--- 3 files changed, 48 insertions(+), 31 deletions(-) diff --git a/src/isdn/dss1.c b/src/isdn/dss1.c index d682d61..f05bd1e 100644 --- a/src/isdn/dss1.c +++ b/src/isdn/dss1.c @@ -202,36 +202,29 @@ static void generate_aocs_fac(call_t *call) LOGP(DISDN, LOGL_DEBUG, "Sending AOC-S facility from metering data: connect_units=%d unit_period_decisecs=%d\n", call->metering_connect_units, call->metering_unit_period_decisecs); if(call->metering_connect_units == 0) { // Free call - LOGP(DISDN, LOGL_DEBUG, "AOC-S currencyInfoList: BasicComm FreeOfCharge\n"); - fac.u.inv.o.AOCcuril.currencyInfoCount = 1; + LOGP(DISDN, LOGL_DEBUG, "AOC-S currencyInfoList: BasicComm FreeOfCharge / CallSetup FreeOfCharge\n"); + fac.u.inv.o.AOCcuril.currencyInfoCount = 2; fac.u.inv.o.AOCcuril.currencyInfo[0].chargedItem = 0x00; // basic comm fac.u.inv.o.AOCcuril.currencyInfo[0].currencyType = 0x84; // free + fac.u.inv.o.AOCcuril.currencyInfo[1].chargedItem = 0x02; // call setup + fac.u.inv.o.AOCcuril.currencyInfo[1].currencyType = 0x84; // free } - else if(call->metering_unit_period_decisecs == 0) { // setup/connect FlatRate + else if(call->metering_unit_period_decisecs == 0) { // CallSetup-only FlatRate /* note some payphones (e.g. BluePhone) only interpret 'basic comm' charged item, therefore we don't use 'call setup' charged item */ - LOGP(DISDN, LOGL_DEBUG, "AOC-S currencyInfoList: BasicComm FlatRate\n"); - fac.u.inv.o.AOCcuril.currencyInfoCount = 1; + LOGP(DISDN, LOGL_DEBUG, "AOC-S currencyInfoList: BasicComm FlatRate / CallSetup FlatRate\n"); + fac.u.inv.o.AOCcuril.currencyInfoCount = 2; fac.u.inv.o.AOCcuril.currencyInfo[0].chargedItem = 0x00; // basic comm fac.u.inv.o.AOCcuril.currencyInfo[0].currencyType = 0xA2; // FlatRate strncpy((char *)fac.u.inv.o.AOCcuril.currencyInfo[0].FlatRateCurrency.currency, "EUR", 10); // Currency value fac.u.inv.o.AOCcuril.currencyInfo[0].FlatRateCurrency.currencyAmount = AOCS_CURRENCY_AMOUNT_PER_UNIT * call->metering_connect_units; fac.u.inv.o.AOCcuril.currencyInfo[0].FlatRateCurrency.multiplier = 1; // 1/100 EUR + fac.u.inv.o.AOCcuril.currencyInfo[1].chargedItem = 0x02; // call setup + fac.u.inv.o.AOCcuril.currencyInfo[1].currencyType = 0xA2; // FlatRate + strncpy((char *)fac.u.inv.o.AOCcuril.currencyInfo[0].FlatRateCurrency.currency, "EUR", 10); // Currency value + fac.u.inv.o.AOCcuril.currencyInfo[1].FlatRateCurrency.currencyAmount = AOCS_CURRENCY_AMOUNT_PER_UNIT * call->metering_connect_units; + fac.u.inv.o.AOCcuril.currencyInfo[1].FlatRateCurrency.multiplier = 1; // 1/100 EUR } - else if(call->metering_connect_units == 1) { // Normal call - LOGP(DISDN, LOGL_DEBUG, "AOC-S currencyInfoList: BasicComm DurationCurrency\n"); - fac.u.inv.o.AOCcuril.currencyInfoCount = 1; - fac.u.inv.o.AOCcuril.currencyInfo[0].chargedItem = 0x00; // basic comm - fac.u.inv.o.AOCcuril.currencyInfo[0].currencyType = 0xA1; // DurationCurrency - strncpy((char *)fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.currency, "EUR", 10); // Currency value - fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.currencyAmount = AOCS_CURRENCY_AMOUNT_PER_UNIT; - fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.multiplier = 1; // 1/100 EUR - fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.typeOfCharging = 0x00; // Contin. Charging - fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.durLengthTimeUnit = call->metering_unit_period_decisecs; // Unit duration - fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.durLengthTimeScale = 1; // 1/10 s - fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.granLengthTimeUnit = call->metering_unit_period_decisecs; // Granularity - fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.granLengthTimeScale = 1; // 1/10 s - } - else { // Special call with setup/connect FlatRate + else { // Normal call /* note some payphones (e.g. BluePhone) only interpret 'basic comm' charged item */ LOGP(DISDN, LOGL_DEBUG, "AOC-S currencyInfoList: BasicComm DurationCurrency / CallSetup FlatRate\n"); fac.u.inv.o.AOCcuril.currencyInfoCount = 2; @@ -239,12 +232,12 @@ static void generate_aocs_fac(call_t *call) fac.u.inv.o.AOCcuril.currencyInfo[0].currencyType = 0xA1; // DurationCurrency strncpy((char *)fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.currency, "EUR", 10); // Currency value fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.currencyAmount = AOCS_CURRENCY_AMOUNT_PER_UNIT; - fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.multiplier = 1; // 1/100 EUR + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.multiplier = 1; // 1/100 EUR fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.typeOfCharging = 0x00; // Contin. Charging - fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.durLengthTimeUnit = call->metering_unit_period_decisecs; // Unit duration - fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.durLengthTimeScale = 1; // 1/10 s - fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.granLengthTimeUnit = call->metering_unit_period_decisecs; // Granularity - fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.granLengthTimeScale = 1; // 1/10 s + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.durLengthTimeUnit = call->metering_unit_period_decisecs * 10; // Unit duration + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.durLengthTimeScale = 0; // 1/100 s + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.granLengthTimeUnit = call->metering_unit_period_decisecs * 10; // Granularity + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.granLengthTimeScale = 0; // 1/100 s fac.u.inv.o.AOCcuril.currencyInfo[1].chargedItem = 0x02; // call setup fac.u.inv.o.AOCcuril.currencyInfo[1].currencyType = 0xA2; // FlatRate strncpy((char *)fac.u.inv.o.AOCcuril.currencyInfo[1].FlatRateCurrency.currency, "EUR", 10); // Currency value diff --git a/src/libmisdnuser/include/mISDN/suppserv.h b/src/libmisdnuser/include/mISDN/suppserv.h index d03bc91..a4a5cc5 100644 --- a/src/libmisdnuser/include/mISDN/suppserv.h +++ b/src/libmisdnuser/include/mISDN/suppserv.h @@ -315,9 +315,9 @@ extern "C" { __u16 currencyAmount; __u8 multiplier; __u8 typeOfCharging; - __u16 durLengthTimeUnit; + __u32 durLengthTimeUnit; __u8 durLengthTimeScale; - __u8 granLengthTimeUnit; + __u32 granLengthTimeUnit; __u8 granLengthTimeScale; }; diff --git a/src/libmisdnuser/suppserv/fac.c b/src/libmisdnuser/suppserv/fac.c index 43c588a..6e3cd90 100644 --- a/src/libmisdnuser/suppserv/fac.c +++ b/src/libmisdnuser/suppserv/fac.c @@ -274,7 +274,15 @@ static int encodeAOCSChargingUnitOperation(__u8 * dest, const struct asn1_parm * ci_len++; c_len++; p[i++] = 0x81; // durationLengthOfTimeUnit ci_len++; c_len++; - if(currinfolist->currencyInfo[ci].durationCurrency.durLengthTimeUnit > 0xff) { + if(currinfolist->currencyInfo[ci].durationCurrency.durLengthTimeUnit > 32767) { + p[i++] = 0x03; // Length + ci_len++; c_len++; + p[i++] = ((currinfolist->currencyInfo[ci].durationCurrency.durLengthTimeUnit) >> 16) & 0xff; + ci_len++; c_len++; + p[i++] = ((currinfolist->currencyInfo[ci].durationCurrency.durLengthTimeUnit) >> 8) & 0xff; + ci_len++; c_len++; + } + else if(currinfolist->currencyInfo[ci].durationCurrency.durLengthTimeUnit > 127) { p[i++] = 0x02; // Length ci_len++; c_len++; p[i++] = ((currinfolist->currencyInfo[ci].durationCurrency.durLengthTimeUnit) >> 8) & 0xff; @@ -298,9 +306,25 @@ static int encodeAOCSChargingUnitOperation(__u8 * dest, const struct asn1_parm * ci_len++; c_len++; p[i++] = 0x81; // granuLengthOfTimeUnit ci_len++; c_len++; - p[i++] = 0x01; // Length - ci_len++; c_len++; - p[i++] = currinfolist->currencyInfo[ci].durationCurrency.granLengthTimeUnit; + if(currinfolist->currencyInfo[ci].durationCurrency.granLengthTimeUnit > 32767) { + p[i++] = 0x03; // Length + ci_len++; c_len++; + p[i++] = ((currinfolist->currencyInfo[ci].durationCurrency.granLengthTimeUnit) >> 16) & 0xff; + ci_len++; c_len++; + p[i++] = ((currinfolist->currencyInfo[ci].durationCurrency.granLengthTimeUnit) >> 8) & 0xff; + ci_len++; c_len++; + } + else if(currinfolist->currencyInfo[ci].durationCurrency.granLengthTimeUnit > 127) { + p[i++] = 0x02; // Length + ci_len++; c_len++; + p[i++] = ((currinfolist->currencyInfo[ci].durationCurrency.granLengthTimeUnit) >> 8) & 0xff; + ci_len++; c_len++; + } + else { + p[i++] = 0x01; // Length + ci_len++; c_len++; + } + p[i++] = ((currinfolist->currencyInfo[ci].durationCurrency.granLengthTimeUnit) >> 0) & 0xff; ci_len++; c_len++; p[i++] = 0x82; // granuScaleOfTimeUnit ci_len++; c_len++; From e39db4cffdda0648ea5a053a03820ad9367ec46f Mon Sep 17 00:00:00 2001 From: Dennis Grunert Date: Thu, 11 Jan 2024 14:39:31 +0100 Subject: [PATCH 9/9] AOC-S: Changed typeOfCharging to stepFunction The durationCurrency typeOfCharging=stepFunction is more suitable to a per-unit metering than continuousCharging. stepFunction implies start of the first unit at call connect - for normal calls without additional unit charges for call setup, chargedItem CallSetup is set to FreeOfCharge. Source: ETS 300 178 Tested with Bluephone and Clubtelefon 5 ISDN. --- src/isdn/dss1.c | 64 +++++++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/src/isdn/dss1.c b/src/isdn/dss1.c index f05bd1e..2586492 100644 --- a/src/isdn/dss1.c +++ b/src/isdn/dss1.c @@ -201,48 +201,54 @@ static void generate_aocs_fac(call_t *call) LOGP(DISDN, LOGL_DEBUG, "Sending AOC-S facility from metering data: connect_units=%d unit_period_decisecs=%d\n", call->metering_connect_units, call->metering_unit_period_decisecs); - if(call->metering_connect_units == 0) { // Free call - LOGP(DISDN, LOGL_DEBUG, "AOC-S currencyInfoList: BasicComm FreeOfCharge / CallSetup FreeOfCharge\n"); + if(call->metering_connect_units == 0) { + /* Free call */ + LOGP(DISDN, LOGL_DEBUG, "AOC-S currencyInfoList: BasicComm FreeOfCharge; CallSetup FreeOfCharge\n"); fac.u.inv.o.AOCcuril.currencyInfoCount = 2; - fac.u.inv.o.AOCcuril.currencyInfo[0].chargedItem = 0x00; // basic comm - fac.u.inv.o.AOCcuril.currencyInfo[0].currencyType = 0x84; // free - fac.u.inv.o.AOCcuril.currencyInfo[1].chargedItem = 0x02; // call setup - fac.u.inv.o.AOCcuril.currencyInfo[1].currencyType = 0x84; // free + fac.u.inv.o.AOCcuril.currencyInfo[0].chargedItem = 0x00; // BasicComm + fac.u.inv.o.AOCcuril.currencyInfo[0].currencyType = 0x84; // Free + fac.u.inv.o.AOCcuril.currencyInfo[1].chargedItem = 0x02; // CallSetup + fac.u.inv.o.AOCcuril.currencyInfo[1].currencyType = 0x84; // Free } - else if(call->metering_unit_period_decisecs == 0) { // CallSetup-only FlatRate - /* note some payphones (e.g. BluePhone) only interpret 'basic comm' charged item, therefore we don't use 'call setup' charged item */ - LOGP(DISDN, LOGL_DEBUG, "AOC-S currencyInfoList: BasicComm FlatRate / CallSetup FlatRate\n"); + else if(call->metering_unit_period_decisecs == 0) { + /* Connect-only FlatRate call; note some payphones (e.g. BluePhone) only interpret 'BasicComm' charged item, therefore we don't use 'CallSetup' charged item */ + LOGP(DISDN, LOGL_DEBUG, "AOC-S currencyInfoList: BasicComm FlatRate %d/100 EUR; CallSetup FreeOfCharge\n", AOCS_CURRENCY_AMOUNT_PER_UNIT * call->metering_connect_units); fac.u.inv.o.AOCcuril.currencyInfoCount = 2; - fac.u.inv.o.AOCcuril.currencyInfo[0].chargedItem = 0x00; // basic comm - fac.u.inv.o.AOCcuril.currencyInfo[0].currencyType = 0xA2; // FlatRate + fac.u.inv.o.AOCcuril.currencyInfo[0].chargedItem = 0x00; // BasicComm + fac.u.inv.o.AOCcuril.currencyInfo[0].currencyType = 0xA2; // FlatRate strncpy((char *)fac.u.inv.o.AOCcuril.currencyInfo[0].FlatRateCurrency.currency, "EUR", 10); // Currency value fac.u.inv.o.AOCcuril.currencyInfo[0].FlatRateCurrency.currencyAmount = AOCS_CURRENCY_AMOUNT_PER_UNIT * call->metering_connect_units; - fac.u.inv.o.AOCcuril.currencyInfo[0].FlatRateCurrency.multiplier = 1; // 1/100 EUR - fac.u.inv.o.AOCcuril.currencyInfo[1].chargedItem = 0x02; // call setup - fac.u.inv.o.AOCcuril.currencyInfo[1].currencyType = 0xA2; // FlatRate - strncpy((char *)fac.u.inv.o.AOCcuril.currencyInfo[0].FlatRateCurrency.currency, "EUR", 10); // Currency value - fac.u.inv.o.AOCcuril.currencyInfo[1].FlatRateCurrency.currencyAmount = AOCS_CURRENCY_AMOUNT_PER_UNIT * call->metering_connect_units; - fac.u.inv.o.AOCcuril.currencyInfo[1].FlatRateCurrency.multiplier = 1; // 1/100 EUR + fac.u.inv.o.AOCcuril.currencyInfo[0].FlatRateCurrency.multiplier = 1; // 1/100 EUR + fac.u.inv.o.AOCcuril.currencyInfo[1].chargedItem = 0x02; // CallSetup + fac.u.inv.o.AOCcuril.currencyInfo[1].currencyType = 0x84; // Free } - else { // Normal call - /* note some payphones (e.g. BluePhone) only interpret 'basic comm' charged item */ - LOGP(DISDN, LOGL_DEBUG, "AOC-S currencyInfoList: BasicComm DurationCurrency / CallSetup FlatRate\n"); + else { + /* Normal call; note some payphones (e.g. BluePhone) only interpret 'BasicComm' charged item */ fac.u.inv.o.AOCcuril.currencyInfoCount = 2; - fac.u.inv.o.AOCcuril.currencyInfo[0].chargedItem = 0x00; // basic comm - fac.u.inv.o.AOCcuril.currencyInfo[0].currencyType = 0xA1; // DurationCurrency + fac.u.inv.o.AOCcuril.currencyInfo[0].chargedItem = 0x00; // BasicComm + fac.u.inv.o.AOCcuril.currencyInfo[0].currencyType = 0xA1; // DurationCurrency strncpy((char *)fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.currency, "EUR", 10); // Currency value fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.currencyAmount = AOCS_CURRENCY_AMOUNT_PER_UNIT; - fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.multiplier = 1; // 1/100 EUR - fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.typeOfCharging = 0x00; // Contin. Charging + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.multiplier = 1; // 1/100 EUR + fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.typeOfCharging = 1; // StepFunction fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.durLengthTimeUnit = call->metering_unit_period_decisecs * 10; // Unit duration fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.durLengthTimeScale = 0; // 1/100 s fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.granLengthTimeUnit = call->metering_unit_period_decisecs * 10; // Granularity fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.granLengthTimeScale = 0; // 1/100 s - fac.u.inv.o.AOCcuril.currencyInfo[1].chargedItem = 0x02; // call setup - fac.u.inv.o.AOCcuril.currencyInfo[1].currencyType = 0xA2; // FlatRate - strncpy((char *)fac.u.inv.o.AOCcuril.currencyInfo[1].FlatRateCurrency.currency, "EUR", 10); // Currency value - fac.u.inv.o.AOCcuril.currencyInfo[1].FlatRateCurrency.currencyAmount = AOCS_CURRENCY_AMOUNT_PER_UNIT * call->metering_connect_units; - fac.u.inv.o.AOCcuril.currencyInfo[1].FlatRateCurrency.multiplier = 1; // 1/100 EUR + fac.u.inv.o.AOCcuril.currencyInfo[1].chargedItem = 0x02; // CallSetup + if(call->metering_connect_units > 1) { + /* Additional CallSetup charge */ + LOGP(DISDN, LOGL_DEBUG, "AOC-S currencyInfoList: BasicComm DurationCurrency %d/100 EUR per %d/100 seconds; CallSetup FlatRate %d/100 EUR\n", AOCS_CURRENCY_AMOUNT_PER_UNIT, call->metering_unit_period_decisecs * 10, AOCS_CURRENCY_AMOUNT_PER_UNIT * (call->metering_connect_units - 1)); + fac.u.inv.o.AOCcuril.currencyInfo[1].currencyType = 0xA2; // FlatRate + strncpy((char *)fac.u.inv.o.AOCcuril.currencyInfo[1].FlatRateCurrency.currency, "EUR", 10); // Currency value + fac.u.inv.o.AOCcuril.currencyInfo[1].FlatRateCurrency.currencyAmount = AOCS_CURRENCY_AMOUNT_PER_UNIT * (call->metering_connect_units - 1); + fac.u.inv.o.AOCcuril.currencyInfo[1].FlatRateCurrency.multiplier = 1; // 1/100 EUR + } + else { + /* No additional CallSetup charge */ + LOGP(DISDN, LOGL_DEBUG, "AOC-S currencyInfoList: BasicComm DurationCurrency %d/100 EUR per %d/100 seconds; CallSetup FreeOfCharge\n", AOCS_CURRENCY_AMOUNT_PER_UNIT, call->metering_unit_period_decisecs * 10); + fac.u.inv.o.AOCcuril.currencyInfo[1].currencyType = 0x84; // Free + } } encodeFac(fac_ie, &fac);