aboutsummaryrefslogtreecommitdiffstats
path: root/src/libosmocc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libosmocc')
-rw-r--r--src/libosmocc/Makefile.am15
-rw-r--r--src/libosmocc/cause.c251
-rw-r--r--src/libosmocc/cause.h5
-rw-r--r--src/libosmocc/endpoint.c1584
-rw-r--r--src/libosmocc/endpoint.h131
-rw-r--r--src/libosmocc/helper.c193
-rw-r--r--src/libosmocc/helper.h13
-rw-r--r--src/libosmocc/message.c1291
-rw-r--r--src/libosmocc/message.h512
-rw-r--r--src/libosmocc/rtp.c404
-rw-r--r--src/libosmocc/rtp.h8
-rw-r--r--src/libosmocc/screen.c693
-rw-r--r--src/libosmocc/screen.h7
-rw-r--r--src/libosmocc/sdp.c544
-rw-r--r--src/libosmocc/sdp.h6
-rw-r--r--src/libosmocc/session.c640
-rw-r--r--src/libosmocc/session.h130
-rw-r--r--src/libosmocc/socket.c583
-rw-r--r--src/libosmocc/socket.h44
19 files changed, 0 insertions, 7054 deletions
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 <jolly@eversberg.eu>
- * All Rights Reserved
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdint.h>
-#include <arpa/inet.h>
-#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 48290d5..0000000
--- a/src/libosmocc/endpoint.c
+++ /dev/null
@@ -1,1584 +0,0 @@
-/* Endpoint and call process handling
- *
- * (C) 2019 by Andreas Eversberg <jolly@eversberg.eu>
- * All Rights Reserved
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#include "../libtimer/timer.h"
-#include "../libdebug/debug.h"
-#include "endpoint.h"
-
-osmo_cc_endpoint_t *osmo_cc_endpoint_list = NULL;
-
-static osmo_cc_call_t *call_new(osmo_cc_endpoint_t *ep, uint32_t callref)
-{
- osmo_cc_call_t *call, **cp;
-
- call = calloc(1, sizeof(*call));
- if (!call) {
- PDEBUG(DCC, DEBUG_ERROR, "No memory for call process instance.\n");
- abort();
- }
-
- PDEBUG(DCC, DEBUG_DEBUG, "Creating new call with callref %u.\n", callref);
-
- call->ep = ep;
- call->callref = callref;
-
- /* attach to call process list */
- cp = &ep->call_list;
- while (*cp)
- cp = &((*cp)->next);
- *cp = call;
-
- /* return new entry */
- return call;
-}
-
-static void call_delete(osmo_cc_call_t *call)
-{
- osmo_cc_call_t **cp;
-
- PDEBUG(DCC, DEBUG_DEBUG, "Destroying call with callref %u.\n", call->callref);
-
- /* detach from call process list */
- cp = &call->ep->call_list;
- while (*cp != call)
- cp = &((*cp)->next);
- *cp = call->next;
-
- /* flush message queue */
- while (call->sock_queue) {
- osmo_cc_msg_t *msg = osmo_cc_msg_list_dequeue(&call->sock_queue, NULL);
- osmo_cc_free_msg(msg);
- }
-
- /* free remote peer */
- free((char *)call->attached_name);
- free((char *)call->attached_host);
-
- free(call);
-}
-
-static const char *state_names[] = {
- "IDLE",
- "INIT-OUT",
- "INIT-IN",
- "OVERLAP-OUT",
- "OVERLAP-IN",
- "PROCEEDING-OUT",
- "PROCEEDING-IN",
- "ALERTING-OUT",
- "ALERTING-IN",
- "CONNECTING-OUT",
- "CONNECTING-IN",
- "ACTIVE",
- "DISCONNECTING-OUT",
- "DISCONNECTING-IN",
- "DISCONNECT-COLLISION",
- "RELEASING-OUT",
- "ATTACH-SENT",
- "ATTACH-OUT",
- "ATTACH-WAIT",
- "ATTACH-IN",
-};
-
-static void new_call_state(osmo_cc_call_t *call, enum osmo_cc_state new_state)
-{
- PDEBUG(DCC, DEBUG_DEBUG, "Changing call state with callref %u from %s to %s.\n", call->callref, state_names[call->state], state_names[new_state]);
- call->state = new_state;
-}
-
-/* helper to forward message to lower layer */
-static void forward_to_ll(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- if (call->lower_layer_released)
- return;
-
- if (msg->type == OSMO_CC_MSG_SETUP_REQ
- || msg->type == OSMO_CC_MSG_SETUP_RSP) {
- /* screen towards lower layer */
- msg = osmo_cc_screen_msg(call->ep, msg, 0, NULL);
- }
-
- osmo_cc_msg_list_enqueue(&call->ep->ll_queue, msg, call->callref);
-}
-
-static void sock_reject_msg(osmo_cc_socket_t *os, uint32_t callref, uint8_t location, uint8_t socket_cause, uint8_t isdn_cause, uint16_t sip_cause)
-{
- osmo_cc_msg_t *msg;
-
- /* create message */
- msg = osmo_cc_new_msg(OSMO_CC_MSG_REJ_IND);
-
- /* add cause */
- osmo_cc_add_ie_cause(msg, location, isdn_cause, sip_cause, socket_cause);
- osmo_cc_convert_cause_msg(msg);
-
- /* message to socket */
- osmo_cc_sock_send_msg(os, callref, msg, NULL, 0);
-}
-
-static void ll_reject_msg(osmo_cc_call_t *call, uint8_t location, uint8_t socket_cause, uint8_t isdn_cause, uint16_t sip_cause)
-{
- osmo_cc_msg_t *msg;
-
- /* create message */
- msg = osmo_cc_new_msg(OSMO_CC_MSG_REJ_REQ);
-
- /* add cause */
- osmo_cc_add_ie_cause(msg, location, isdn_cause, sip_cause, socket_cause);
- osmo_cc_convert_cause_msg(msg);
-
- /* message to lower layer */
- forward_to_ll(call, msg);
-}
-
-static int split_address(const char *address, const char **host_p, uint16_t *port_p)
-{
- const char *portstring;
-
- *host_p = osmo_cc_host_of_address(address);
- if (!(*host_p)) {
- PDEBUG(DCC, DEBUG_ERROR, "Host IP in given address '%s' is invalid.\n", address);
- return -EINVAL;
- }
- portstring = osmo_cc_port_of_address(address);
- if (!portstring) {
- PDEBUG(DCC, DEBUG_ERROR, "Port number in given address '%s' is not specified or invalid.\n", address);
- return -EINVAL;
- }
- *port_p = atoi(portstring);
-
- return 0;
-}
-
-
-osmo_cc_call_t *osmo_cc_get_attached_interface(osmo_cc_endpoint_t *ep, const char *interface)
-{
- osmo_cc_call_t *att;
-
- for (att = ep->call_list; att; att = att->next) {
- if (att->state != OSMO_CC_STATE_ATTACH_IN)
- continue;
- /* no interface given, just use the attached peer */
- if (!interface[0])
- break;
- /* no interface name given on attached peer, ignore it */
- if (!att->attached_name || !att->attached_name[0])
- continue;
- /* interface given, use the attached peer with the same interface name */
- if (!strcmp(interface, att->attached_name))
- break;
- }
-
- return att;
-}
-/* helper to forward message to upper layer */
-static void forward_to_ul(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- const char *address = NULL, *host = NULL;
- uint16_t port;
- int rc;
-
- if (call->upper_layer_released)
- return;
-
- if (msg->type == OSMO_CC_MSG_SETUP_IND
- || msg->type == OSMO_CC_MSG_SETUP_CNF) {
- /* screen towards upper layer */
- msg = osmo_cc_screen_msg(call->ep, msg, 1, &address);
- }
-
- /* no socket: forward message to upper layer */
- if (call->ep->ul_msg_cb) {
- call->ep->ul_msg_cb(call, msg);
- return;
- }
-
- /* if remote peer is included in the setup message */
- if (address && msg->type == OSMO_CC_MSG_SETUP_IND) {
- rc = split_address(address, &host, &port);
- if (rc < 0) {
- PDEBUG(DCC, DEBUG_ERROR, "Given remote peer's address '%s' in setup message is invalid, rejecting call.\n", address);
-reject:
- /* reject, due to error */
- osmo_cc_free_msg(msg);
- new_call_state(call, OSMO_CC_STATE_IDLE);
- ll_reject_msg(call, call->ep->serving_location, 0, OSMO_CC_ISDN_CAUSE_DEST_OOO, 0);
- call_delete(call);
- return;
- }
- PDEBUG(DCC, DEBUG_DEBUG, "Using host IP '%s' and port '%d' from setup message.\n", host, port);
- }
-
- /* for attach message, use remote peer */
- if (msg->type == OSMO_CC_MSG_ATTACH_IND) {
- host = call->ep->remote_host;
- port = call->ep->remote_port;
- PDEBUG(DCC, DEBUG_DEBUG, "Using host IP '%s' and port '%d' from remote address for attach message.\n", host, port);
- }
-
- /* if there is no remote peer in the setup message, use remote peer */
- if (!address && msg->type == OSMO_CC_MSG_SETUP_IND && call->ep->remote_host) {
- host = call->ep->remote_host;
- port = call->ep->remote_port;
- PDEBUG(DCC, DEBUG_DEBUG, "Using host IP '%s' and port '%d' from remote address for setup message.\n", host, port);
- }
-
- /* if there is no remote peer set, try to use the interface name */
- if (!host && msg->type == OSMO_CC_MSG_SETUP_IND) {
- char interface[256];
- osmo_cc_call_t *att;
-
- rc = osmo_cc_get_ie_called_interface(msg, 0, interface, sizeof(interface));
- if (rc < 0)
- interface[0] = '\0';
- /* check for incoming attachment */
- att = osmo_cc_get_attached_interface(call->ep, interface);
- if (!att && !interface[0]) {
- PDEBUG(DCC, DEBUG_ERROR, "No remote peer attached, rejecting call.\n");
- goto reject;
- }
- if (!att) {
- PDEBUG(DCC, DEBUG_ERROR, "No remote peer attached for given interface '%s', rejecting call.\n", interface);
- goto reject;
- }
- host = att->attached_host;
- port = att->attached_port;
- PDEBUG(DCC, DEBUG_DEBUG, "Using host IP '%s' and port '%d' from attached peer for setup message.\n", host, port);
- }
-
- /* add local interface name to setup message */
- // FIXME: should we do that if there is already an interface name given?
- if (msg->type == OSMO_CC_MSG_SETUP_IND && call->ep->local_name)
- osmo_cc_add_ie_calling_interface(msg, call->ep->local_name);
-
- /* forward message to socket */
- osmo_cc_sock_send_msg(&call->ep->os, call->callref, msg, host, port);
-}
-
-/* send attach indication to socket */
-void send_attach_ind(struct timer *timer)
-{
- osmo_cc_endpoint_t *ep = (osmo_cc_endpoint_t *)timer->priv;
- osmo_cc_call_t *call;
- osmo_cc_msg_t *msg;
-
- PDEBUG(DCC, DEBUG_DEBUG, "Trying to attach to remote peer \"%s\".\n", ep->remote_host);
-
- /* create new call for attachment */
- call = osmo_cc_call_new(ep);
-
- /* create attach message */
- msg = osmo_cc_new_msg(OSMO_CC_MSG_ATTACH_IND);
-
- /* set interface name and address */
- osmo_cc_add_ie_calling_interface(msg, ep->local_name);
- osmo_cc_add_ie_socket_address(msg, ep->local_address);
-
- /* message to socket */
- forward_to_ul(call, msg);
-
- /* set state */
- new_call_state(call, OSMO_CC_STATE_ATTACH_SENT);
-}
-
-void attach_rsp(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- PDEBUG(DCC, DEBUG_INFO, "Attached to remote peer \"%s\".\n", call->ep->remote_address);
-
- /* set state */
- new_call_state(call, OSMO_CC_STATE_ATTACH_OUT);
-
- /* drop message */
- osmo_cc_free_msg(msg);
-}
-
-void attach_rel(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* (re-)start timer for next attachment */
- if (call->state == OSMO_CC_STATE_ATTACH_SENT
- || call->state == OSMO_CC_STATE_ATTACH_OUT) {
- timer_start(&call->ep->attach_timer, OSMO_CC_ATTACH_TIMER);
- PDEBUG(DCC, DEBUG_INFO, "Attachment to remote peer \"%s\" failed, retrying.\n", call->ep->remote_address);
- }
-
- if (call->attached_name)
- PDEBUG(DCC, DEBUG_INFO, "Peer with remote interface \"%s\" detached from us.\n", call->attached_name);
-
- /* change state */
- new_call_state(call, OSMO_CC_STATE_IDLE);
-
- /* unset interface */
- free((char *)call->attached_name);
- call->attached_name = NULL;
- free((char *)call->attached_host);
- call->attached_host = NULL;
-
- /* drop message */
- osmo_cc_free_msg(msg);
-
- /* destroy */
- call_delete(call);
-}
-
-void attach_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- char address[256];
- char interface[256];
- const char *host;
- uint16_t port;
- int rc;
-
- /* get peer from message */
- rc = osmo_cc_get_ie_socket_address(msg, 0, address, sizeof(address));
- if (rc < 0)
- address[0] = '\0';
- if (!address[0]) {
- PDEBUG(DCC, DEBUG_ERROR, "Attachment request from remote peer has no remote address set, rejecting.\n");
-
-rel:
- /* change to REL_REQ */
- msg->type = OSMO_CC_MSG_REL_IND;
- PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type));
-
- /* message to socket */
- forward_to_ul(call, msg);
-
- /* destroy */
- call_delete(call);
-
- return;
- }
- rc = split_address(address, &host, &port);
- if (rc < 0) {
- PDEBUG(DCC, DEBUG_ERROR, "Given remote peer's address '%s' in attach message is invalid, rejecting call.\n", address);
- goto rel;
- }
- free((char *)call->attached_host);
- call->attached_host = strdup(host);
- call->attached_port = port;
-
- rc = osmo_cc_get_ie_calling_interface(msg, 0, interface, sizeof(interface));
- if (rc < 0)
- interface[0] = '\0';
- if (interface[0]) {
- free((char *)call->attached_name);
- call->attached_name = strdup(interface);
- }
-
- PDEBUG(DCC, DEBUG_INFO, "Remote peer with socket address '%s' and port '%d' and interface '%s' attached to us.\n", call->attached_host, call->attached_port, call->attached_name);
-
- /* changing to confirm message */
- msg->type = OSMO_CC_MSG_ATTACH_CNF;
- PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type));
-
- /* message to socket */
- forward_to_ul(call, msg);
-
- /* set state */
- new_call_state(call, OSMO_CC_STATE_ATTACH_IN);
-}
-
-static void setup_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* change state */
- new_call_state(call, OSMO_CC_STATE_INIT_OUT);
-
- /* to lower layer */
- forward_to_ll(call, msg);
-}
-
-static void setup_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* change state */
- new_call_state(call, OSMO_CC_STATE_INIT_IN);
-
- /* to upper layer */
- forward_to_ul(call, msg);
-}
-
-static void rej_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* change state */
- new_call_state(call, OSMO_CC_STATE_IDLE);
-
- /* to lower layer */
- forward_to_ll(call, msg);
-
- /* destroy */
- call_delete(call);
-}
-
-static void rej_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* change state */
- new_call_state(call, OSMO_CC_STATE_IDLE);
-
- /* to upper layer */
- forward_to_ul(call, msg);
-
- /* destroy */
- call_delete(call);
-}
-
-static void setup_ack_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* change state */
- new_call_state(call, OSMO_CC_STATE_OVERLAP_IN);
-
- /* to lower layer */
- forward_to_ll(call, msg);
-}
-
-static void setup_ack_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* change state */
- new_call_state(call, OSMO_CC_STATE_OVERLAP_OUT);
-
- /* to upper layer */
- forward_to_ul(call, msg);
-}
-
-static void proc_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* change state */
- new_call_state(call, OSMO_CC_STATE_PROCEEDING_IN);
-
- /* to lower layer */
- forward_to_ll(call, msg);
-}
-
-static void proc_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* change state */
- new_call_state(call, OSMO_CC_STATE_PROCEEDING_OUT);
-
- /* to upper layer */
- forward_to_ul(call, msg);
-}
-
-static void alert_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* change state */
- new_call_state(call, OSMO_CC_STATE_ALERTING_IN);
-
- /* to lower layer */
- forward_to_ll(call, msg);
-}
-
-static void alert_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* change state */
- new_call_state(call, OSMO_CC_STATE_ALERTING_OUT);
-
- /* to upper layer */
- forward_to_ul(call, msg);
-}
-
-static void setup_rsp(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* change state */
- new_call_state(call, OSMO_CC_STATE_CONNECTING_IN);
-
- /* to lower layer */
- forward_to_ll(call, msg);
-}
-
-static void setup_cnf(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* change state */
- new_call_state(call, OSMO_CC_STATE_CONNECTING_OUT);
-
- /* to upper layer */
- forward_to_ul(call, msg);
-}
-
-static void setup_comp_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* change state */
- new_call_state(call, OSMO_CC_STATE_ACTIVE);
-
- /* to lower layer */
- forward_to_ll(call, msg);
-}
-
-static void setup_comp_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* change state */
- new_call_state(call, OSMO_CC_STATE_ACTIVE);
-
- /* to upper layer */
- forward_to_ul(call, msg);
-}
-
-static void info_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* to lower layer */
- forward_to_ll(call, msg);
-}
-
-static void info_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* to upper layer */
- forward_to_ul(call, msg);
-}
-
-static void progress_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* to lower layer */
- forward_to_ll(call, msg);
-}
-
-static void progress_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* to upper layer */
- forward_to_ul(call, msg);
-}
-
-static void notify_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* to lower layer */
- forward_to_ll(call, msg);
-}
-
-static void notify_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* to upper layer */
- forward_to_ul(call, msg);
-}
-
-static void 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;
- PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type));
-
- /* to lower layer */
- forward_to_ll(call, msg);
-
- return;
- }
-
- /* change state */
- new_call_state(call, OSMO_CC_STATE_DISC_COLLISION);
-
- /* to upper layer */
- forward_to_ul(call, msg);
-}
-
-static void disc_collision_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* release to upper layer wheen there is no lower layer */
- if (call->lower_layer_released) {
- /* change to REL_REQ */
- msg->type = OSMO_CC_MSG_REL_IND;
- PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type));
-
- /* to upper layer */
- forward_to_ul(call, msg);
-
- /* destroy */
- call_delete(call);
-
- return;
- }
-
- /* change state */
- new_call_state(call, OSMO_CC_STATE_DISC_COLLISION);
-
- /* to lower layer */
- forward_to_ll(call, msg);
-}
-
-static void rel_collision(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* change state */
- if (call->state != OSMO_CC_STATE_IDLE)
- new_call_state(call, OSMO_CC_STATE_IDLE);
-
- /* drop message */
- osmo_cc_free_msg(msg);
-
- /* destroy */
- call_delete(call);
-}
-
-static void rej_ind_disc(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* change state */
- new_call_state(call, OSMO_CC_STATE_IDLE);
-
- /* change to REL_IND */
- msg->type = OSMO_CC_MSG_REL_IND;
- PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type));
-
- /* to upper layer */
- forward_to_ul(call, msg);
-
- /* destroy */
- call_delete(call);
-}
-
-static void rej_req_disc(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- /* change state */
- new_call_state(call, OSMO_CC_STATE_IDLE);
-
- /* change to REL_REQ */
- msg->type = OSMO_CC_MSG_REL_REQ;
- PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type));
-
- /* to lower layer */
- forward_to_ll(call, msg);
-
- /* destroy */
- call_delete(call);
-}
-
-static void rel_ind_other(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- // FIXME: does this event really happens in this state?
- // just to be safe we handle it
- /* if thereis no upper layer, we are done */
- if (call->upper_layer_released) {
- /* drop message */
- osmo_cc_free_msg(msg);
-
- /* destroy */
- call_delete(call);
-
- return;
- }
-
- /* change state */
- new_call_state(call, OSMO_CC_STATE_DISCONNECTING_IN);
-
- /* change to DISC_IND */
- msg->type = OSMO_CC_MSG_DISC_IND;
- PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type));
- call->lower_layer_released = 1;
-
- /* to upper layer */
- forward_to_ul(call, msg);
-}
-
-static void rel_req_other(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
-{
- // FIXME: does this event really happens in this state?
- // just to be safe we handle it
- /* if thereis no lower layer, we are done */
- if (call->lower_layer_released) {
- /* drop message */
- osmo_cc_free_msg(msg);
-
- /* destroy */
- call_delete(call);
-
- return;
- }
-
- /* change state */
- new_call_state(call, OSMO_CC_STATE_DISCONNECTING_OUT);
-
- /* change to DISC_REQ */
- msg->type = OSMO_CC_MSG_DISC_REQ;
- PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type));
- call->upper_layer_released = 1;
-
- /* to lower layer */
- forward_to_ll(call, msg);
-}
-
-#define SBIT(a) (1 << a)
-#define ALL_STATES (~0)
-
-static struct statemachine {
- uint32_t states;
- int type;
- void (*action)(osmo_cc_call_t *call, osmo_cc_msg_t *msg);
-} statemachine_list[] = {
- /* attachment states */
- {SBIT(OSMO_CC_STATE_ATTACH_SENT),
- OSMO_CC_MSG_ATTACH_RSP, attach_rsp},
- {SBIT(OSMO_CC_STATE_ATTACH_OUT) | SBIT(OSMO_CC_STATE_ATTACH_SENT),
- OSMO_CC_MSG_REL_REQ, attach_rel},
- {SBIT(OSMO_CC_STATE_IDLE),
- OSMO_CC_MSG_ATTACH_REQ, attach_req},
- {SBIT(OSMO_CC_STATE_ATTACH_IN),
- OSMO_CC_MSG_REL_REQ, attach_rel},
-
- /* call setup toward lower layer protocol */
- {SBIT(OSMO_CC_STATE_IDLE),
- OSMO_CC_MSG_SETUP_REQ, setup_req},
- {SBIT(OSMO_CC_STATE_INIT_OUT),
- OSMO_CC_MSG_SETUP_ACK_IND, setup_ack_ind},
- {SBIT(OSMO_CC_STATE_INIT_OUT) | SBIT(OSMO_CC_STATE_OVERLAP_OUT),
- OSMO_CC_MSG_PROC_IND, proc_ind},
- {SBIT(OSMO_CC_STATE_INIT_OUT) | SBIT(OSMO_CC_STATE_OVERLAP_OUT) |
- SBIT(OSMO_CC_STATE_PROCEEDING_OUT),
- OSMO_CC_MSG_ALERT_IND, alert_ind},
- {SBIT(OSMO_CC_STATE_INIT_OUT) | SBIT(OSMO_CC_STATE_OVERLAP_OUT) |
- SBIT(OSMO_CC_STATE_PROCEEDING_OUT) | SBIT(OSMO_CC_STATE_ALERTING_OUT),
- OSMO_CC_MSG_SETUP_CNF, setup_cnf},
- {SBIT(OSMO_CC_STATE_OVERLAP_OUT) | SBIT(OSMO_CC_STATE_PROCEEDING_OUT) |
- SBIT(OSMO_CC_STATE_ALERTING_OUT),
- OSMO_CC_MSG_PROGRESS_IND, progress_ind},
- {SBIT(OSMO_CC_STATE_OVERLAP_OUT),
- OSMO_CC_MSG_INFO_REQ, info_req},
- {SBIT(OSMO_CC_STATE_PROCEEDING_OUT) | SBIT(OSMO_CC_STATE_ALERTING_OUT),
- OSMO_CC_MSG_NOTIFY_IND, notify_ind},
- {SBIT(OSMO_CC_STATE_CONNECTING_OUT),
- OSMO_CC_MSG_SETUP_COMP_REQ, setup_comp_req},
-
- /* call setup from lower layer protocol */
- {SBIT(OSMO_CC_STATE_IDLE),
- OSMO_CC_MSG_SETUP_IND, setup_ind},
- {SBIT(OSMO_CC_STATE_INIT_IN),
- OSMO_CC_MSG_SETUP_ACK_REQ, setup_ack_req},
- {SBIT(OSMO_CC_STATE_INIT_IN) | SBIT(OSMO_CC_STATE_OVERLAP_IN),
- OSMO_CC_MSG_PROC_REQ, proc_req},
- {SBIT(OSMO_CC_STATE_INIT_IN) | SBIT(OSMO_CC_STATE_OVERLAP_IN) |
- SBIT(OSMO_CC_STATE_PROCEEDING_IN),
- OSMO_CC_MSG_ALERT_REQ, alert_req},
- {SBIT(OSMO_CC_STATE_INIT_IN) | SBIT(OSMO_CC_STATE_OVERLAP_IN) |
- SBIT(OSMO_CC_STATE_PROCEEDING_IN) | SBIT(OSMO_CC_STATE_ALERTING_IN),
- OSMO_CC_MSG_SETUP_RSP, setup_rsp},
- {SBIT(OSMO_CC_STATE_OVERLAP_IN) | SBIT(OSMO_CC_STATE_PROCEEDING_IN) |
- SBIT(OSMO_CC_STATE_ALERTING_IN),
- OSMO_CC_MSG_PROGRESS_REQ, progress_req},
- {SBIT(OSMO_CC_STATE_OVERLAP_IN),
- OSMO_CC_MSG_INFO_IND, info_ind},
- {SBIT(OSMO_CC_STATE_PROCEEDING_IN) | SBIT(OSMO_CC_STATE_ALERTING_IN),
- OSMO_CC_MSG_NOTIFY_REQ, notify_req},
- {SBIT(OSMO_CC_STATE_CONNECTING_IN),
- OSMO_CC_MSG_SETUP_COMP_IND, setup_comp_ind},
-
- /* active state */
- {SBIT(OSMO_CC_STATE_ACTIVE),
- OSMO_CC_MSG_NOTIFY_IND, notify_ind},
- {SBIT(OSMO_CC_STATE_ACTIVE),
- OSMO_CC_MSG_NOTIFY_REQ, notify_req},
- {SBIT(OSMO_CC_STATE_ACTIVE),
- OSMO_CC_MSG_INFO_IND, info_ind},
- {SBIT(OSMO_CC_STATE_ACTIVE),
- OSMO_CC_MSG_INFO_REQ, info_req},
- {SBIT(OSMO_CC_STATE_ACTIVE),
- OSMO_CC_MSG_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) {
- PDEBUG(DCC, DEBUG_INFO, "Message %s unhandled at state %s (callref %d)\n",
- osmo_cc_msg_value2name(msg->type), state_names[call->state], call->callref);
- osmo_cc_free_msg(msg);
- return;
- }
-
- PDEBUG(DCC, DEBUG_INFO, "Handle message %s at state %s (callref %d)\n",
- osmo_cc_msg_value2name(msg->type), state_names[call->state], call->callref);
- if (debuglevel <= DEBUG_INFO)
- osmo_cc_debug_ie(msg, DEBUG_INFO);
- statemachine_list[i].action(call, msg);
-}
-
-static int handle_call(osmo_cc_call_t *call)
-{
- /* may handle only one message, since call may be destroyed when handling */
- if (call->sock_queue) {
- osmo_cc_msg_t *msg = osmo_cc_msg_list_dequeue(&call->sock_queue, NULL);
- handle_msg(call, msg);
- return 1;
- }
-
- return 0;
-}
-
-static int osmo_cc_handle_endpoint(osmo_cc_endpoint_t *ep)
-{
- int work = 0;
- uint32_t callref;
- osmo_cc_call_t *call;
-
- /* may handle only one message, since call may be destroyed when handling */
- if (ep->ll_queue) {
- osmo_cc_msg_t *msg = osmo_cc_msg_list_dequeue(&ep->ll_queue, &callref);
- ep->ll_msg_cb(ep, callref, msg);
- work |= 1;
- }
-
- /* handle only one call, because it might have been removed */
- for (call = ep->call_list; call; call = call->next) {
- work |= handle_call(call);
- if (work)
- break;
- }
-
- return work;
-}
-
-/* main handler
- * note that it must be called in a loop (with other handlers) until no work was done
- */
-int osmo_cc_handle(void)
-{
- int work = 0;
- osmo_cc_endpoint_t *ep;
-
- for (ep = osmo_cc_endpoint_list; ep; ep = ep->next) {
- work |= osmo_cc_handle_endpoint(ep);
- work |= osmo_cc_handle_socket(&ep->os);
- }
-
- return work;
-}
-
-osmo_cc_call_t *osmo_cc_call_by_callref(osmo_cc_endpoint_t *ep, uint32_t callref)
-{
- osmo_cc_call_t *call;
-
- if (!callref)
- return NULL;
-
- for (call = ep->call_list; call; call = call->next) {
- if (call->callref == callref) {
- return call;
- }
- }
-
- return NULL;
-}
-
-
-void osmo_cc_ll_msg(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg)
-{
- osmo_cc_call_t *call;
-
- if (!(msg->type & 1)) {
- PDEBUG(DCC, DEBUG_ERROR, "Received message from lower layer that is not an _IND nor _CNF, please fix!\n");
- osmo_cc_free_msg(msg);
- return;
- }
-
- call = osmo_cc_call_by_callref(ep, callref);
- if (call) {
- /* complete cause */
- osmo_cc_convert_cause_msg(msg);
- handle_msg(call, msg);
- return;
- }
-
- /* if no ref exists */
-}
-
-/* message from upper layer (socket) */
-void osmo_cc_ul_msg(void *priv, uint32_t callref, osmo_cc_msg_t *msg)
-{
- osmo_cc_endpoint_t *ep = priv;
- osmo_cc_call_t *call;
-
- if ((msg->type & 1)) {
- PDEBUG(DCC, DEBUG_ERROR, "Received message from socket that is not an _REQ nor _RSP, please fix!\n");
- osmo_cc_free_msg(msg);
- return;
- }
-
- call = osmo_cc_call_by_callref(ep, callref);
- if (call) {
- /* if we are not in INIT-IN state, we change a CC-REJ-REQ into CC-REL_REQ.
- * this happens, if the socket fails.
- */
- if (call->state != OSMO_CC_STATE_INIT_IN
- && msg->type == OSMO_CC_MSG_REJ_REQ)
- msg->type = OSMO_CC_MSG_REL_REQ;
-
- osmo_cc_msg_list_enqueue(&call->sock_queue, msg, call->callref);
- return;
- }
-
- /* if no ref exists */
-
- /* reject and release are ignored */
- if (msg->type == OSMO_CC_MSG_REJ_REQ
- || msg->type == OSMO_CC_MSG_REL_REQ) {
- osmo_cc_free_msg(msg);
- return;
- }
-
- /* reject if not a setup/attach or release message */
- if (msg->type != OSMO_CC_MSG_SETUP_REQ
- && msg->type != OSMO_CC_MSG_ATTACH_REQ) {
- sock_reject_msg(&ep->os, callref, ep->serving_location, 0, OSMO_CC_ISDN_CAUSE_INVAL_CALLREF, 0);
- osmo_cc_free_msg(msg);
- return;
- }
-
- /* create call instance with one socket reference */
- call = call_new(ep, callref);
-
- osmo_cc_msg_list_enqueue(&call->sock_queue, msg, call->callref);
-}
-
-static void osmo_cc_help_name(void)
-{
- printf("Name options:\n\n");
-
- printf("name <name>\n");
-
- printf("Allows to override endpoint name given by application.\n");
-}
-
-static int osmo_cc_set_name(osmo_cc_endpoint_t *ep, const char *text)
-{
- if (!strncasecmp(text, "name", 4)) {
- text += 4;
- /* remove spaces after keyword */
- while (*text) {
- if (*text > 32)
- break;
- text++;
- }
- } else {
- PDEBUG(DCC, DEBUG_ERROR, "Invalid name definition '%s'\n", text);
- return -EINVAL;
- }
-
- free((char *)ep->local_name);
- ep->local_name = strdup(text);
-
- return 0;
-}
-
-static void osmo_cc_help_address(void)
-{
- printf("Address options:\n\n");
-
- printf("local <IPv4 address>:<port>\n");
- printf("local [<IPv6 address>]:<port>\n");
- printf("remote <IPv4 address>:<port>\n");
- printf("remote [<IPv6 address>]:<port>\n\n");
- printf("remote auto\n\n");
- printf("remote none\n\n");
-
- printf("These options can be used to define local and remote IP and port for the socket\n");
- printf("interface. Note that IPv6 addresses must be enclosed by '[' and ']'.\n\n");
-
- printf("If no local address was given, the IPv4 loopback IP and port %d is used. If\n", OSMO_CC_DEFAULT_PORT);
- printf("this port is already in use, the first free higher port is used.\n\n");
-
- printf("If no remote address is given, the local IP is used. If the local port is %d,\n", OSMO_CC_DEFAULT_PORT);
- printf("the remote port will be %d. If not, the remote port will be %d. This way it is\n", OSMO_CC_DEFAULT_PORT + 1, OSMO_CC_DEFAULT_PORT);
- printf("possible to link two interfaces without any IP configuration required.\n\n");
-
- printf("Use 'remote auto' to enable and 'remote none' to disable. This can be useful to\n");
- printf("override application default.\n\n");
-}
-
-static int osmo_cc_set_address(osmo_cc_endpoint_t *ep, const char *text)
-{
- const char **address_p, **host_p;
- uint16_t *port_p;
- int local = 0;
- int rc;
-
- if (!strncasecmp(text, "local", 5)) {
- text += 5;
- /* remove spaces after keyword */
- while (*text) {
- if (*text > 32)
- break;
- text++;
- }
- address_p = &ep->local_address;
- host_p = &ep->local_host;
- port_p = &ep->local_port;
- local = 1;
- } else if (!strncasecmp(text, "remote", 6)) {
- text += 6;
- /* remove spaces after keyword */
- while (*text) {
- if (*text > 32)
- break;
- text++;
- }
- if (!strcasecmp(text, "auto")) {
- PDEBUG(DCC, DEBUG_DEBUG, "setting automatic remote peer selection\n");
- ep->remote_auto = 1;
- return 0;
- }
- if (!strcasecmp(text, "none")) {
- PDEBUG(DCC, DEBUG_DEBUG, "disable automatic remote peer selection\n");
- ep->remote_auto = 0;
- return 0;
- }
- ep->remote_auto = 0;
- address_p = &ep->remote_address;
- host_p = &ep->remote_host;
- port_p = &ep->remote_port;
- } else {
- PDEBUG(DCC, DEBUG_ERROR, "Invalid local or remote address definition '%s'\n", text);
- return -EINVAL;
- }
-
- if (*address_p) {
- free((char *)*address_p);
- *address_p = NULL;
- }
- if (*host_p) {
- free((char *)*host_p);
- *host_p = NULL;
- }
- rc = split_address(text, host_p, port_p);
- if (rc < 0) {
- /* unset, so that this is not treated with free() */
- *host_p = NULL;
- return rc;
- }
- *address_p = strdup(text);
- *host_p = strdup(*host_p);
-
- if (local) {
- enum osmo_cc_session_addrtype addrtype;
- addrtype = osmo_cc_address_type(*host_p);
- if (addrtype == osmo_cc_session_addrtype_unknown) {
- PDEBUG(DCC, DEBUG_ERROR, "Given local address '%s' is invalid.\n", *host_p);
- return -EINVAL;
- }
- osmo_cc_set_local_peer(&ep->session_config, osmo_cc_session_nettype_inet, addrtype, *host_p);
- return 0;
- }
-
- return 0;
-}
-
-static void osmo_cc_help_rtp(void)
-{
- printf("RTP options:\n\n");
-
- printf("rtp-peer <IPv4 address>\n");
- printf("rtp-peer <IPv6 address>\n");
- printf("rtp-ports <first> <last>\n\n");
-
- printf("These options can be used to alter the local IP and port range for RTP traffic.\n");
- printf("By default the local peer is used, which is loopback by default. To connect\n");
- printf("interfaces, between machines, local machine's IP must be given.\n\n");
-}
-
-static int osmo_cc_set_rtp(osmo_cc_endpoint_t *ep, const char *text)
-{
- int peer = 0, ports = 0;
-
- if (!strncasecmp(text, "rtp-peer", 8)) {
- text += 8;
- peer = 1;
- } else if (!strncasecmp(text, "rtp-ports", 9)) {
- text += 9;
- ports = 1;
- } else {
- PDEBUG(DCC, DEBUG_ERROR, "Invalid RTP definition '%s'\n", text);
- return -EINVAL;
- }
-
- /* remove spaces after keyword */
- while (*text) {
- if (*text > 32)
- break;
- text++;
- }
-
- if (peer) {
- enum osmo_cc_session_addrtype addrtype;
- addrtype = osmo_cc_address_type(text);
- if (addrtype == osmo_cc_session_addrtype_unknown) {
- PDEBUG(DCC, DEBUG_ERROR, "Given RTP address '%s' is invalid.\n", text);
- return -EINVAL;
- }
- osmo_cc_set_local_peer(&ep->session_config, osmo_cc_session_nettype_inet, addrtype, text);
- return 0;
- }
-
- if (ports) {
- int from = 0, to = 0;
-
- /* from port */
- while (*text > ' ') {
- if (*text < '0' || *text > '9') {
- PDEBUG(DCC, DEBUG_ERROR, "Given 'from' port in '%s' is invalid.\n", text);
- return -EINVAL;
- }
- from = from * 10 + *text - '0';
- text++;
- }
-
- /* remove spaces after keyword */
- while (*text) {
- if (*text > 32)
- break;
- text++;
- }
-
- /* to port */
- while (*text > ' ') {
- if (*text < '0' || *text > '9') {
- PDEBUG(DCC, DEBUG_ERROR, "Given 'to' port in '%s' is invalid.\n", text);
- return -EINVAL;
- }
- to = to * 10 + *text - '0';
- text++;
- }
-
- osmo_cc_set_rtp_ports(&ep->session_config, from, to);
- return 0;
- }
-
- return -EINVAL;
-}
-
-void osmo_cc_help(void)
-{
- osmo_cc_help_name();
- osmo_cc_help_address();
- osmo_cc_help_rtp();
- osmo_cc_help_screen();
-}
-
-/* create a new endpoint instance */
-int osmo_cc_new(osmo_cc_endpoint_t *ep, const char *version, const char *name, uint8_t serving_location, void (*ll_msg_cb)(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg), void (*ul_msg_cb)(osmo_cc_call_t *call, osmo_cc_msg_t *msg), void *priv, int argc, const char *argv[])
-{
- osmo_cc_endpoint_t **epp;
- int rc;
- int i;
-
- PDEBUG(DCC, DEBUG_DEBUG, "Creating new endpoint instance.\n");
-
- if (!!strcmp(version, OSMO_CC_VERSION)) {
- PDEBUG(DCC, DEBUG_ERROR, "Application was compiled for different Osmo-CC version.\n");
- return OSMO_CC_RC_VERSION_MISMATCH;
- }
-
- memset(ep, 0, sizeof(*ep));
-
- /* attach to list */
- epp = &osmo_cc_endpoint_list;
- while (*epp)
- epp = &((*epp)->next);
- *epp = ep;
-
- if (name)
- ep->local_name = strdup(name);
- ep->ll_msg_cb = ll_msg_cb;
- ep->ul_msg_cb = ul_msg_cb;
- ep->serving_location = serving_location;
- ep->priv = priv;
-
- osmo_cc_set_local_peer(&ep->session_config, osmo_cc_session_nettype_inet, osmo_cc_session_addrtype_ipv4, "127.0.0.1");
- osmo_cc_set_rtp_ports(&ep->session_config, 16384, 32767);
-
- /* apply args */
- for (i = 0; i < argc; i++) {
- if (!strncasecmp(argv[i], "name", 4)) {
- rc = osmo_cc_set_name(ep, argv[i]);
- if (rc < 0) {
- return rc;
- }
- } else
- if (!strncasecmp(argv[i], "local", 5)) {
- rc = osmo_cc_set_address(ep, argv[i]);
- if (rc < 0) {
- return rc;
- }
- } else
- if (!strncasecmp(argv[i], "remote", 6)) {
- rc = osmo_cc_set_address(ep, argv[i]);
- if (rc < 0) {
- return rc;
- }
- } else
- if (!strncasecmp(argv[i], "rtp", 3)) {
- rc = osmo_cc_set_rtp(ep, argv[i]);
- if (rc < 0) {
- return rc;
- }
- } else
- if (!strncasecmp(argv[i], "screen", 6)) {
- rc = osmo_cc_add_screen(ep, argv[i]);
- if (rc < 0) {
- return rc;
- }
- } else {
- PDEBUG(DCC, DEBUG_ERROR, "Unknown osmo-cc argument \"%s\"\n", argv[i]);
- return -EINVAL;
- }
- }
-
- /* open socket */
- if (!ul_msg_cb) {
- char address[256];
- const char *host;
- uint16_t port;
- enum osmo_cc_session_addrtype addrtype;
-
- host = ep->local_host;
- port = ep->local_port;
- if (!host) {
- host = "127.0.0.1";
- PDEBUG(DCC, DEBUG_DEBUG, "No local peer set, using default \"%s\"\n", host);
- }
- rc = osmo_cc_open_socket(&ep->os, host, port, ep, osmo_cc_ul_msg, serving_location);
- if (rc < 0) {
- return rc;
- }
- port = rc;
- if (!ep->local_host) {
- ep->local_host = strdup(host);
- /* create address string */
- addrtype = osmo_cc_address_type(host);
- if (addrtype == osmo_cc_session_addrtype_ipv6)
- sprintf(address, "[%s]:%d", host, port);
- else
- sprintf(address, "%s:%d", host, port);
- ep->local_address = strdup(address);
- }
- ep->local_port = port;
- /* auto configure */
- if (ep->remote_auto) {
- free((char *)ep->remote_host);
- ep->remote_host = strdup(ep->local_host);
- PDEBUG(DCC, DEBUG_DEBUG, "Remote peer set to auto, using local peer's host \"%s\" for remote peer.\n", ep->remote_host);
- if (rc == OSMO_CC_DEFAULT_PORT)
- ep->remote_port = OSMO_CC_DEFAULT_PORT + 1;
- else
- ep->remote_port = OSMO_CC_DEFAULT_PORT;
- PDEBUG(DCC, DEBUG_DEBUG, " -> Using remote port %d.\n", ep->remote_port);
- /* create address string */
- free((char *)ep->remote_address);
- addrtype = osmo_cc_address_type(ep->remote_host);
- if (addrtype == osmo_cc_session_addrtype_ipv6)
- sprintf(address, "[%s]:%d", ep->remote_host, ep->remote_port);
- else
- sprintf(address, "%s:%d", ep->remote_host, ep->remote_port);
- ep->remote_address = strdup(address);
- }
- /* attach to remote host */
- timer_init(&ep->attach_timer, send_attach_ind, ep);
- if (ep->remote_host) {
- send_attach_ind(&ep->attach_timer);
- }
- }
-
- return 0;
-}
-
-/* destroy an endpoint instance */
-void osmo_cc_delete(osmo_cc_endpoint_t *ep)
-{
- osmo_cc_endpoint_t **epp;
-
- PDEBUG(DCC, DEBUG_DEBUG, "Destroying endpoint instance.\n");
-
- /* detach from list >*/
- epp = &osmo_cc_endpoint_list;
- while (*epp && *epp != ep)
- epp = &((*epp)->next);
- if (*epp)
- *epp = ep->next;
-
- /* remove timer */
- timer_exit(&ep->attach_timer);
-
- /* flush screen lists */
- osmo_cc_flush_screen(ep->screen_calling_in);
- osmo_cc_flush_screen(ep->screen_called_in);
- osmo_cc_flush_screen(ep->screen_calling_out);
- osmo_cc_flush_screen(ep->screen_called_out);
-
- /* free local and remote peer */
- free((char *)ep->local_name);
- free((char *)ep->local_address);
- free((char *)ep->local_host);
- free((char *)ep->remote_address);
- free((char *)ep->remote_host);
-
- /* destroying all child callesses (calls) */
- while(ep->call_list)
- call_delete(ep->call_list);
-
- /* flush message queue */
- while(ep->ll_queue) {
- osmo_cc_msg_t *msg = osmo_cc_msg_list_dequeue(&ep->ll_queue, NULL);
- osmo_cc_free_msg(msg);
- }
-
- /* remove socket */
- osmo_cc_close_socket(&ep->os);
-
- memset(ep, 0, sizeof(*ep));
-}
-
-/* create new call instance */
-osmo_cc_call_t *osmo_cc_call_new(osmo_cc_endpoint_t *ep)
-{
- return call_new(ep, osmo_cc_new_callref());
-}
-
-/* destroy call instance */
-void osmo_cc_call_delete(osmo_cc_call_t *call)
-{
- call_delete(call);
-}
-
-/* check valid IP and return address type (protocol) */
-enum osmo_cc_session_addrtype osmo_cc_address_type(const char *address)
-{
- struct sockaddr_storage sa;
- int rc;
-
- rc = inet_pton(AF_INET, address, &sa);
- if (rc > 0)
- return osmo_cc_session_addrtype_ipv4;
- rc = inet_pton(AF_INET6, address, &sa);
- if (rc > 0)
- return osmo_cc_session_addrtype_ipv6;
-
- return osmo_cc_session_addrtype_unknown;
-}
-
-/* get host from address */
-const char *osmo_cc_host_of_address(const char *address)
-{
- static char host[256];
- char *p;
-
- if (strlen(address) >= sizeof(host)) {
- PDEBUG(DCC, DEBUG_ERROR, "String way too long!\n");
- return NULL;
- }
-
- if (address[0] == '[' && (p = strchr(address, ']'))) {
- memcpy(host, address + 1, p - address - 1);
- host[p - address - 1] = '\0';
- return host;
- }
-
- strcpy(host, address);
- if ((p = strchr(host, ':')))
- *p = '\0';
-
- return host;
-}
-
-/* get port from address */
-const char *osmo_cc_port_of_address(const char *address)
-{
- const char *p;
- int i;
-
- if (address[0] == '[' && (p = strchr(address, ']')))
- address = p + 1;
-
- if (!(p = strchr(address, ':')))
- return NULL;
- p++;
-
- /* check for zero */
- if (p[0] == '0')
- return NULL;
-
- /* check for digits */
- for (i = 0; i < (int)strlen(p); i++) {
- if (p[i] < '0' || p[i] > '9')
- return NULL;
- }
-
- /* check for magnitude */
- if (atoi(p) > 65535)
- return NULL;
-
- return p;
-}
-
diff --git a/src/libosmocc/endpoint.h b/src/libosmocc/endpoint.h
deleted file mode 100644
index 4425532..0000000
--- a/src/libosmocc/endpoint.h
+++ /dev/null
@@ -1,131 +0,0 @@
-#ifndef OSMO_CC_ENDPOINT_H
-#define OSMO_CC_ENDPOINT_H
-
-#include "message.h"
-#include "socket.h"
-#include "cause.h"
-
-/* special osmo-cc error codes */
-#define OSMO_CC_RC_SEE_ERRNO -1
-#define OSMO_CC_RC_VERSION_MISMATCH 1
-
-#define OSMO_CC_ATTACH_TIMER 2
-
-/* call control state */
-enum osmo_cc_state {
- OSMO_CC_STATE_IDLE = 0,
- /* call states */
- OSMO_CC_STATE_INIT_OUT, /* outgoing CC-SETUP-REQ sent */
- OSMO_CC_STATE_INIT_IN, /* incoming CC-SETUP-IND received */
- OSMO_CC_STATE_OVERLAP_OUT, /* received CC-SETUP-ACK-IND on outgoing call */
- OSMO_CC_STATE_OVERLAP_IN, /* sent CC-SETUP-ACK-REQ on incoming call */
- OSMO_CC_STATE_PROCEEDING_OUT, /* received CC-PROC-IND on outgoing call */
- OSMO_CC_STATE_PROCEEDING_IN, /* sent CC-PROC-REQ on incoming call */
- OSMO_CC_STATE_ALERTING_OUT, /* received CC-ALERT-IND on outgoing call */
- OSMO_CC_STATE_ALERTING_IN, /* sent CC-ALERT-REQ on incoming call */
- OSMO_CC_STATE_CONNECTING_OUT, /* received CC-SETUP-CNF on outgoing call */
- OSMO_CC_STATE_CONNECTING_IN, /* sent CC-SETUP-RSP on incoming call */
- OSMO_CC_STATE_ACTIVE, /* received or sent CC-SETUP-COMPL-* */
- OSMO_CC_STATE_DISCONNECTING_OUT, /* sent CC-DISC-REQ */
- OSMO_CC_STATE_DISCONNECTING_IN, /* received CC-DISC-IND */
- OSMO_CC_STATE_DISC_COLLISION, /* received CC-DISC-IND after sending CC-DISC_REQ */
- OSMO_CC_STATE_RELEASING_OUT, /* sent CC-REL-REQ */
- /* attachment states */
- OSMO_CC_STATE_ATTACH_SENT, /* outgoing CC-ATT-REQ sent to socket */
- OSMO_CC_STATE_ATTACH_OUT, /* received CC-ATT-RSP on outgoing socket */
- OSMO_CC_STATE_ATTACH_WAIT, /* wait for outgoing attachment after failure */
- OSMO_CC_STATE_ATTACH_IN, /* incoming CC-ATT-REQ received from socket*/
-};
-
-/* sample type */
-typedef int16_t osmo_cc_sample_t;
-
-#define OSMO_CC_SAMPLE_MILLIWATT 23170 /* peak sine at -3 dB of full sample range */
-#define OSMO_CC_SAMPLE_SPEECH 3672 /* peak speech at -16 dB of milliwatt */
-#define OSMO_CC_SAMPLE_MIN -32768 /* lowest level */
-#define OSMO_CC_SAMPLE_MAX 32767 /* highest level */
-
-#include "session.h"
-
-struct osmo_cc_call;
-
-typedef struct osmo_cc_screen_list {
- struct osmo_cc_screen_list *next;
- int has_from_type;
- uint8_t from_type;
- int has_from_present;
- uint8_t from_present;
- char from[128];
- int has_to_type;
- uint8_t to_type;
- int has_to_present;
- uint8_t to_present;
- char to[128];
-} osmo_cc_screen_list_t;
-
-/* endpoint instance */
-typedef struct osmo_cc_endpoint {
- struct osmo_cc_endpoint *next;
- void *priv;
- void (*ll_msg_cb)(struct osmo_cc_endpoint *ep, uint32_t callref, osmo_cc_msg_t *msg);
- void (*ul_msg_cb)(struct osmo_cc_call *call, osmo_cc_msg_t *msg);
- osmo_cc_msg_list_t *ll_queue; /* messages towards lower layer */
- struct osmo_cc_call *call_list;
- const char *local_name; /* name of interface */
- const char *local_address; /* host+port */
- const char *local_host;
- uint16_t local_port;
- const char *remote_address; /* host+port */
- const char *remote_host;
- uint16_t remote_port;
- uint8_t serving_location;
- osmo_cc_socket_t os;
- osmo_cc_screen_list_t *screen_calling_in;
- osmo_cc_screen_list_t *screen_called_in;
- osmo_cc_screen_list_t *screen_calling_out;
- osmo_cc_screen_list_t *screen_called_out;
- int remote_auto; /* automatic remote address */
- struct timer attach_timer; /* timer to retry attachment */
- osmo_cc_session_config_t session_config; /* SDP/RTP default configuration */
-} osmo_cc_endpoint_t;
-
-extern osmo_cc_endpoint_t *osmo_cc_endpoint_list;
-
-/* call process */
-typedef struct osmo_cc_call {
- struct osmo_cc_call *next;
- osmo_cc_endpoint_t *ep;
- enum osmo_cc_state state;
- int lower_layer_released; /* when lower layer sent release, while upper layer gets a disconnect */
- int upper_layer_released; /* when upper layer sent release, while lower layer gets a disconnect */
- uint32_t callref;
- osmo_cc_msg_list_t *sock_queue; /* messages from socket */
- const char *attached_host; /* host and port from remote peer that attached to us */
- uint16_t attached_port;
- const char *attached_name; /* interface name from remote peer that attached to us */
-} osmo_cc_call_t;
-
-/* returns 0 if ok
- * returns <0 for error as indicated
- * returns >=1 to indicate osmo-cc error code
- */
-
-void osmo_cc_help(void);
-int osmo_cc_new(osmo_cc_endpoint_t *ep, const char *version, const char *name, uint8_t serving_location, void (*ll_msg_cb)(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg), void (*ul_msg_cb)(osmo_cc_call_t *call, osmo_cc_msg_t *msg), void *priv, int argc, const char *argv[]);
-void osmo_cc_delete(struct osmo_cc_endpoint *ep);
-int osmo_cc_handle(void);
-osmo_cc_call_t *osmo_cc_call_by_callref(osmo_cc_endpoint_t *ep, uint32_t callref);
-osmo_cc_call_t *osmo_cc_get_attached_interface(osmo_cc_endpoint_t *ep, const char *interface);
-void osmo_cc_ll_msg(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg);
-void osmo_cc_ul_msg(void *priv, uint32_t callref, osmo_cc_msg_t *msg);
-osmo_cc_call_t *osmo_cc_call_new(osmo_cc_endpoint_t *ep);
-void osmo_cc_call_delete(struct osmo_cc_call *call);
-enum osmo_cc_session_addrtype osmo_cc_address_type(const char *address);
-const char *osmo_cc_host_of_address(const char *address);
-const char *osmo_cc_port_of_address(const char *address);
-
-#include "rtp.h"
-#include "sdp.h"
-#include "screen.h"
-
-#endif /* OSMO_CC_ENDPOINT_H */
diff --git a/src/libosmocc/helper.c b/src/libosmocc/helper.c
deleted file mode 100644
index 7700174..0000000
--- a/src/libosmocc/helper.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/* Osmo-CC: helpers to simplify Osmo-CC usage
- *
- * (C) 2016 by Andreas Eversberg <jolly@eversberg.eu>
- * All Rights Reserved
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <inttypes.h>
-#include "../libtimer/timer.h"
-#include "../libdebug/debug.h"
-#include "endpoint.h"
-#include "helper.h"
-
-osmo_cc_session_t *osmo_cc_helper_audio_offer(osmo_cc_session_config_t *conf, void *priv, struct osmo_cc_helper_audio_codecs *codecs, void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len), osmo_cc_msg_t *msg, int debug)
-{
- osmo_cc_session_t *session;
- osmo_cc_session_media_t *media;
- const char *sdp;
- int i;
-
- session = osmo_cc_new_session(conf, priv, NULL, NULL, NULL, 0, 0, NULL, NULL, debug);
- if (!session)
- return NULL;
-
- media = osmo_cc_add_media(session, 0, 0, NULL, osmo_cc_session_media_type_audio, 0, osmo_cc_session_media_proto_rtp, 1, 1, receiver, debug);
- osmo_cc_rtp_open(media);
-
- for (i = 0; codecs[i].payload_name; i++)
- osmo_cc_add_codec(media, codecs[i].payload_name, codecs[i].payload_rate, codecs[i].payload_channels, codecs[i].encoder, codecs[i].decoder, debug);
-
- sdp = osmo_cc_session_send_offer(session);
- osmo_cc_add_ie_sdp(msg, sdp);
-
- return session;
-}
-
-const char *osmo_cc_helper_audio_accept(osmo_cc_session_config_t *conf, void *priv, struct osmo_cc_helper_audio_codecs *codecs, void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len), osmo_cc_msg_t *msg, osmo_cc_session_t **session_p, osmo_cc_session_codec_t **codec_p, int force_our_codec)
-{
- char offer_sdp[65536];
- const char *accept_sdp;
- osmo_cc_session_media_t *media, *selected_media;
- osmo_cc_session_codec_t *codec, *selected_codec, *telephone_event;
- int rc;
- int i, selected_codec_i, telephone_event_i;
-
- if (*session_p) {
- PDEBUG(DCC, DEBUG_ERROR, "Session already set, please fix!\n");
- abort();
- }
- if (*codec_p) {
- PDEBUG(DCC, DEBUG_ERROR, "Codec already set, please fix!\n");
- abort();
- }
-
- /* SDP IE */
- rc = osmo_cc_get_ie_sdp(msg, 0, offer_sdp, sizeof(offer_sdp));
- if (rc < 0) {
- PDEBUG(DCC, DEBUG_ERROR, "There is no SDP included in setup request.\n");
- return NULL;
- }
-
- *session_p = osmo_cc_session_receive_offer(conf, priv, offer_sdp);
- if (!*session_p) {
- PDEBUG(DCC, DEBUG_ERROR, "Failed to parse SDP.\n");
- return NULL;
- }
-
- selected_media = NULL;
- osmo_cc_session_for_each_media((*session_p)->media_list, media) {
- /* only audio */
- if (media->description.type != osmo_cc_session_media_type_audio)
- continue;
- selected_codec_i = -1;
- selected_codec = NULL;
- telephone_event_i = -1;
- telephone_event = NULL;
- osmo_cc_session_for_each_codec(media->codec_list, codec) {
- if (!!strcasecmp(codec->payload_name, "telephone-event")) {
- for (i = 0; codecs[i].payload_name; i++) {
- if (osmo_cc_session_if_codec(codec, codecs[i].payload_name, codecs[i].payload_rate, codecs[i].payload_channels)) {
- /* select the first matchting codec or the one we prefer */
- if (selected_codec_i < 0 || i < selected_codec_i) {
- selected_codec = codec;
- selected_codec_i = i;
- selected_media = media;
- }
- /* if we don't force our preferred codec, use the preferred one from the remote */
- if (!force_our_codec)
- break;
- }
- }
- } else {
- /* special case: add telephone-event, if supported */
- for (i = 0; codecs[i].payload_name; i++) {
- if (!!strcasecmp(codecs[i].payload_name, "telephone-event"))
- continue;
- telephone_event = codec;
- telephone_event_i = i;
- break;
- }
- }
- }
- /* codec is selected within this media, we are done */
- if (selected_codec)
- break;
- }
- if (!selected_codec) {
- PDEBUG(DCC, DEBUG_ERROR, "No codec found in setup message that we support.\n");
- osmo_cc_free_session(*session_p);
- *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)) {
- PDEBUG(DCC, DEBUG_ERROR, "Session not set, please fix!\n");
- abort();
- }
-
- /* once done, just ignore further messages that reply to setup */
- if (*codec_p)
- return 0;
-
- /* SDP IE */
- rc = osmo_cc_get_ie_sdp(msg, 0, sdp, sizeof(sdp));
- if (rc < 0)
- return 0; // no reply in this message
-
- rc = osmo_cc_session_receive_answer(*session_p, sdp);
- if (rc < 0)
- return rc;
-
- osmo_cc_session_for_each_media((*session_p)->media_list, media) {
- /* only audio */
- if (media->description.type != osmo_cc_session_media_type_audio)
- continue;
- /* select first codec, if one was accpeted */
- if (media->codec_list)
- *codec_p = media->codec_list;
- if (*codec_p) {
- osmo_cc_rtp_connect(media);
- /* no more media streams */
- break;
- }
- }
- if (!(*codec_p)) {
- PDEBUG(DCC, DEBUG_ERROR, "No codec found in setup reply message that we support.\n");
- return -EIO;
- }
-
- return 0;
-}
-
diff --git a/src/libosmocc/helper.h b/src/libosmocc/helper.h
deleted file mode 100644
index 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 ab66a9f..0000000
--- a/src/libosmocc/message.c
+++ /dev/null
@@ -1,1291 +0,0 @@
-/* Osmo-CC: Message handling
- *
- * (C) 2016 by Andreas Eversberg <jolly@eversberg.eu>
- * All Rights Reserved
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <arpa/inet.h>
-#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 "<unknown>"; \
- else \
- return array[value]; \
-}
-
-#define _OSMO_CC_NAME2VALUE(array) { \
- int value; \
- for (value = 0; (size_t)value < (sizeof(array) / sizeof(array[0])); value++) { \
- if (!strcasecmp(array[value], name)) \
- return value; \
- } \
- return -1; \
-}
-
-static const char *osmo_cc_msg_name[OSMO_CC_MSG_NUM] = {
- [OSMO_CC_MSG_SETUP_REQ] = "CC-SETUP-REQ",
- [OSMO_CC_MSG_SETUP_IND] = "CC-SETUP-IND",
- [OSMO_CC_MSG_REJ_REQ] = "CC-REJ-REQ",
- [OSMO_CC_MSG_REJ_IND] = "CC-REJ-IND",
- [OSMO_CC_MSG_SETUP_ACK_REQ] = "CC-SETUP-ACK-REQ",
- [OSMO_CC_MSG_SETUP_ACK_IND] = "CC-SETUP-ACK-IND",
- [OSMO_CC_MSG_PROC_REQ] = "CC-PROC-REQ",
- [OSMO_CC_MSG_PROC_IND] = "CC-PROC-IND",
- [OSMO_CC_MSG_ALERT_REQ] = "CC-ALERT-REQ",
- [OSMO_CC_MSG_ALERT_IND] = "CC-ALERT-IND",
- [OSMO_CC_MSG_SETUP_RSP] = "CC-SETUP-RSP",
- [OSMO_CC_MSG_SETUP_CNF] = "CC-SETUP-CNF",
- [OSMO_CC_MSG_SETUP_COMP_REQ] = "CC-SETUP-COMP-REQ",
- [OSMO_CC_MSG_SETUP_COMP_IND] = "CC-SETUP-COMP-IND",
- [OSMO_CC_MSG_DISC_REQ] = "CC-DISC-REQ",
- [OSMO_CC_MSG_DISC_IND] = "CC-DISC-IND",
- [OSMO_CC_MSG_REL_REQ] = "CC-REL-REQ",
- [OSMO_CC_MSG_REL_CNF] = "CC-REL-CNF",
- [OSMO_CC_MSG_REL_IND] = "CC-REL-IND",
- [OSMO_CC_MSG_PROGRESS_REQ] = "CC-PROGRESS-REQ",
- [OSMO_CC_MSG_PROGRESS_IND] = "CC-PROGRESS-IND",
- [OSMO_CC_MSG_NOTIFY_REQ] = "CC-NOTIFY-REQ",
- [OSMO_CC_MSG_NOTIFY_IND] = "CC-NOTIFY-IND",
- [OSMO_CC_MSG_INFO_REQ] = "CC-INFO-REQ",
- [OSMO_CC_MSG_INFO_IND] = "CC-INFO-IND",
- [OSMO_CC_MSG_ATTACH_REQ] = "CC-ATTACH-REQ",
- [OSMO_CC_MSG_ATTACH_IND] = "CC-ATTACH-IND",
- [OSMO_CC_MSG_ATTACH_RSP] = "CC-ATTACH-RSP",
- [OSMO_CC_MSG_ATTACH_CNF] = "CC-ATTACH-CNF",
-};
-
-const char *osmo_cc_msg_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_msg_name)
-int osmo_cc_msg_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_msg_name)
-
-static const char *osmo_cc_ie_name[OSMO_CC_IE_NUM] = {
- [OSMO_CC_IE_CALLED] = "IE_CALLED",
- [OSMO_CC_IE_CALLED_SUB] = "IE_CALLED_SUB",
- [OSMO_CC_IE_CALLED_NAME] = "IE_CALLED_NAME",
- [OSMO_CC_IE_CALLED_INTERFACE] = "IE_CALLED_INTERFACE",
- [OSMO_CC_IE_DTMF] = "IE_DTMF",
- [OSMO_CC_IE_KEYPAD] = "IE_KEYPAD",
- [OSMO_CC_IE_COMPLETE] = "IE_COMPLETE",
- [OSMO_CC_IE_CALLING] = "IE_CALLING",
- [OSMO_CC_IE_CALLING_SUB] = "IE_CALLING_SUB",
- [OSMO_CC_IE_CALLING_NAME] = "IE_CALLING_NAME",
- [OSMO_CC_IE_CALLING_INTERFACE] = "IE_CALLING_INTERFACE",
- [OSMO_CC_IE_CALLING_NETWORK] = "IE_CALLING_NETWORK",
- [OSMO_CC_IE_REDIR] = "IE_REDIR",
- [OSMO_CC_IE_PROGRESS] = "IE_PROGRESS",
- [OSMO_CC_IE_NOTIFY] = "IE_NOTIFY",
- [OSMO_CC_IE_DISPLAY] = "IE_DISPLAY",
- [OSMO_CC_IE_CAUSE] = "IE_CAUSE",
- [OSMO_CC_IE_BEARER] = "IE_BEARER",
- [OSMO_CC_IE_SDP] = "IE_SDP",
- [OSMO_CC_IE_SOCKET_ADDRESS] = "IE_SOCKET_ADDRESS",
- [OSMO_CC_IE_PRIVATE] = "IE_PRIVATE",
-};
-
-const char *osmo_cc_ie_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_ie_name)
-int osmo_cc_ie_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_ie_name)
-
-static const char *osmo_cc_type_name[OSMO_CC_TYPE_NUM] = {
- [OSMO_CC_TYPE_UNKNOWN] = "unknown",
- [OSMO_CC_TYPE_INTERNATIONAL] = "international",
- [OSMO_CC_TYPE_NATIONAL] = "national",
- [OSMO_CC_TYPE_NETWORK] = "network",
- [OSMO_CC_TYPE_SUBSCRIBER] = "subscriber",
- [OSMO_CC_TYPE_ABBREVIATED] = "abbreviated",
- [OSMO_CC_TYPE_RESERVED] = "reserved",
-};
-
-const char *osmo_cc_type_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_type_name)
-int osmo_cc_type_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_type_name)
-
-static const char *osmo_cc_plan_name[OSMO_CC_PLAN_NUM] = {
- [OSMO_CC_PLAN_UNKNOWN] = "unknown",
- [OSMO_CC_PLAN_TELEPHONY] = "telephony",
- [OSMO_CC_PLAN_DATA] = "data",
- [OSMO_CC_PLAN_TTY] = "tty",
- [OSMO_CC_PLAN_NATIONAL_STANDARD] = "national standard",
- [OSMO_CC_PLAN_PRIVATE] = "private",
- [OSMO_CC_PLAN_RESERVED] = "reserved",
-};
-
-const char *osmo_cc_plan_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_plan_name)
-int osmo_cc_plan_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_plan_name)
-
-static const char *osmo_cc_present_name[OSMO_CC_PRESENT_NUM] = {
- [OSMO_CC_PRESENT_ALLOWED] = "allowed",
- [OSMO_CC_PRESENT_RESTRICTED] = "restricted",
- [OSMO_CC_PRESENT_NOT_AVAIL] = "not available",
- [OSMO_CC_PRESENT_RESERVED] = "reserved",
-};
-
-const char *osmo_cc_present_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_present_name)
-int osmo_cc_present_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_present_name)
-
-static const char *osmo_cc_screen_name[OSMO_CC_SCREEN_NUM] = {
- [OSMO_CC_SCREEN_USER_UNSCREENED] = "unscreened",
- [OSMO_CC_SCREEN_USER_VERIFIED_PASSED] = "user provided and passed",
- [OSMO_CC_SCREEN_USER_VERIFIED_FAILED] = "user provided an failed",
- [OSMO_CC_SCREEN_NETWORK] = "network provided",
-};
-
-const char *osmo_cc_screen_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_screen_name)
-int osmo_cc_screen_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_screen_name)
-
-static const char *osmo_cc_redir_reason_name[OSMO_CC_REDIR_REASON_NUM] = {
- [OSMO_CC_REDIR_REASON_UNKNOWN] = "unknown",
- [OSMO_CC_REDIR_REASON_CFB] = "call forward busy",
- [OSMO_CC_REDIR_REASON_CFNR] = "call forward no response",
- [OSMO_CC_REDIR_REASON_CD] = "call deflect",
- [OSMO_CC_REDIR_REASON_CF_OUTOFORDER] = "call forward out of order",
- [OSMO_CC_REDIR_REASON_CF_BY_DTE] = "call froward by dte",
- [OSMO_CC_REDIR_REASON_CFU] = "call forward unconditional",
-};
-
-const char *osmo_cc_redir_reason_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_redir_reason_name)
-int osmo_cc_redir_reason_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_redir_reason_name)
-
-static const char *osmo_cc_notify_name[OSMO_CC_NOTIFY_NUM] = {
- [OSMO_CC_NOTIFY_USER_SUSPENDED] = "user suspended",
- [OSMO_CC_NOTIFY_USER_RESUMED] = "user resumed",
- [OSMO_CC_NOTIFY_BEARER_SERVICE_CHANGE] = "bearer service change",
- [OSMO_CC_NOTIFY_CALL_COMPLETION_DELAY] = "call completion delay",
- [OSMO_CC_NOTIFY_CONFERENCE_ESTABLISHED] = "conference established",
- [OSMO_CC_NOTIFY_CONFERENCE_DISCONNECTED] = "conference disconnected",
- [OSMO_CC_NOTIFY_OTHER_PARTY_ADDED] = "ohter party added",
- [OSMO_CC_NOTIFY_ISOLATED] = "isolated",
- [OSMO_CC_NOTIFY_REATTACHED] = "reattached",
- [OSMO_CC_NOTIFY_OTHER_PARTY_ISOLATED] = "ohter party isolated",
- [OSMO_CC_NOTIFY_OTHER_PARTY_REATTACHED] = "ohter party reattached",
- [OSMO_CC_NOTIFY_OTHER_PARTY_SPLIT] = "other party split",
- [OSMO_CC_NOTIFY_OTHER_PARTY_DISCONNECTED] = "other party disconnected",
- [OSMO_CC_NOTIFY_CONFERENCE_FLOATING] = "confernce floating",
- [OSMO_CC_NOTIFY_CONFERENCE_DISC_PREEMPT] = "confernce disconnect preemption",
- [OSMO_CC_NOTIFY_CONFERENCE_FLOATING_SUP] = "conference floating sup",
- [OSMO_CC_NOTIFY_CALL_IS_A_WAITING_CALL] = "call is a waiting call",
- [OSMO_CC_NOTIFY_DIVERSION_ACTIVATED] = "diversion activated",
- [OSMO_CC_NOTIFY_RESERVED_CT_1] = "reserved CT 1",
- [OSMO_CC_NOTIFY_RESERVED_CT_2] = "reserved CT 2",
- [OSMO_CC_NOTIFY_REVERSE_CHARGING] = "reverse charging",
- [OSMO_CC_NOTIFY_REMOTE_HOLD] = "remote hold",
- [OSMO_CC_NOTIFY_REMOTE_RETRIEVAL] = "remote retrieval",
- [OSMO_CC_NOTIFY_CALL_IS_DIVERTING] = "call is diverting",
-};
-
-const char *osmo_cc_notify_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_notify_name)
-int osmo_cc_notify_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_notify_name)
-
-static const char *osmo_cc_coding_name[OSMO_CC_CODING_NUM] = {
- [OSMO_CC_CODING_ITU_T] = "ITU-T",
- [OSMO_CC_CODING_ISO_IEC] = "ISO/IEC",
- [OSMO_CC_CODING_NATIONAL] = "national",
- [OSMO_CC_CODING_STANDARD_SPECIFIC] = "standard specific",
-};
-
-const char *osmo_cc_coding_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_coding_name)
-int osmo_cc_coding_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_coding_name)
-
-static const char *osmo_cc_isdn_cause_name[OSMO_CC_ISDN_CAUSE_NUM] = {
- [0] = "unset",
- [OSMO_CC_ISDN_CAUSE_UNASSIGNED_NR] = "unsassigned number",
- [OSMO_CC_ISDN_CAUSE_NO_ROUTE_TRANSIT] = "no route to transit network",
- [OSMO_CC_ISDN_CAUSE_NO_ROUTE] = "no route",
- [OSMO_CC_ISDN_CAUSE_CHAN_UNACCEPT] = "channel unacceptable",
- [OSMO_CC_ISDN_CAUSE_OP_DET_BARRING] = "detected barring",
- [OSMO_CC_ISDN_CAUSE_NORM_CALL_CLEAR] = "normal call clearing",
- [OSMO_CC_ISDN_CAUSE_USER_BUSY] = "user busy",
- [OSMO_CC_ISDN_CAUSE_USER_NOTRESPOND] = "user not responding",
- [OSMO_CC_ISDN_CAUSE_USER_ALERTING_NA] = "user does not answer",
- [OSMO_CC_ISDN_CAUSE_CALL_REJECTED] = "call rejected",
- [OSMO_CC_ISDN_CAUSE_NUMBER_CHANGED] = "number changed",
- [OSMO_CC_ISDN_CAUSE_PRE_EMPTION] = "pre-emption",
- [OSMO_CC_ISDN_CAUSE_NONSE_USER_CLR] = "non-selected user clearing",
- [OSMO_CC_ISDN_CAUSE_DEST_OOO] = "destination out-of-order",
- [OSMO_CC_ISDN_CAUSE_INV_NR_FORMAT] = "invalid number format",
- [OSMO_CC_ISDN_CAUSE_FACILITY_REJ] = "facility rejected",
- [OSMO_CC_ISDN_CAUSE_RESP_STATUS_INQ] = "response to status enquiery",
- [OSMO_CC_ISDN_CAUSE_NORMAL_UNSPEC] = "normal, uspecified",
- [OSMO_CC_ISDN_CAUSE_NO_CIRCUIT_CHAN] = "no circuit/channel available",
- [OSMO_CC_ISDN_CAUSE_NETWORK_OOO] = "network out of order",
- [OSMO_CC_ISDN_CAUSE_TEMP_FAILURE] = "temporary failure",
- [OSMO_CC_ISDN_CAUSE_SWITCH_CONG] = "switching equipment congested",
- [OSMO_CC_ISDN_CAUSE_ACC_INF_DISCARD] = "access information discarded",
- [OSMO_CC_ISDN_CAUSE_REQ_CHAN_UNAVAIL] = "requested circuit/channel unavailable",
- [OSMO_CC_ISDN_CAUSE_RESOURCE_UNAVAIL] = "resource unavailable",
- [OSMO_CC_ISDN_CAUSE_QOS_UNAVAIL] = "quality of service unavailable",
- [OSMO_CC_ISDN_CAUSE_REQ_FAC_NOT_SUBSC] = "requested facility not subscribed",
- [OSMO_CC_ISDN_CAUSE_INC_BARRED_CUG] = "inc barred in closed user group",
- [OSMO_CC_ISDN_CAUSE_BEARER_CAP_UNAUTH] = "bearer capability unauthorized",
- [OSMO_CC_ISDN_CAUSE_BEARER_CA_UNAVAIL] = "bearer capability not available",
- [OSMO_CC_ISDN_CAUSE_SERV_OPT_UNAVAIL] = "service or option not available",
- [OSMO_CC_ISDN_CAUSE_BEARERSERV_UNIMPL] = "bearer service unimplemented",
- [OSMO_CC_ISDN_CAUSE_ACM_GE_ACM_MAX] = "acm ge ach max",
- [OSMO_CC_ISDN_CAUSE_REQ_FAC_NOTIMPL] = "requrested facility not implemented",
- [OSMO_CC_ISDN_CAUSE_RESTR_BCAP_AVAIL] = "restricted bearer capabilitey available",
- [OSMO_CC_ISDN_CAUSE_SERV_OPT_UNIMPL] = "service or option unimplemented",
- [OSMO_CC_ISDN_CAUSE_INVAL_CALLREF] = "invalid call reference",
- [OSMO_CC_ISDN_CAUSE_USER_NOT_IN_CUG] = "user not in closed user group",
- [OSMO_CC_ISDN_CAUSE_INCOMPAT_DEST] = "incompatible destination",
- [OSMO_CC_ISDN_CAUSE_INVAL_TRANS_NET] = "invalid transit network",
- [OSMO_CC_ISDN_CAUSE_SEMANTIC_INCORR] = "semantically incorrect",
- [OSMO_CC_ISDN_CAUSE_INVAL_MAND_INF] = "invalid mandatory information",
- [OSMO_CC_ISDN_CAUSE_MSGTYPE_NOTEXIST] = "message type does not exist",
- [OSMO_CC_ISDN_CAUSE_MSGTYPE_INCOMPAT] = "message type incompatible",
- [OSMO_CC_ISDN_CAUSE_IE_NOTEXIST] = "informaton element does not exits",
- [OSMO_CC_ISDN_CAUSE_COND_IE_ERR] = "conditional information element error",
- [OSMO_CC_ISDN_CAUSE_MSG_INCOMP_STATE] = "message at incompatlible state",
- [OSMO_CC_ISDN_CAUSE_RECOVERY_TIMER] = "recovery on time expiery",
- [OSMO_CC_ISDN_CAUSE_PROTO_ERR] = "protocol error",
- [OSMO_CC_ISDN_CAUSE_INTERWORKING] = "interworking, unspecified",
-};
-
-const char *osmo_cc_isdn_cause_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_isdn_cause_name)
-int osmo_cc_isdn_cause_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_isdn_cause_name)
-
-static const char *osmo_cc_location_name[OSMO_CC_LOCATION_NUM] = {
- [OSMO_CC_LOCATION_USER] = "user",
- [OSMO_CC_LOCATION_PRIV_SERV_LOC_USER] = "private network serving local user",
- [OSMO_CC_LOCATION_PUB_SERV_LOC_USER] = "public network serving local user",
- [OSMO_CC_LOCATION_TRANSIT] = "transit network",
- [OSMO_CC_LOCATION_PUB_SERV_REM_USER] = "public network serving remote user",
- [OSMO_CC_LOCATION_PRIV_SERV_REM_USER] = "private network serving remote user",
- [OSMO_CC_LOCATION_BEYOND_INTERWORKING] = "beyond interworking",
-};
-
-const char *osmo_cc_location_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_location_name)
-int osmo_cc_location_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_location_name)
-
-static const char *osmo_cc_progress_name[OSMO_CC_PROGRESS_NUM] = {
- [OSMO_CC_PROGRESS_NOT_END_TO_END_ISDN] = "not end-to-end ISDN",
- [OSMO_CC_PROGRESS_DEST_NOT_ISDN] = "destination not ISDN",
- [OSMO_CC_PROGRESS_ORIG_NOT_ISDN] = "originator not ISDN",
- [OSMO_CC_PROGRESS_RETURN_TO_ISDN] = "return to ISDN",
- [OSMO_CC_PROGRESS_INTERWORKING] = "interworking",
- [OSMO_CC_PROGRESS_INBAND_INFO_AVAILABLE] = "inmand information available (audio)",
-};
-
-const char *osmo_cc_progress_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_progress_name)
-int osmo_cc_progress_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_progress_name)
-
-static const char *osmo_cc_capability_name[OSMO_CC_CAPABILITY_NUM] = {
- [OSMO_CC_CAPABILITY_SPEECH] = "speech",
- [OSMO_CC_CAPABILITY_DATA] = "data",
- [OSMO_CC_CAPABILITY_DATA_RESTRICTED] = "data restricted",
- [OSMO_CC_CAPABILITY_AUDIO] = "audio",
- [OSMO_CC_CAPABILITY_DATA_WITH_TONES] = "data with tones",
- [OSMO_CC_CAPABILITY_VIDEO] = "video",
-};
-
-const char *osmo_cc_capability_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_capability_name)
-int osmo_cc_capability_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_capability_name)
-
-static const char *osmo_cc_mode_name[OSMO_CC_MODE_NUM] = {
- [OSMO_CC_MODE_CIRCUIT] = "circuit",
- [OSMO_CC_MODE_PACKET] = "packet",
-};
-
-const char *osmo_cc_mode_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_mode_name)
-int osmo_cc_mode_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_mode_name)
-
-static const char *osmo_cc_dtmf_mode_name[OSMO_CC_DTMF_MODE_NUM] = {
- [OSMO_CC_DTMF_MODE_OFF] = "off",
- [OSMO_CC_DTMF_MODE_ON] = "on",
- [OSMO_CC_DTMF_MODE_DIGITS] = "digit",
-};
-
-const char *osmo_cc_dtmf_mode_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_dtmf_mode_name)
-int osmo_cc_dtmf_mode_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_dtmf_mode_name)
-
-static const char *osmo_cc_socket_cause_name[OSMO_CC_SOCKET_CAUSE_NUM] = {
- [0] = "unset",
- [OSMO_CC_SOCKET_CAUSE_VERSION_MISMATCH] = "version mismatch",
- [OSMO_CC_SOCKET_CAUSE_FAILED] = "socket failed",
- [OSMO_CC_SOCKET_CAUSE_BROKEN_PIPE] = "broken pipe",
- [OSMO_CC_SOCKET_CAUSE_TIMEOUT] = "keepalive timeout",
-};
-
-const char *osmo_cc_socket_cause_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_socket_cause_name)
-int osmo_cc_socket_cause_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_socket_cause_name)
-
-static const char *osmo_cc_network_name[OSMO_CC_NETWORK_NUM] = {
- [OSMO_CC_NETWORK_UNDEFINED] = "undefined",
- [OSMO_CC_NETWORK_ALSA_NONE] = "alsa",
- [OSMO_CC_NETWORK_POTS_NONE] = "pots",
- [OSMO_CC_NETWORK_ISDN_NONE] = "isdn",
- [OSMO_CC_NETWORK_SIP_NONE] = "sip",
- [OSMO_CC_NETWORK_GSM_IMSI] = "gsm-imsi",
- [OSMO_CC_NETWORK_GSM_IMEI] = "gsm-imei",
- [OSMO_CC_NETWORK_WEB_NONE] = "web",
- [OSMO_CC_NETWORK_DECT_NONE] = "decs",
- [OSMO_CC_NETWORK_BLUETOOTH_NONE] = "bluetooth",
- [OSMO_CC_NETWORK_SS5_NONE] = "ss5",
- [OSMO_CC_NETWORK_ANETZ_NONE] = "anetz",
- [OSMO_CC_NETWORK_BNETZ_MUENZ] = "bnetz",
- [OSMO_CC_NETWORK_CNETZ_NONE] = "cnetz",
- [OSMO_CC_NETWORK_NMT_NONE] = "nmt",
- [OSMO_CC_NETWORK_R2000_NONE] = "radiocom2000",
- [OSMO_CC_NETWORK_AMPS_ESN] = "amps",
- [OSMO_CC_NETWORK_MTS_NONE] = "mts",
- [OSMO_CC_NETWORK_IMTS_NONE] = "imts",
- [OSMO_CC_NETWORK_EUROSIGNAL_NONE] = "eurosignal",
- [OSMO_CC_NETWORK_JOLLYCOM_NONE] = "jollycom",
- [OSMO_CC_NETWORK_MPT1327_PSTN] = "mpt1327-pstn",
- [OSMO_CC_NETWORK_MPT1327_PBX] = "mpt1327-pbx",
-};
-
-const char *osmo_cc_network_value2name(int value) _OSMO_CC_VALUE2NAME(osmo_cc_network_name)
-int osmo_cc_network_name2value(const char *name) _OSMO_CC_NAME2VALUE(osmo_cc_network_name)
-
-/*
- *
- */
-
-static uint32_t new_callref = 0;
-
-uint32_t osmo_cc_new_callref(void)
-{
- return (++new_callref);
-}
-
-/* create message with maximum size */
-osmo_cc_msg_t *osmo_cc_new_msg(uint8_t msg_type)
-{
- osmo_cc_msg_t *msg;
-
- /* allocate message */
- msg = calloc(1, sizeof(*msg) + 65535);
- if (!msg) {
- PDEBUG(DCC, DEBUG_ERROR, "No memory\n");
- abort();
- }
- /* set message type and zero length */
- msg->type = msg_type;
- msg->length_networkorder = htons(0);
-
- return msg;
-}
-
-/* clone message */
-osmo_cc_msg_t *osmo_cc_clone_msg(osmo_cc_msg_t *msg)
-{
- osmo_cc_msg_t *new_msg;
-
- new_msg = osmo_cc_new_msg(msg->type);
- new_msg->length_networkorder = msg->length_networkorder;
- memcpy(new_msg->data, msg->data, ntohs(msg->length_networkorder));
-
- return new_msg;
-}
-
-osmo_cc_msg_t *osmo_cc_msg_list_dequeue(osmo_cc_msg_list_t **mlp, uint32_t *callref_p)
-{
- osmo_cc_msg_list_t *ml;
- osmo_cc_msg_t *msg;
-
- ml = *mlp;
- msg = ml->msg;
- if (callref_p)
- *callref_p = ml->callref;
- *mlp = ml->next;
- free(ml);
-
- return msg;
-}
-
-osmo_cc_msg_list_t *osmo_cc_msg_list_enqueue(osmo_cc_msg_list_t **mlp, osmo_cc_msg_t *msg, uint32_t callref)
-{
- osmo_cc_msg_list_t *ml;
-
- ml = calloc(1, sizeof(*ml));
- ml->msg = msg;
- ml->callref = callref;
- while (*mlp)
- mlp = &((*mlp)->next);
- *mlp = ml;
-
- return ml;
-}
-
-/* destroy message */
-void osmo_cc_free_msg(osmo_cc_msg_t *msg)
-{
- free(msg);
-}
-
-void osmo_cc_debug_ie(osmo_cc_msg_t *msg, int level)
-{
- uint16_t msg_len, len;
- uint8_t *p;
- osmo_cc_ie_t *ie;
- int rc;
- int ie_repeat[256];
- uint8_t type, plan, present, screen, coding, capability, mode, progress, reason, duration_ms, pause_ms, dtmf_mode, location, notify, isdn_cause, socket_cause;
- uint16_t sip_cause;
- uint32_t unique;
- char string[65536];
- int i;
-
- memset(ie_repeat, 0, sizeof(ie_repeat));
-
- msg_len = ntohs(msg->length_networkorder);
- p = msg->data;
-
- while (msg_len) {
- ie = (osmo_cc_ie_t *)p;
- /* check for minimum IE length */
- if (msg_len < sizeof(*ie)) {
- PDEBUG(DCC, level, "****** Rest of message is too short for an IE: value=%s\n", debug_hex(p, msg_len));
- return;
- }
- /* get actual IE length */
- len = ntohs(ie->length_networkorder);
- /* check if IE length does not exceed message */
- if (msg_len < sizeof(*ie) + len) {
- PDEBUG(DCC, level, "****** IE: type=0x%02x length=%d would exceed the rest length of message (%d bytes left)\n", ie->type, len, msg_len - (int)sizeof(*ie));
- return;
- }
- switch (ie->type) {
- case OSMO_CC_IE_CALLED:
- rc = osmo_cc_get_ie_called(msg, ie_repeat[ie->type], &type, &plan, string, sizeof(string));
- if (rc < 0)
- break;
- PDEBUG(DCC, level, " %s type=%d(%s) plan=%d(%s) number='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_type_value2name(type), plan, osmo_cc_plan_value2name(plan), string);
- break;
- case OSMO_CC_IE_CALLED_SUB:
- rc = osmo_cc_get_ie_called_sub(msg, ie_repeat[ie->type], &type, string, sizeof(string));
- if (rc < 0)
- break;
- PDEBUG(DCC, level, " %s type=%d(%s) number='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_type_value2name(type), string);
- break;
- case OSMO_CC_IE_CALLED_NAME:
- rc = osmo_cc_get_ie_called_name(msg, ie_repeat[ie->type], string, sizeof(string));
- if (rc < 0)
- break;
- PDEBUG(DCC, level, " %s name='%s'\n", osmo_cc_ie_value2name(ie->type), string);
- break;
- case OSMO_CC_IE_CALLED_INTERFACE:
- rc = osmo_cc_get_ie_called_interface(msg, ie_repeat[ie->type], string, sizeof(string));
- if (rc < 0)
- break;
- PDEBUG(DCC, level, " %s name='%s'\n", osmo_cc_ie_value2name(ie->type), string);
- break;
- case OSMO_CC_IE_COMPLETE:
- rc = osmo_cc_get_ie_complete(msg, ie_repeat[ie->type]);
- if (rc < 0)
- break;
- PDEBUG(DCC, level, " %s\n", osmo_cc_ie_value2name(ie->type));
- break;
- case OSMO_CC_IE_CALLING:
- rc = osmo_cc_get_ie_calling(msg, ie_repeat[ie->type], &type, &plan, &present, &screen, string, sizeof(string));
- if (rc < 0)
- break;
- PDEBUG(DCC, level, " %s type=%d(%s) plan=%d(%s), presentation=%d(%s), screening=%d(%s), number='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_type_value2name(type), plan, osmo_cc_plan_value2name(plan), present, osmo_cc_present_value2name(present), screen, osmo_cc_screen_value2name(screen), string);
- break;
- case OSMO_CC_IE_CALLING_SUB:
- rc = osmo_cc_get_ie_calling_sub(msg, ie_repeat[ie->type], &type, string, sizeof(string));
- if (rc < 0)
- break;
- PDEBUG(DCC, level, " %s type=%d(%s) number='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_type_value2name(type), string);
- break;
- case OSMO_CC_IE_CALLING_NAME:
- rc = osmo_cc_get_ie_calling_name(msg, ie_repeat[ie->type], string, sizeof(string));
- if (rc < 0)
- break;
- PDEBUG(DCC, level, " %s name='%s'\n", osmo_cc_ie_value2name(ie->type), string);
- break;
- case OSMO_CC_IE_CALLING_INTERFACE:
- rc = osmo_cc_get_ie_calling_interface(msg, ie_repeat[ie->type], string, sizeof(string));
- if (rc < 0)
- break;
- PDEBUG(DCC, level, " %s name='%s'\n", osmo_cc_ie_value2name(ie->type), string);
- break;
- case OSMO_CC_IE_CALLING_NETWORK:
- rc = osmo_cc_get_ie_calling_network(msg, ie_repeat[ie->type], &type, string, sizeof(string));
- if (rc < 0)
- break;
- PDEBUG(DCC, level, " %s type=%d(%s) id='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_network_value2name(type), string);
- break;
- case OSMO_CC_IE_BEARER:
- rc = osmo_cc_get_ie_bearer(msg, ie_repeat[ie->type], &coding, &capability, &mode);
- if (rc < 0)
- break;
- PDEBUG(DCC, level, " %s coding=%d(%s) capability=%d(%s) mode=%d(%s)\n", osmo_cc_ie_value2name(ie->type), coding, osmo_cc_coding_value2name(coding), capability, osmo_cc_capability_value2name(capability), mode, osmo_cc_mode_value2name(mode));
- break;
- case OSMO_CC_IE_REDIR:
- rc = osmo_cc_get_ie_redir(msg, ie_repeat[ie->type], &type, &plan, &present, &screen, &reason, string, sizeof(string));
- if (rc < 0)
- break;
- PDEBUG(DCC, level, " %s type=%d(%s) plan=%d(%s) presentation=%d(%s) screening=%d(%s) reason=%d(%s) number='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_type_value2name(type), plan, osmo_cc_plan_value2name(plan), present, osmo_cc_present_value2name(present), screen, osmo_cc_screen_value2name(screen), reason, osmo_cc_redir_reason_value2name(reason), string);
- break;
- case OSMO_CC_IE_DTMF:
- rc = osmo_cc_get_ie_dtmf(msg, ie_repeat[ie->type], &duration_ms, &pause_ms, &dtmf_mode, string, sizeof(string));
- if (rc < 0)
- break;
- PDEBUG(DCC, level, " %s duration=%dms pause=%dms mode=%d(%s)\n", osmo_cc_ie_value2name(ie->type), duration_ms, pause_ms, dtmf_mode, osmo_cc_dtmf_mode_value2name(dtmf_mode));
- break;
- case OSMO_CC_IE_KEYPAD:
- rc = osmo_cc_get_ie_keypad(msg, ie_repeat[ie->type], string, sizeof(string));
- if (rc < 0)
- break;
- PDEBUG(DCC, level, " %s digits='%s'\n", osmo_cc_ie_value2name(ie->type), string);
- break;
- case OSMO_CC_IE_PROGRESS:
- rc = osmo_cc_get_ie_progress(msg, ie_repeat[ie->type], &coding, &location, &progress);
- if (rc < 0)
- break;
- PDEBUG(DCC, level, " %s coding=%d(%s) location=%d(%s) progress=%d(%s)\n", osmo_cc_ie_value2name(ie->type), coding, osmo_cc_coding_value2name(coding), location, osmo_cc_location_value2name(location), progress, osmo_cc_progress_value2name(progress));
- break;
- case OSMO_CC_IE_NOTIFY:
- rc = osmo_cc_get_ie_notify(msg, ie_repeat[ie->type], &notify);
- if (rc < 0)
- break;
- PDEBUG(DCC, level, " %s indicator=%d(%s)\n", osmo_cc_ie_value2name(ie->type), notify, osmo_cc_notify_value2name(notify));
- break;
- case OSMO_CC_IE_CAUSE:
- rc = osmo_cc_get_ie_cause(msg, ie_repeat[ie->type], &location, &isdn_cause, &sip_cause, &socket_cause);
- if (rc < 0)
- break;
- PDEBUG(DCC, level, " %s location=%d(%s) isdn_cause=%d(%s) sip_cause=%d socket_cause=%d(%s)\n", osmo_cc_ie_value2name(ie->type), location, osmo_cc_location_value2name(location), isdn_cause, osmo_cc_isdn_cause_value2name(isdn_cause), sip_cause, socket_cause, osmo_cc_socket_cause_value2name(socket_cause));
- break;
- case OSMO_CC_IE_DISPLAY:
- rc = osmo_cc_get_ie_display(msg, ie_repeat[ie->type], string, sizeof(string));
- if (rc < 0)
- break;
- PDEBUG(DCC, level, " %s info='%s'\n", osmo_cc_ie_value2name(ie->type), string);
- break;
- case OSMO_CC_IE_SDP:
- rc = osmo_cc_get_ie_sdp(msg, ie_repeat[ie->type], string, sizeof(string));
- if (rc < 0)
- break;
- for (i = 0; string[i]; i++) {
- if (string[i] == '\r')
- string[i] = '\\';
- if (string[i] == '\n')
- string[i] = 'n';
- }
- PDEBUG(DCC, level, " %s payload=%s\n", osmo_cc_ie_value2name(ie->type), string);
- break;
- case OSMO_CC_IE_SOCKET_ADDRESS:
- rc = osmo_cc_get_ie_socket_address(msg, ie_repeat[ie->type], string, sizeof(string));
- if (rc < 0)
- break;
- PDEBUG(DCC, level, " %s address='%s'\n", osmo_cc_ie_value2name(ie->type), string);
- break;
- case OSMO_CC_IE_PRIVATE:
- rc = osmo_cc_get_ie_private(msg, ie_repeat[ie->type], &unique, (uint8_t *)string, sizeof(string));
- if (rc < 0)
- break;
- PDEBUG(DCC, level, " %s unique=%u=0x%08x private=%s\n", osmo_cc_ie_value2name(ie->type), unique, unique, debug_hex((uint8_t *)string, rc));
- break;
- default:
- PDEBUG(DCC, level, " %s type=0x%02x length=%d value=%s\n", osmo_cc_ie_value2name(ie->type), ie->type, len, debug_hex(ie->data, len));
- }
- ie_repeat[ie->type]++;
- p += sizeof(*ie) + len;
- msg_len -= sizeof(*ie) + len;
- }
-}
-
-/* search and return information element
- * we give the IE type we are searching for
- * we also give the repetition, to find IE that is repeated
- * the result is stored in *ie_data
- * the return length is the length that exceeds the given ie_len
- * if there is an error, a value < 0 is returned
- */
-int osmo_cc_get_ie_struct(osmo_cc_msg_t *msg, uint8_t ie_type, int ie_repeat, int ie_len, const osmo_cc_ie_t **ie_struct)
-{
- uint16_t msg_len, len;
- uint8_t *p;
- osmo_cc_ie_t *ie;
-
- msg_len = ntohs(msg->length_networkorder);
- p = msg->data;
-
- while (msg_len) {
- ie = (osmo_cc_ie_t *)p;
- /* check for minimum IE length */
- if (msg_len < sizeof(*ie)) {
- PDEBUG(DCC, DEBUG_ERROR, "MSG short read\n");
- osmo_cc_debug_ie(msg, DEBUG_ERROR);
- return -EINVAL;
- }
- /* get actual IE length */
- len = ntohs(ie->length_networkorder);
- /* check if IE length does not exceed message */
- if (msg_len < sizeof(*ie) + len) {
- PDEBUG(DCC, DEBUG_ERROR, "MSG short read\n");
- osmo_cc_debug_ie(msg, DEBUG_ERROR);
- return -EINVAL;
- }
- /* check if IE matches the one that is searched for */
- if (ie->type != ie_type) {
- p += sizeof(*ie) + len;
- msg_len -= sizeof(*ie) + len;
- continue;
- }
- /* check if IE repetition exists */
- if (ie_repeat) {
- --ie_repeat;
- p += sizeof(*ie) + len;
- msg_len -= sizeof(*ie) + len;
- continue;
- }
- /* return IE and indicate how many bytes we have more than the given length*/
- if (ntohs(ie->length_networkorder) < ie_len) {
- PDEBUG(DCC, DEBUG_ERROR, "IE 0x%02d has length of %d, but we expect it to have at least %d!\n", ie_type, ntohs(ie->length_networkorder), ie_len);
- return -EINVAL;
- }
- *ie_struct = ie;
- return ntohs(ie->length_networkorder) - ie_len;
- }
-
- /* IE not found */
- return -EINVAL;
-}
-
-/* as above, but return data of IE only */
-int osmo_cc_get_ie_data(osmo_cc_msg_t *msg, uint8_t ie_type, int ie_repeat, int ie_len, const void **ie_data)
-{
- const osmo_cc_ie_t *ie;
- int rc;
-
- rc = osmo_cc_get_ie_struct(msg, ie_type, ie_repeat, ie_len, &ie);
- if (rc >= 0)
- *ie_data = ie->data;
-
- return rc;
-}
-
-/* as above, but return 1 if IE exists */
-int osmo_cc_has_ie(osmo_cc_msg_t *msg, uint8_t ie_type, int ie_repeat)
-{
- const osmo_cc_ie_t *ie;
- int rc;
-
- rc = osmo_cc_get_ie_struct(msg, ie_type, ie_repeat, 0, &ie);
- if (rc >= 0)
- return 1;
-
- return 0;
-}
-
-/* remove IE from message */
-int osmo_cc_remove_ie(osmo_cc_msg_t *msg, uint8_t ie_type, int ie_repeat)
-{
- const osmo_cc_ie_t *ie;
- int rc;
- int msg_len, before_ie, ie_size, after_ie;
-
- rc = osmo_cc_get_ie_struct(msg, ie_type, ie_repeat, 0, &ie);
- if (rc < 0)
- return rc;
-
- msg_len = ntohs(msg->length_networkorder);
- before_ie = (void *)ie - (void *)msg->data;
- ie_size = sizeof(*ie) + ntohs(ie->length_networkorder);
- after_ie = msg_len - ie_size - before_ie;
- if (after_ie)
- memcpy(msg->data + before_ie, msg->data + before_ie + ie_size, after_ie);
- msg->length_networkorder = htons(msg_len - ie_size);
-
- return 0;
-}
-
-/* add information element
- * the type is given by ie_type and length is given by ie_len
- * the return value is a pointer to the data of the IE
- */
-void *osmo_cc_add_ie(osmo_cc_msg_t *msg, uint8_t ie_type, int ie_len)
-{
- uint16_t msg_len;
- int new_msg_len;
- uint8_t *p;
- osmo_cc_ie_t *ie;
-
- /* get pointer to first IE, if any */
- p = msg->data;
- /* expand messasge */
- msg_len = ntohs(msg->length_networkorder);
- new_msg_len = msg_len + sizeof(*ie) + ie_len;
- if (new_msg_len > 65535) {
- PDEBUG(DCC, DEBUG_ERROR, "MSG overflow\n");
- return NULL;
- }
- msg->length_networkorder = htons(new_msg_len);
- /* go to end of (unexpanded) message */
- ie = (osmo_cc_ie_t *)(p + msg_len);
- /* add ie */
- ie->type = ie_type;
- ie->length_networkorder = htons(ie_len);
- memset(ie->data, 0, ie_len); /* just in case there is something, but it shouldn't */
-
- return ie->data;
-}
-
-/* gets the information element's data that *iep points to and returns that ie.
- * if *iep points to msg->data, the first IE's data is returned. (must be set before first call.)
- * if *iep points to the end of the message, NULL is returned.
- * if there is no next IE, *iep is set to point to the end of message.
- */
-void *osmo_cc_msg_sep_ie(osmo_cc_msg_t *msg, void **iep, uint8_t *ie_type, uint16_t *ie_length)
-{
- uint16_t msg_len;
- osmo_cc_ie_t *ie;
-
- /* in case that *iep points to start of message, make it point to first IE */
- if (*iep == msg)
- *iep = msg->data;
- /* case IE */
- ie = *iep;
- /* check if it is NULL */
- if (ie == NULL)
- return NULL;
- /* check if it points to the end of message or there is not at least an IE header */
- msg_len = ntohs(msg->length_networkorder);
- if ((int)((uint8_t *)ie - msg->data) > (int)(msg_len - sizeof(*ie)))
- return NULL;
- /* increment iep and return IE */
- *ie_type = ie->type;
- *ie_length = ntohs(ie->length_networkorder);
- *iep = (uint8_t *)ie + sizeof(*ie) + *ie_length;
- return ie->data;
-}
-
-/* copy given block to given string with given size */
-static void _ie2string(char *string, size_t string_size, const char *ie_string, int ie_size)
-{
- int copy_size;
-
- copy_size = string_size - 1;
- if (ie_size < copy_size)
- copy_size = ie_size;
- memcpy(string, ie_string, copy_size);
- string[copy_size] = '\0';
-}
-
-/* helper to encode called party number (dialing) */
-void osmo_cc_add_ie_called(osmo_cc_msg_t *msg, uint8_t type, uint8_t plan, const char *dialing)
-{
- struct osmo_cc_ie_called *ie_called;
-
- ie_called = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLED, sizeof(*ie_called) + strlen(dialing));
- ie_called->type = type;
- ie_called->plan = plan;
- memcpy(ie_called->digits, dialing, strlen(dialing));
-}
-
-/* helper to decode called party number (dialing) */
-int osmo_cc_get_ie_called(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, uint8_t *plan, char *dialing, size_t dialing_size)
-{
- struct osmo_cc_ie_called *ie_called;
- int rc;
-
- rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLED, ie_repeat, sizeof(*ie_called), (const void **)&ie_called);
- if (rc < 0)
- return rc;
- *type = ie_called->type;
- *plan = ie_called->plan;
- _ie2string(dialing, dialing_size, ie_called->digits, rc);
- return rc;
-}
-
-/* helper to encode called party sub address (dialing) */
-void osmo_cc_add_ie_called_sub(osmo_cc_msg_t *msg, uint8_t type, const char *dialing)
-{
- struct osmo_cc_ie_called_sub *ie_called_sub;
-
- ie_called_sub = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLED_SUB, sizeof(*ie_called_sub) + strlen(dialing));
- ie_called_sub->type = type;
- memcpy(ie_called_sub->digits, dialing, strlen(dialing));
-}
-
-/* helper to decode called party sub address (dialing) */
-int osmo_cc_get_ie_called_sub(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, char *dialing, size_t dialing_size)
-{
- struct osmo_cc_ie_called_sub *ie_called_sub;
- int rc;
-
- rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLED_SUB, ie_repeat, sizeof(*ie_called_sub), (const void **)&ie_called_sub);
- if (rc < 0)
- return rc;
- *type = ie_called_sub->type;
- _ie2string(dialing, dialing_size, ie_called_sub->digits, rc);
- return rc;
-}
-
-/* helper to encode called party name (dialing) */
-void osmo_cc_add_ie_called_name(osmo_cc_msg_t *msg, const char *name)
-{
- struct osmo_cc_ie_called_name *ie_called_name;
-
- ie_called_name = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLED_NAME, sizeof(*ie_called_name) + strlen(name));
- memcpy(ie_called_name->name, name, strlen(name));
-}
-
-/* helper to decode called party name (dialing) */
-int osmo_cc_get_ie_called_name(osmo_cc_msg_t *msg, int ie_repeat, char *name, size_t name_size)
-{
- struct osmo_cc_ie_called_name *ie_called_name;
- int rc;
-
- rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLED_NAME, ie_repeat, sizeof(*ie_called_name), (const void **)&ie_called_name);
- if (rc < 0)
- return rc;
- _ie2string(name, name_size, ie_called_name->name, rc);
- return rc;
-}
-
-/* helper to encode called interface name */
-void osmo_cc_add_ie_called_interface(osmo_cc_msg_t *msg, const char *interface)
-{
- struct osmo_cc_ie_called_interface *ie_interface;
-
- ie_interface = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLED_INTERFACE, sizeof(*ie_interface) + strlen(interface));
- memcpy(ie_interface->name, interface, strlen(interface));
-}
-
-/* helper to decode called interface name */
-int osmo_cc_get_ie_called_interface(osmo_cc_msg_t *msg, int ie_repeat, char *interface, size_t interface_size)
-{
- struct osmo_cc_ie_called_interface *ie_interface;
- int rc;
-
- rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLED_INTERFACE, ie_repeat, sizeof(*ie_interface), (const void **)&ie_interface);
- if (rc < 0)
- return rc;
- _ie2string(interface, interface_size, ie_interface->name, rc);
- return rc;
-}
-
-/* helper to encode complete IE */
-void osmo_cc_add_ie_complete(osmo_cc_msg_t *msg)
-{
- osmo_cc_add_ie(msg, OSMO_CC_IE_COMPLETE, 0);
-}
-
-/* helper to decode complete IE */
-int osmo_cc_get_ie_complete(osmo_cc_msg_t *msg, int ie_repeat)
-{
- int rc;
- void *ie_complete;
-
- rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_COMPLETE, ie_repeat, 0, (const void **)&ie_complete);
- return rc;
-}
-
-/* helper to encode calling/connected party number (caller ID or connected ID) */
-void osmo_cc_add_ie_calling(osmo_cc_msg_t *msg, uint8_t type, uint8_t plan, uint8_t present, uint8_t screen, const char *callerid)
-{
- struct osmo_cc_ie_calling *ie_calling;
-
- ie_calling = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLING, sizeof(*ie_calling) + strlen(callerid));
- ie_calling->type = type;
- ie_calling->plan = plan;
- ie_calling->present = present;
- ie_calling->screen = screen;
- memcpy(ie_calling->digits, callerid, strlen(callerid));
-}
-
-/* helper to decode calling/connected party number (caller ID or connected ID) */
-int osmo_cc_get_ie_calling(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, uint8_t *plan, uint8_t *present, uint8_t *screen, char *callerid, size_t callerid_size)
-{
- struct osmo_cc_ie_calling *ie_calling;
- int rc;
-
- rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLING, ie_repeat, sizeof(*ie_calling), (const void **)&ie_calling);
- if (rc < 0)
- return rc;
- *type = ie_calling->type;
- *plan = ie_calling->plan;
- *present = ie_calling->present;
- *screen = ie_calling->screen;
- _ie2string(callerid, callerid_size, ie_calling->digits, rc);
- return rc;
-}
-
-/* helper to encode calling/connected sub address (caller ID or connected ID) */
-void osmo_cc_add_ie_calling_sub(osmo_cc_msg_t *msg, uint8_t type, const char *callerid)
-{
- struct osmo_cc_ie_calling_sub *ie_calling_sub;
-
- ie_calling_sub = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLING_SUB, sizeof(*ie_calling_sub) + strlen(callerid));
- ie_calling_sub->type = type;
- memcpy(ie_calling_sub->digits, callerid, strlen(callerid));
-}
-
-/* helper to decode calling/connected sub address (caller ID or connected ID) */
-int osmo_cc_get_ie_calling_sub(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, char *callerid, size_t callerid_size)
-{
- struct osmo_cc_ie_calling_sub *ie_calling_sub;
- int rc;
-
- rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLING_SUB, ie_repeat, sizeof(*ie_calling_sub), (const void **)&ie_calling_sub);
- if (rc < 0)
- return rc;
- *type = ie_calling_sub->type;
- _ie2string(callerid, callerid_size, ie_calling_sub->digits, rc);
- return rc;
-}
-
-/* helper to encode calling/connected name (caller ID or connected ID) */
-void osmo_cc_add_ie_calling_name(osmo_cc_msg_t *msg, const char *name)
-{
- struct osmo_cc_ie_calling_name *ie_calling_name;
-
- ie_calling_name = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLING_NAME, sizeof(*ie_calling_name) + strlen(name));
- memcpy(ie_calling_name->name, name, strlen(name));
-}
-
-/* helper to decode calling/connected name address (caller ID or connected ID) */
-int osmo_cc_get_ie_calling_name(osmo_cc_msg_t *msg, int ie_repeat, char *name, size_t name_size)
-{
- struct osmo_cc_ie_calling_name *ie_calling_name;
- int rc;
-
- rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLING_NAME, ie_repeat, sizeof(*ie_calling_name), (const void **)&ie_calling_name);
- if (rc < 0)
- return rc;
- _ie2string(name, name_size, ie_calling_name->name, rc);
- return rc;
-}
-
-/* helper to encode calling interface name */
-void osmo_cc_add_ie_calling_interface(osmo_cc_msg_t *msg, const char *interface)
-{
- struct osmo_cc_ie_calling_interface *ie_interface;
-
- ie_interface = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLING_INTERFACE, sizeof(*ie_interface) + strlen(interface));
- memcpy(ie_interface->name, interface, strlen(interface));
-}
-
-/* helper to decode calling interface name */
-int osmo_cc_get_ie_calling_interface(osmo_cc_msg_t *msg, int ie_repeat, char *interface, size_t interface_size)
-{
- struct osmo_cc_ie_calling_interface *ie_interface;
- int rc;
-
- rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLING_INTERFACE, ie_repeat, sizeof(*ie_interface), (const void **)&ie_interface);
- if (rc < 0)
- return rc;
- _ie2string(interface, interface_size, ie_interface->name, rc);
- return rc;
-}
-
-/* helper to encode network specific caller/connected ID */
-void osmo_cc_add_ie_calling_network(osmo_cc_msg_t *msg, uint8_t type, const char *networkid)
-{
- struct osmo_cc_ie_network *ie_network;
-
- ie_network = osmo_cc_add_ie(msg, OSMO_CC_IE_CALLING_NETWORK, sizeof(*ie_network) + strlen(networkid));
- ie_network->type = type;
- memcpy(ie_network->id, networkid, strlen(networkid));
-}
-
-/* helper to encode network specific caller/connected ID */
-int osmo_cc_get_ie_calling_network(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, char *networkid, size_t networkid_size)
-{
- struct osmo_cc_ie_network *ie_network;
- int rc;
-
- rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CALLING_NETWORK, ie_repeat, sizeof(*ie_network), (const void **)&ie_network);
- if (rc < 0)
- return rc;
- *type = ie_network->type;
- _ie2string(networkid, networkid_size, ie_network->id, rc);
- return rc;
-}
-
-/* helper to encode bearer capability */
-void osmo_cc_add_ie_bearer(osmo_cc_msg_t *msg, uint8_t coding, uint8_t capability, uint8_t mode)
-{
- struct osmo_cc_ie_bearer *ie_bearer;
-
- ie_bearer = osmo_cc_add_ie(msg, OSMO_CC_IE_BEARER, sizeof(*ie_bearer));
- ie_bearer->coding = coding;
- ie_bearer->capability = capability;
- ie_bearer->mode = mode;
-}
-
-/* helper to decode bearer capability */
-int osmo_cc_get_ie_bearer(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *coding, uint8_t *capability, uint8_t *mode)
-{
- struct osmo_cc_ie_bearer *ie_bearer;
- int rc;
-
- rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_BEARER, ie_repeat, sizeof(*ie_bearer), (const void **)&ie_bearer);
- if (rc < 0)
- return rc;
- *coding = ie_bearer->coding;
- *capability = ie_bearer->capability;
- *mode = ie_bearer->mode;
- return rc;
-}
-
-/* helper to encode redirection and redirecting number */
-void osmo_cc_add_ie_redir(osmo_cc_msg_t *msg, uint8_t type, uint8_t plan, uint8_t present, uint8_t screen, uint8_t redir_reason, const char *callerid)
-{
- struct osmo_cc_ie_redir *ie_redir;
-
- ie_redir = osmo_cc_add_ie(msg, OSMO_CC_IE_REDIR, sizeof(*ie_redir) + strlen(callerid));
- ie_redir->type = type;
- ie_redir->plan = plan;
- ie_redir->present = present;
- ie_redir->screen = screen;
- ie_redir->redir_reason = redir_reason;
- memcpy(ie_redir->digits, callerid, strlen(callerid));
-}
-
-/* helper to decode redirection and redirecting number */
-int osmo_cc_get_ie_redir(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *type, uint8_t *plan, uint8_t *present, uint8_t *screen, uint8_t *reason, char *callerid, size_t callerid_size)
-{
- struct osmo_cc_ie_redir *ie_redir;
- int rc;
-
- rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_REDIR, ie_repeat, sizeof(*ie_redir), (const void **)&ie_redir);
- if (rc < 0)
- return rc;
- *type = ie_redir->type;
- *plan = ie_redir->plan;
- *present = ie_redir->present;
- *screen = ie_redir->screen;
- *reason = ie_redir->redir_reason;
- _ie2string(callerid, callerid_size, ie_redir->digits, rc);
- return rc;
-}
-
-/* helper to encode DTMF tones */
-void osmo_cc_add_ie_dtmf(osmo_cc_msg_t *msg, uint8_t duration_ms, uint8_t pause_ms, uint8_t dtmf_mode, const char *digits)
-{
- struct osmo_cc_ie_dtmf *ie_dtmf;
-
- ie_dtmf = osmo_cc_add_ie(msg, OSMO_CC_IE_DTMF, sizeof(*ie_dtmf) + strlen(digits));
- ie_dtmf->duration_ms = duration_ms;
- ie_dtmf->pause_ms = pause_ms;
- ie_dtmf->dtmf_mode = dtmf_mode;
- memcpy(ie_dtmf->digits, digits, strlen(digits));
-}
-
-/* helper to decode DTMF tones */
-int osmo_cc_get_ie_dtmf(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *duration_ms, uint8_t *pause_ms, uint8_t *dtmf_mode, char *digits, size_t digits_size)
-{
- struct osmo_cc_ie_dtmf *ie_dtmf;
- int rc;
-
- rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_DTMF, ie_repeat, sizeof(*ie_dtmf), (const void **)&ie_dtmf);
- if (rc < 0)
- return rc;
- *duration_ms = ie_dtmf->duration_ms;
- *pause_ms = ie_dtmf->pause_ms;
- *dtmf_mode = ie_dtmf->dtmf_mode;
- _ie2string(digits, digits_size, ie_dtmf->digits, rc);
- return rc;
-}
-
-/* helper to encode keypad press */
-void osmo_cc_add_ie_keypad(osmo_cc_msg_t *msg, const char *digits)
-{
- struct osmo_cc_ie_keypad *ie_keypad;
-
- ie_keypad = osmo_cc_add_ie(msg, OSMO_CC_IE_KEYPAD, sizeof(*ie_keypad) + strlen(digits));
- memcpy(ie_keypad->digits, digits, strlen(digits));
-}
-
-/* helper to decode keypad press */
-int osmo_cc_get_ie_keypad(osmo_cc_msg_t *msg, int ie_repeat, char *digits, size_t digits_size)
-{
- struct osmo_cc_ie_keypad *ie_keypad;
- int rc;
-
- rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_KEYPAD, ie_repeat, sizeof(*ie_keypad), (const void **)&ie_keypad);
- if (rc < 0)
- return rc;
- _ie2string(digits, digits_size, ie_keypad->digits, rc);
- return rc;
-}
-
-/* helper to encode call progress information */
-void osmo_cc_add_ie_progress(osmo_cc_msg_t *msg, uint8_t coding, uint8_t location, uint8_t progress)
-{
- struct osmo_cc_ie_progress *ie_progress;
-
- ie_progress = osmo_cc_add_ie(msg, OSMO_CC_IE_PROGRESS, sizeof(*ie_progress));
- ie_progress->coding = coding;
- ie_progress->location = location;
- ie_progress->progress = progress;
-}
-
-/* helper to decode call progress information */
-int osmo_cc_get_ie_progress(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *coding, uint8_t *location, uint8_t *progress)
-{
- struct osmo_cc_ie_progress *ie_progress;
- int rc;
-
- rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_PROGRESS, ie_repeat, sizeof(*ie_progress), (const void **)&ie_progress);
- if (rc < 0)
- return rc;
- *coding = ie_progress->coding;
- *location = ie_progress->location;
- *progress = ie_progress->progress;
- return rc;
-}
-
-/* helper to encode notification */
-void osmo_cc_add_ie_notify(osmo_cc_msg_t *msg, uint8_t notify)
-{
- struct osmo_cc_ie_notify *ie_notify;
-
- ie_notify = osmo_cc_add_ie(msg, OSMO_CC_IE_NOTIFY, sizeof(*ie_notify));
- ie_notify->notify = notify;
-}
-
-/* helper to decode notification */
-int osmo_cc_get_ie_notify(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *notify)
-{
- struct osmo_cc_ie_notify *ie_notify;
- int rc;
-
- rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_NOTIFY, ie_repeat, sizeof(*ie_notify), (const void **)&ie_notify);
- if (rc < 0)
- return rc;
- *notify = ie_notify->notify;
- return rc;
-}
-
-/* helper to encode cause */
-void osmo_cc_add_ie_cause(osmo_cc_msg_t *msg, uint8_t location, uint8_t isdn_cause, uint16_t sip_cause, uint8_t socket_cause)
-{
- struct osmo_cc_ie_cause *ie_cause;
-
- ie_cause = osmo_cc_add_ie(msg, OSMO_CC_IE_CAUSE, sizeof(*ie_cause));
- ie_cause->location = location;
- ie_cause->isdn_cause = isdn_cause;
- ie_cause->sip_cause_networkorder = htons(sip_cause);
- ie_cause->socket_cause = socket_cause;
-}
-
-/* helper to deccode cause */
-int osmo_cc_get_ie_cause(osmo_cc_msg_t *msg, int ie_repeat, uint8_t *location, uint8_t *isdn_cause, uint16_t *sip_cause, uint8_t *socket_cause)
-{
- struct osmo_cc_ie_cause *ie_cause;
- int rc;
-
- rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_CAUSE, ie_repeat, sizeof(*ie_cause), (const void **)&ie_cause);
- if (rc < 0)
- return rc;
- *location = ie_cause->location;
- *isdn_cause = ie_cause->isdn_cause;
- *sip_cause = ntohs(ie_cause->sip_cause_networkorder);
- *socket_cause = ie_cause->socket_cause;
- return rc;
-}
-
-/* helper to encode DISPLAY information */
-void osmo_cc_add_ie_display(osmo_cc_msg_t *msg, const char *text)
-{
- struct osmo_cc_ie_display *ie_display;
-
- ie_display = osmo_cc_add_ie(msg, OSMO_CC_IE_DISPLAY, sizeof(*ie_display) + strlen(text));
- memcpy(ie_display->text, text, strlen(text));
-}
-
-/* helper to decode DISPLAY information */
-int osmo_cc_get_ie_display(osmo_cc_msg_t *msg, int ie_repeat, char *text, size_t text_size)
-{
- struct osmo_cc_ie_display *ie_display;
- int rc;
-
- rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_DISPLAY, ie_repeat, sizeof(*ie_display), (const void **)&ie_display);
- if (rc < 0)
- return rc;
- _ie2string(text, text_size, ie_display->text, rc);
- return rc;
-}
-
-/* helper to encode SDP */
-void osmo_cc_add_ie_sdp(osmo_cc_msg_t *msg, const char *sdp)
-{
- struct osmo_cc_ie_sdp *ie_sdp;
-
- ie_sdp = osmo_cc_add_ie(msg, OSMO_CC_IE_SDP, sizeof(*ie_sdp) + strlen(sdp));
- memcpy(ie_sdp->sdp, sdp, strlen(sdp));
-}
-
-/* helper to decode SDP */
-int osmo_cc_get_ie_sdp(osmo_cc_msg_t *msg, int ie_repeat, char *sdp, size_t sdp_size)
-{
- struct osmo_cc_ie_sdp *ie_sdp;
- int rc;
-
- rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_SDP, ie_repeat, sizeof(*ie_sdp), (const void **)&ie_sdp);
- if (rc < 0)
- return rc;
- _ie2string(sdp, sdp_size, ie_sdp->sdp, rc);
- return rc;
-}
-
-/* helper to encode socket address */
-void osmo_cc_add_ie_socket_address(osmo_cc_msg_t *msg, const char *address)
-{
- struct osmo_cc_ie_socket_address *ie_socket_address;
-
- ie_socket_address = osmo_cc_add_ie(msg, OSMO_CC_IE_SOCKET_ADDRESS, sizeof(*ie_socket_address) + strlen(address));
- memcpy(ie_socket_address->address, address, strlen(address));
-}
-
-/* helper to decode socket address */
-int osmo_cc_get_ie_socket_address(osmo_cc_msg_t *msg, int ie_repeat, char *address, size_t address_size)
-{
- struct osmo_cc_ie_socket_address *ie_socket_address;
- int rc;
-
- rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_SOCKET_ADDRESS, ie_repeat, sizeof(*ie_socket_address), (const void **)&ie_socket_address);
- if (rc < 0)
- return rc;
- _ie2string(address, address_size, ie_socket_address->address, rc);
- return rc;
-}
-
-/* helper to encode private information element */
-void osmo_cc_add_ie_private(osmo_cc_msg_t *msg, uint32_t unique, const uint8_t *data, size_t data_size)
-{
- struct osmo_cc_ie_private *ie_private;
-
- ie_private = osmo_cc_add_ie(msg, OSMO_CC_IE_PRIVATE, sizeof(*ie_private) + data_size);
- ie_private->unique_networkorder = htonl(unique);
- memcpy(ie_private->data, data, data_size);
-}
-
-/* helper to decode private information element */
-int osmo_cc_get_ie_private(osmo_cc_msg_t *msg, int ie_repeat, uint32_t *unique, uint8_t *data, size_t data_size)
-{
- struct osmo_cc_ie_private *ie_private;
- int rc;
-
- rc = osmo_cc_get_ie_data(msg, OSMO_CC_IE_PRIVATE, ie_repeat, sizeof(*ie_private), (const void **)&ie_private);
- if (rc < 0)
- return rc;
- *unique = ntohl(ie_private->unique_networkorder);
- if (rc > (int)data_size)
- rc = data_size;
- memcpy(data, ie_private->data, rc);
- return rc;
-}
-
diff --git a/src/libosmocc/message.h b/src/libosmocc/message.h
deleted file mode 100644
index da46435..0000000
--- a/src/libosmocc/message.h
+++ /dev/null
@@ -1,512 +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_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 fc70748..0000000
--- a/src/libosmocc/rtp.c
+++ /dev/null
@@ -1,404 +0,0 @@
-/* Osmo-CC: RTP handling
- *
- * (C) 2016 by Andreas Eversberg <jolly@eversberg.eu>
- * All Rights Reserved
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include "../libdebug/debug.h"
-#include "../libtimer/timer.h"
-#include "endpoint.h"
-
-#define RTP_VERSION 2
-
-void osmo_cc_set_rtp_ports(osmo_cc_session_config_t *conf, uint16_t from, uint16_t to)
-{
- conf->rtp_port_next = from;
- conf->rtp_port_from = from;
- conf->rtp_port_to = to;
-}
-
-struct rtp_hdr {
- uint8_t byte0;
- uint8_t byte1;
- uint16_t sequence;
- uint32_t timestamp;
- uint32_t ssrc;
-} __attribute__((packed));
-
-struct rtp_x_hdr {
- uint16_t by_profile;
- uint16_t length;
-} __attribute__((packed));
-
-static int rtp_receive(int sock, uint8_t **payload_p, int *payload_len_p, uint8_t *marker_p, uint8_t *pt_p, uint16_t *sequence_p, uint32_t *timestamp_p, uint32_t *ssrc_p)
-{
- static uint8_t data[2048];
- int len;
- struct rtp_hdr *rtph = (struct rtp_hdr *)data;
- uint8_t version, padding, extension, csrc_count, marker, payload_type;
- struct rtp_x_hdr *rtpxh;
- uint8_t *payload;
- int payload_len;
- int x_len;
-
- len = read(sock, data, sizeof(data));
- if (len < 0) {
- if (errno == EAGAIN)
- return -EAGAIN;
- PDEBUG(DCC, DEBUG_DEBUG, "Read errno = %d (%s)\n", errno, strerror(errno));
- return -EIO;
- }
- if (len < 12) {
- PDEBUG(DCC, DEBUG_NOTICE, "Received RTP frame too short (len = %d).\n", len);
- return -EINVAL;
- }
-
- version = rtph->byte0 >> 6;
- padding = (rtph->byte0 >> 5) & 1;
- extension = (rtph->byte0 >> 4) & 1;
- csrc_count = rtph->byte0 & 0x0f;
- marker = rtph->byte1 >> 7;
- payload_type = rtph->byte1 & 0x7f;
- *sequence_p = ntohs(rtph->sequence);
- *timestamp_p = ntohl(rtph->timestamp);
- *ssrc_p = ntohl(rtph->ssrc);
-
- if (version != RTP_VERSION) {
- PDEBUG(DCC, DEBUG_NOTICE, "Received RTP version %d not supported.\n", version);
- return -EINVAL;
- }
-
- payload = data + sizeof(*rtph) + (csrc_count << 2);
- payload_len = len - sizeof(*rtph) - (csrc_count << 2);
- if (payload_len < 0) {
- PDEBUG(DCC, DEBUG_NOTICE, "Received RTP frame too short (len = %d, csrc count = %d).\n", len, csrc_count);
- return -EINVAL;
- }
-
- if (extension) {
- if (payload_len < (int)sizeof(*rtpxh)) {
- PDEBUG(DCC, DEBUG_NOTICE, "Received RTP frame too short for extension header.\n");
- return -EINVAL;
- }
- rtpxh = (struct rtp_x_hdr *)payload;
- x_len = ntohs(rtpxh->length) * 4 + sizeof(*rtpxh);
- payload += x_len;
- payload_len -= x_len;
- if (payload_len < (int)sizeof(*rtpxh)) {
- PDEBUG(DCC, DEBUG_NOTICE, "Received RTP frame too short, extension header exceeds frame length.\n");
- return -EINVAL;
- }
- }
-
- if (padding) {
- if (payload_len < 1) {
- PDEBUG(DCC, DEBUG_NOTICE, "Received RTP frame too short for padding length.\n");
- return -EINVAL;
- }
- payload_len -= payload[payload_len - 1];
- if (payload_len < 0) {
- PDEBUG(DCC, DEBUG_NOTICE, "Received RTP frame padding is greater than payload.\n");
- return -EINVAL;
- }
- }
-
- *payload_p = payload;
- *payload_len_p = payload_len;
- *marker_p = marker;
- *pt_p = payload_type;
-
- return 0;
-}
-
-static void rtp_send(int sock, uint8_t *payload, int payload_len, uint8_t marker, uint8_t pt, uint16_t sequence, uint32_t timestamp, uint32_t ssrc)
-{
- struct rtp_hdr *rtph;
- char data[sizeof(*rtph) + payload_len];
- int len, rc;
-
- rtph = (struct rtp_hdr *)data;
- len = sizeof(*rtph);
- rtph->byte0 = RTP_VERSION << 6;
- rtph->byte1 = pt | (marker << 7);
- rtph->sequence = htons(sequence);
- rtph->timestamp = htonl(timestamp);
- rtph->ssrc = htonl(ssrc);
- len += payload_len;
- if (len > (int)sizeof(data)) {
- PDEBUG(DCC, DEBUG_NOTICE, "Buffer overflow, please fix!.\n");
- abort();
- }
- memcpy(data + sizeof(*rtph), payload, payload_len);
-
- rc = write(sock, data, len);
- if (rc < 0)
- PDEBUG(DCC, DEBUG_DEBUG, "Write errno = %d (%s)\n", errno, strerror(errno));
-}
-
-/* open and bind RTP
- * set local port to what we bound
- */
-int osmo_cc_rtp_open(osmo_cc_session_media_t *media)
-{
- osmo_cc_session_config_t *conf = media->session->config;
- int domain = 0; // make GCC happy
- uint16_t start_port;
- struct sockaddr_storage sa;
- int slen = 0; // make GCC happy
- struct sockaddr_in6 *sa6;
- struct sockaddr_in *sa4;
- uint16_t *sport;
- int flags;
- int rc;
-
- media->tx_ssrc = rand();
-
- osmo_cc_rtp_close(media);
-
- switch (media->connection_data_local.addrtype) {
- case osmo_cc_session_addrtype_ipv4:
- domain = AF_INET;
- memset(&sa, 0, sizeof(sa));
- sa4 = (struct sockaddr_in *)&sa;
- sa4->sin_family = domain;
- rc = inet_pton(AF_INET, media->connection_data_local.address, &sa4->sin_addr);
- if (rc < 1) {
-pton_error:
- PDEBUG(DCC, DEBUG_NOTICE, "Cannot bind to address '%s'.\n", media->connection_data_local.address);
- return -EINVAL;
- }
- sport = &sa4->sin_port;
- slen = sizeof(*sa4);
- break;
- case osmo_cc_session_addrtype_ipv6:
- domain = AF_INET6;
- memset(&sa, 0, sizeof(sa));
- sa6 = (struct sockaddr_in6 *)&sa;
- sa6->sin6_family = domain;
- rc = inet_pton(AF_INET6, media->connection_data_local.address, &sa6->sin6_addr);
- if (rc < 1)
- goto pton_error;
- sport = &sa6->sin6_port;
- slen = sizeof(*sa6);
- break;
- case osmo_cc_session_addrtype_unknown:
- PDEBUG(DCC, DEBUG_NOTICE, "Unsupported address type '%s'.\n", media->connection_data_local.addrtype_name);
- return -EINVAL;
- }
-
- /* rtp_port_from/rtp_port_to may be changed at run time, so rtp_port_next can become out of range. */
- if (conf->rtp_port_next < conf->rtp_port_from || conf->rtp_port_next > conf->rtp_port_to)
- conf->rtp_port_next = conf->rtp_port_from;
- start_port = conf->rtp_port_next;
- while (1) {
- /* open sockets */
- rc = socket(domain, SOCK_DGRAM, IPPROTO_UDP);
- if (rc < 0) {
-socket_error:
- PDEBUG(DCC, DEBUG_ERROR, "Cannot create socket (domain=%d, errno=%d(%s))\n", domain, errno, strerror(errno));
- osmo_cc_rtp_close(media);
- return -EIO;
- }
- media->rtp_socket = rc;
- rc = socket(domain, SOCK_DGRAM, IPPROTO_UDP);
- if (rc < 0)
- goto socket_error;
- media->rtcp_socket = rc;
-
- /* bind sockets */
- *sport = htons(conf->rtp_port_next);
- rc = bind(media->rtp_socket, (struct sockaddr *)&sa, slen);
- if (rc < 0) {
-bind_error:
- osmo_cc_rtp_close(media);
- conf->rtp_port_next = (conf->rtp_port_next + 2 > conf->rtp_port_to) ? conf->rtp_port_from : conf->rtp_port_next + 2;
- if (conf->rtp_port_next == start_port) {
- PDEBUG(DCC, DEBUG_ERROR, "Cannot bind socket (errno=%d(%s))\n", errno, strerror(errno));
- return -EIO;
- }
- continue;
- }
- *sport = htons(conf->rtp_port_next + 1);
- rc = bind(media->rtcp_socket, (struct sockaddr *)&sa, slen);
- if (rc < 0)
- goto bind_error;
- media->description.port_local = conf->rtp_port_next;
- conf->rtp_port_next = (conf->rtp_port_next + 2 > conf->rtp_port_to) ? conf->rtp_port_from : conf->rtp_port_next + 2;
- /* set nonblocking io */
- flags = fcntl(media->rtp_socket, F_GETFL);
- flags |= O_NONBLOCK;
- fcntl(media->rtp_socket, F_SETFL, flags);
- flags = fcntl(media->rtcp_socket, F_GETFL);
- flags |= O_NONBLOCK;
- fcntl(media->rtcp_socket, F_SETFL, flags);
- break;
- }
-
- PDEBUG(DCC, DEBUG_DEBUG, "Opening media port %d\n", media->description.port_local);
-
- return 0;
-}
-
-/* connect RTP
- * use remote port to connect to
- */
-int osmo_cc_rtp_connect(osmo_cc_session_media_t *media)
-{
- struct sockaddr_storage sa;
- int slen = 0; // make GCC happy
- struct sockaddr_in6 *sa6;
- struct sockaddr_in *sa4;
- uint16_t *sport;
- int rc;
-
- PDEBUG(DCC, DEBUG_DEBUG, "Connecting media port %d->%d\n", media->description.port_local, media->description.port_remote);
-
- switch (media->connection_data_remote.addrtype) {
- case osmo_cc_session_addrtype_ipv4:
- memset(&sa, 0, sizeof(sa));
- sa4 = (struct sockaddr_in *)&sa;
- sa4->sin_family = AF_INET;
- rc = inet_pton(AF_INET, media->connection_data_remote.address, &sa4->sin_addr);
- if (rc < 1) {
-pton_error:
- PDEBUG(DCC, DEBUG_NOTICE, "Cannot connect to address '%s'.\n", media->connection_data_remote.address);
- return -EINVAL;
- }
- sport = &sa4->sin_port;
- slen = sizeof(*sa4);
- break;
- case osmo_cc_session_addrtype_ipv6:
- memset(&sa, 0, sizeof(sa));
- sa6 = (struct sockaddr_in6 *)&sa;
- sa6->sin6_family = AF_INET6;
- rc = inet_pton(AF_INET6, media->connection_data_remote.address, &sa6->sin6_addr);
- if (rc < 1)
- goto pton_error;
- sport = &sa6->sin6_port;
- slen = sizeof(*sa6);
- break;
- case osmo_cc_session_addrtype_unknown:
- PDEBUG(DCC, DEBUG_NOTICE, "Unsupported address type '%s'.\n", media->connection_data_local.addrtype_name);
- return -EINVAL;
- }
-
- *sport = htons(media->description.port_remote);
- rc = connect(media->rtp_socket, (struct sockaddr *)&sa, slen);
- if (rc < 0) {
-connect_error:
- PDEBUG(DCC, DEBUG_NOTICE, "Cannot connect to address '%s'.\n", media->connection_data_remote.address);
- osmo_cc_rtp_close(media);
- return -EIO;
- }
- *sport = htons(media->description.port_remote + 1);
- rc = connect(media->rtcp_socket, (struct sockaddr *)&sa, slen);
- if (rc < 0)
- goto connect_error;
-
- return 0;
-}
-
-/* send rtp data with given codec */
-void osmo_cc_rtp_send(osmo_cc_session_codec_t *codec, uint8_t *data, int len, uint8_t marker, int inc_sequence, int inc_timestamp, void *priv)
-{
- uint8_t *payload = NULL;
- int payload_len = 0;
-
- if (!codec || !codec->media->rtp_socket)
- return;
-
- if (codec->encoder)
- codec->encoder(data, len, &payload, &payload_len, priv);
- else {
- payload = data;
- payload_len = len;
- }
-
- rtp_send(codec->media->rtp_socket, payload, payload_len, marker, codec->payload_type_remote, codec->media->tx_sequence, codec->media->tx_timestamp, codec->media->tx_ssrc);
- codec->media->tx_sequence += inc_sequence;
- codec->media->tx_timestamp += inc_timestamp;
-
- if (codec->encoder)
- free(payload);
-}
-
-/* receive rtp data for given media, return < 0, if there is nothing this time */
-int osmo_cc_rtp_receive(osmo_cc_session_media_t *media, void *priv)
-{
- int rc;
- uint8_t *payload = NULL;
- int payload_len = 0;
- uint8_t marker;
- uint8_t payload_type;
- osmo_cc_session_codec_t *codec;
- uint8_t *data;
- int len;
-
- if (!media || media->rtp_socket <= 0)
- return -EIO;
-
- rc = rtp_receive(media->rtp_socket, &payload, &payload_len, &marker, &payload_type, &media->rx_sequence, &media->rx_timestamp, &media->rx_ssrc);
- if (rc < 0)
- return rc;
-
- /* search for codec */
- for (codec = media->codec_list; codec; codec = codec->next) {
-
- if (codec->payload_type_local == payload_type)
- break;
- }
- if (!codec) {
- PDEBUG(DCC, DEBUG_NOTICE, "Received RTP frame for unknown codec (payload_type = %d).\n", payload_type);
- return 0;
- }
-
- if (codec->decoder)
- codec->decoder(payload, payload_len, &data, &len, 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;
-}
-
-void osmo_cc_rtp_close(osmo_cc_session_media_t *media)
-{
- if (media->rtp_socket) {
- close(media->rtp_socket);
- media->rtp_socket = 0;
- }
- if (media->rtcp_socket) {
- close(media->rtcp_socket);
- media->rtcp_socket = 0;
- }
-}
-
diff --git a/src/libosmocc/rtp.h b/src/libosmocc/rtp.h
deleted file mode 100644
index f6e5632..0000000
--- a/src/libosmocc/rtp.h
+++ /dev/null
@@ -1,8 +0,0 @@
-
-void osmo_cc_set_rtp_ports(osmo_cc_session_config_t *conf, uint16_t from, uint16_t to);
-int osmo_cc_rtp_open(osmo_cc_session_media_t *media);
-int osmo_cc_rtp_connect(osmo_cc_session_media_t *media);
-void osmo_cc_rtp_send(osmo_cc_session_codec_t *codec, uint8_t *data, int len, uint8_t marker, int inc_sequence, int inc_timestamp, void *priv);
-int osmo_cc_rtp_receive(osmo_cc_session_media_t *media, 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 5558f42..0000000
--- a/src/libosmocc/screen.c
+++ /dev/null
@@ -1,693 +0,0 @@
-/* Endpoint and call process handling
- *
- * (C) 2019 by Andreas Eversberg <jolly@eversberg.eu>
- * All Rights Reserved
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#include "../libtimer/timer.h"
-#include "../libdebug/debug.h"
-#include "endpoint.h"
-#include "message.h"
-
-#define SCREEN_QUESTIONMARK 1
-#define SCREEN_STAR 2
-#define SCREEN_AT 3
-
-void osmo_cc_help_screen(void)
-{
- printf("Screening options:\n\n");
-
- printf("screen-calling-in [attrs] <current caller ID> [attrs] <new caller ID>\n");
- printf("screen-called-in [attrs] <current dialed number> [attrs] <new dialed number>\n");
- printf("screen-calling-out [attrs] <current caller ID> [attrs] <new caller ID>\n");
- printf("screen-called-out [attrs] <current dialed number> [attrs] <new dialed number>\n\n");
-
- printf("These options allow to screen an incoming or outgoing caller ID or dialed\n");
- printf("number. If 'the current caller ID' or 'current dialed number' matches, it will\n");
- printf("be replaced by 'new caller ID' or 'new dialed number'. 'incoming' means from\n");
- printf(" the interface and 'outgoing' means towards the interface.\n\n");
-
- printf("Attributes prior 'current caller ID' or 'new dialed number' may be used to\n");
- printf("perform screening only if the attribute match. Attributes prior\n");
- printf("'new caller ID' or 'new dialed number' may be used to alter them. Attribute to\n");
- printf("define the type of number can be: 'unknown', 'international', 'national',\n");
- printf("'network', 'subscriber', 'abbreviated' Attribute to define the restriction of a\n");
- printf("caller ID: 'allowed', 'restricted'\n\n");
-
- printf("The current caller ID or dialed number may contain one or more '?', to allow\n");
- printf("any digit to match. The current caller ID or dialed number may contain a '*',\n");
- printf("to allow any suffix to match from now on. The new caller ID or dialed number\n");
- printf("may contain a '*', to append the suffix from the current caller ID or dialed\n");
- printf("number.\n\n");
-
- printf("When screening an incoming caller ID or dialed number, the '@' can be appended\n");
- printf("to the 'new caller ID', followed by a 'host:port', to route call to a special\n");
- printf("Osmo-CC endpoint. This way it is possible to do simple routing.\n\n");
-}
-
-char *osmo_cc_strtok_quotes(const char **text_p)
-{
- static char token[1024];
- const char *text = *text_p;
- int i, quote;
-
- /* skip spaces */
- while (*text) {
- if (*text > 32)
- break;
- text++;
- }
-
- /* if eol, return NULL */
- if (!(*text))
- return NULL;
-
- i = 0;
- quote = 0;
- while (*text) {
- /* escape allows all following characters */
- if (*text == '\\') {
- text++;
- if (*text)
- token[i++] = *text++;
- continue;
- }
- /* no quote, check for them or break on white space */
- if (quote == 0) {
- if (*text == '\'') {
- quote = 1;
- text++;
- continue;
- }
- if (*text == '\"') {
- quote = 2;
- text++;
- continue;
- }
- if (*text <= ' ')
- break;
- }
- /* single quote, check for unquote */
- if (quote == 1 && *text == '\'') {
- quote = 0;
- text++;
- continue;
- }
- /* double quote, check for unquote */
- if (quote == 2 && *text == '\"') {
- quote = 0;
- text++;
- continue;
- }
- /* copy character */
- token[i++] = *text++;
- }
- token[i] = '\0';
-
- *text_p = text;
- return token;
-}
-
-int osmo_cc_add_screen(osmo_cc_endpoint_t *ep, const char *text)
-{
- osmo_cc_screen_list_t **list_p = NULL, *list;
- const char *token;
- int no_present = 0, calling_in = 0, star_used, at_used;
- int i, j;
-
- star_used = 0;
- if (!strncasecmp(text, "screen-calling-in", 17)) {
- text += 17;
- list_p = &ep->screen_calling_in;
- no_present = 1;
- calling_in = 1;
- } else if (!strncasecmp(text, "screen-called-in", 16)) {
- text += 16;
- list_p = &ep->screen_called_in;
- calling_in = 1;
- } else if (!strncasecmp(text, "screen-calling-out", 18)) {
- text += 18;
- list_p = &ep->screen_calling_out;
- no_present = 1;
- } else if (!strncasecmp(text, "screen-called-out", 17)) {
- text += 17;
- list_p = &ep->screen_called_out;
- } else {
- PDEBUG(DCC, DEBUG_ERROR, "Invalid screening definition \"%s\". It must start with 'screen-calling-in' or 'screen-called-in' or 'screen-calling-out' or 'screen-called-out'\n", text);
- return -EINVAL;
- }
-
- /* skip space behind screen list string */
- while (*text) {
- if (*text > 32)
- break;
- text++;
- }
-
- list = calloc(1, sizeof(*list));
- if (!list)
- return -ENOMEM;
-
-next_from:
- token = osmo_cc_strtok_quotes(&text);
- if (!token) {
- free(list);
- PDEBUG(DCC, DEBUG_ERROR, "Missing 'from' string in screening definition \"%s\". If the string shall be empty, use double quotes. (\'\' or \"\")\n", text);
- return -EINVAL;
- }
- if (!strcasecmp(token, "unknown")) {
- list->has_from_type = 1;
- list->from_type = OSMO_CC_TYPE_UNKNOWN;
- goto next_from;
- } else
- if (!strcasecmp(token, "international")) {
- list->has_from_type = 1;
- list->from_type = OSMO_CC_TYPE_INTERNATIONAL;
- goto next_from;
- } else
- if (!strcasecmp(token, "national")) {
- list->has_from_type = 1;
- list->from_type = OSMO_CC_TYPE_NATIONAL;
- goto next_from;
- } else
- if (!strcasecmp(token, "network")) {
- list->has_from_type = 1;
- list->from_type = OSMO_CC_TYPE_NETWORK;
- goto next_from;
- } else
- if (!strcasecmp(token, "subscriber")) {
- list->has_from_type = 1;
- list->from_type = OSMO_CC_TYPE_SUBSCRIBER;
- goto next_from;
- } else
- if (!strcasecmp(token, "abbreviated")) {
- list->has_from_type = 1;
- list->from_type = OSMO_CC_TYPE_ABBREVIATED;
- goto next_from;
- } else
- if (!strcasecmp(token, "allowed")) {
- if (no_present) {
-no_present_error:
- free(list);
- PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text);
- PDEBUG(DCC, DEBUG_ERROR, "Keyword '%s' not allowed in screen entry for called number\n", token);
- return -EINVAL;
- }
- list->has_from_present = 1;
- list->from_present = OSMO_CC_PRESENT_ALLOWED;
- goto next_from;
- } else
- if (!strcasecmp(token, "restricted")) {
- if (no_present)
- goto no_present_error;
- list->has_from_present = 1;
- list->from_present = OSMO_CC_PRESENT_RESTRICTED;
- goto next_from;
- } else {
- star_used = 0;
- for (i = j = 0; token[i] && j < (int)sizeof(list->from) - 1; i++, j++) {
- if (token[i] == '?')
- list->from[j] = SCREEN_QUESTIONMARK;
- else
- if (token[i] == '*') {
- if (star_used) {
- free(list);
- PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text);
- PDEBUG(DCC, DEBUG_ERROR, "The '*' may be used only once.\n");
- return -EINVAL;
- }
- list->from[j] = SCREEN_STAR;
- star_used = 1;
- } else
- if (token[i] == '\\' && token[i + 1] != '\0')
- list->from[j] = token[++i];
- else
- list->from[j] = token[i];
- }
- list->from[j] = '\0';
- }
-
-next_to:
- token = osmo_cc_strtok_quotes(&text);
- if (!token) {
- free(list);
- PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text);
- PDEBUG(DCC, DEBUG_ERROR, "Missing screening result. If the string shall be empty, use double quotes. (\'\' or \"\")\n");
- return -EINVAL;
- }
- if (!strcasecmp(token, "unknown")) {
- list->has_to_type = 1;
- list->to_type = OSMO_CC_TYPE_UNKNOWN;
- goto next_to;
- } else
- if (!strcasecmp(token, "international")) {
- list->has_to_type = 1;
- list->to_type = OSMO_CC_TYPE_INTERNATIONAL;
- goto next_to;
- } else
- if (!strcasecmp(token, "national")) {
- list->has_to_type = 1;
- list->to_type = OSMO_CC_TYPE_NATIONAL;
- goto next_to;
- } else
- if (!strcasecmp(token, "network")) {
- list->has_to_type = 1;
- list->to_type = OSMO_CC_TYPE_NETWORK;
- goto next_to;
- } else
- if (!strcasecmp(token, "subscriber")) {
- list->has_to_type = 1;
- list->to_type = OSMO_CC_TYPE_SUBSCRIBER;
- goto next_to;
- } else
- if (!strcasecmp(token, "abbreviated")) {
- list->has_to_type = 1;
- list->to_type = OSMO_CC_TYPE_ABBREVIATED;
- goto next_to;
- } else
- if (!strcasecmp(token, "allowed")) {
- if (no_present)
- goto no_present_error;
- list->has_to_present = 1;
- list->to_present = OSMO_CC_PRESENT_ALLOWED;
- goto next_to;
- } else
- if (!strcasecmp(token, "restricted")) {
- if (no_present)
- goto no_present_error;
- list->has_to_present = 1;
- list->to_present = OSMO_CC_PRESENT_RESTRICTED;
- goto next_to;
- } else {
- at_used = star_used = 0;
- for (i = j = 0; token[i] && j < (int)sizeof(list->to) - 1; i++, j++) {
- if (token[i] == '*') {
- if (star_used) {
- free(list);
- PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text);
- PDEBUG(DCC, DEBUG_ERROR, "The '*' may be used only once.\n");
- return -EINVAL;
- }
- list->to[j] = SCREEN_STAR;
- star_used = 1;
- } else
- if (token[i] == '@') {
- if (!calling_in) {
- free(list);
- PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text);
- PDEBUG(DCC, DEBUG_ERROR, "The '@' may be used only for incoming calls from interface.\n");
- return -EINVAL;
- }
- if (at_used) {
- free(list);
- PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text);
- PDEBUG(DCC, DEBUG_ERROR, "The '@' may be used only once.\n");
- return -EINVAL;
- }
- list->to[j] = SCREEN_AT;
- at_used = 1;
- } else
- if (token[i] == '\\' && token[i + 1] != '\0')
- list->to[j] = token[++i];
- else
- list->to[j] = token[i];
- }
- list->to[j] = '\0';
- }
-
- token = osmo_cc_strtok_quotes(&text);
- if (token) {
- free(list);
- PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text);
- PDEBUG(DCC, DEBUG_ERROR, "Got garbage behind screening result.\n");
- return -EINVAL;
- }
-
- /* attach screen entry to list */
- while (*list_p)
- list_p = &((*list_p)->next);
- *list_p = list;
-
- return 0;
-}
-
-void osmo_cc_flush_screen(osmo_cc_screen_list_t *list)
-{
- osmo_cc_screen_list_t *temp;
-
- while (list) {
- temp = list;
- list = list->next;
- free(temp);
- }
-}
-
-const char *print_rule_string(const char *input)
-{
- static char output[256];
- int i;
-
- for (i = 0; *input && i < (int)sizeof(output) - 1; i++, input++) {
- switch (*input) {
- case SCREEN_QUESTIONMARK:
- output[i] = '?';
- break;
- case SCREEN_STAR:
- output[i] = '*';
- break;
- case SCREEN_AT:
- output[i] = '@';
- break;
- default:
- output[i] = *input;
- }
- }
-
- output[i] = '\0';
- return output;
-}
-
-static int osmo_cc_screen(const char *what, osmo_cc_screen_list_t *list, uint8_t *type, uint8_t *present, char *id_to, int id_to_size, const char *id_from, const char **routing_p)
-{
- const char *suffix;
- int i, j, rule;
-
- PDEBUG(DCC, DEBUG_INFO, "Screening %s '%s':\n", what, id_from);
- switch (*type) {
- case OSMO_CC_TYPE_UNKNOWN:
- PDEBUG(DCC, DEBUG_INFO, " -> type = unknown\n");
- break;
- case OSMO_CC_TYPE_INTERNATIONAL:
- PDEBUG(DCC, DEBUG_INFO, " -> type = international\n");
- break;
- case OSMO_CC_TYPE_NATIONAL:
- PDEBUG(DCC, DEBUG_INFO, " -> type = national\n");
- break;
- case OSMO_CC_TYPE_NETWORK:
- PDEBUG(DCC, DEBUG_INFO, " -> type = network\n");
- break;
- case OSMO_CC_TYPE_SUBSCRIBER:
- PDEBUG(DCC, DEBUG_INFO, " -> type = subscriber\n");
- break;
- case OSMO_CC_TYPE_ABBREVIATED:
- PDEBUG(DCC, DEBUG_INFO, " -> type = abbreviated\n");
- break;
- }
- if (present) switch (*present) {
- case OSMO_CC_PRESENT_ALLOWED:
- PDEBUG(DCC, DEBUG_INFO, " -> present = allowed\n");
- break;
- case OSMO_CC_PRESENT_RESTRICTED:
- PDEBUG(DCC, DEBUG_INFO, " -> present = restricted\n");
- break;
- }
-
- rule = 0;
- while (list) {
- rule++;
- PDEBUG(DCC, DEBUG_INFO, "Comparing with rule #%d: '%s':\n", rule, print_rule_string(list->from));
- if (list->has_from_type) switch (list->from_type) {
- case OSMO_CC_TYPE_UNKNOWN:
- PDEBUG(DCC, DEBUG_INFO, " -> type = unknown\n");
- break;
- case OSMO_CC_TYPE_INTERNATIONAL:
- PDEBUG(DCC, DEBUG_INFO, " -> type = international\n");
- break;
- case OSMO_CC_TYPE_NATIONAL:
- PDEBUG(DCC, DEBUG_INFO, " -> type = national\n");
- break;
- case OSMO_CC_TYPE_NETWORK:
- PDEBUG(DCC, DEBUG_INFO, " -> type = network\n");
- break;
- case OSMO_CC_TYPE_SUBSCRIBER:
- PDEBUG(DCC, DEBUG_INFO, " -> type = subscriber\n");
- break;
- case OSMO_CC_TYPE_ABBREVIATED:
- PDEBUG(DCC, DEBUG_INFO, " -> type = abbreviated\n");
- break;
- }
- if (list->has_from_present) switch (list->from_present) {
- case OSMO_CC_PRESENT_ALLOWED:
- PDEBUG(DCC, DEBUG_INFO, " -> present = allowed\n");
- break;
- case OSMO_CC_PRESENT_RESTRICTED:
- PDEBUG(DCC, DEBUG_INFO, " -> present = restricted\n");
- break;
- }
- suffix = NULL;
- /* attributes do not match */
- if (list->has_from_type && list->from_type != *type) {
- PDEBUG(DCC, DEBUG_INFO, "Rule does not match, because 'type' is different.\n");
- continue;
- }
- if (present && list->has_from_present && list->from_present != *present) {
- PDEBUG(DCC, DEBUG_INFO, "Rule does not match, because 'present' is different.\n");
- continue;
- }
- for (i = 0; list->from[i] && id_from[i]; i++) {
- /* '?' means: any digit, so it machtes */
- if (list->from[i] == SCREEN_QUESTIONMARK) {
- continue;
- }
- /* '*' means: anything may follow, so it machtes */
- if (list->from[i] == SCREEN_STAR) {
- suffix = id_from + i;
- break;
- }
- /* check if digit doesn't matches */
- if (list->from[i] != id_from[i])
- break;
- }
- /* if last checked digit is '*', we have a match */
- /* also if we hit EOL at id_from and next check digit is '*' */
- if (list->from[i] == SCREEN_STAR)
- break;
- /* if all digits have matched */
- if (list->from[i] == '\0' && id_from[i] == '\0')
- break;
- PDEBUG(DCC, DEBUG_INFO, "Rule does not match, because %s is different.\n", what);
- list = list->next;
- }
-
- /* if no list entry matches */
- if (!list)
- return -1;
-
- /* replace ID */
- if (list->has_to_type) {
- *type = list->to_type;
- }
- if (present && list->has_to_present) {
- *present = list->to_present;
- }
- for (i = j = 0; list->to[i]; i++) {
- if (j == id_to_size - 1)
- break;
- /* '*' means to use suffix of input string */
- if (list->to[i] == SCREEN_STAR && suffix) {
- while (*suffix) {
- id_to[j++] = *suffix++;
- if (j == id_to_size - 1)
- break;
- }
- continue;
- /* '@' means to stop and return routing also */
- } else if (list->to[i] == SCREEN_AT) {
- if (routing_p)
- *routing_p = &list->to[i + 1];
- break;
- }
- /* copy output digit */
- id_to[j++] = list->to[i];
- }
- id_to[j] = '\0';
-
- PDEBUG(DCC, DEBUG_INFO, "Rule matches, changing %s to '%s'.\n", what, print_rule_string(id_to));
- if (list->has_to_type) switch (list->to_type) {
- case OSMO_CC_TYPE_UNKNOWN:
- PDEBUG(DCC, DEBUG_INFO, " -> type = unknown\n");
- break;
- case OSMO_CC_TYPE_INTERNATIONAL:
- PDEBUG(DCC, DEBUG_INFO, " -> type = international\n");
- break;
- case OSMO_CC_TYPE_NATIONAL:
- PDEBUG(DCC, DEBUG_INFO, " -> type = national\n");
- break;
- case OSMO_CC_TYPE_NETWORK:
- PDEBUG(DCC, DEBUG_INFO, " -> type = network\n");
- break;
- case OSMO_CC_TYPE_SUBSCRIBER:
- PDEBUG(DCC, DEBUG_INFO, " -> type = subscriber\n");
- break;
- case OSMO_CC_TYPE_ABBREVIATED:
- PDEBUG(DCC, DEBUG_INFO, " -> type = abbreviated\n");
- break;
- }
- if (list->has_to_present) switch (list->to_present) {
- case OSMO_CC_PRESENT_ALLOWED:
- PDEBUG(DCC, DEBUG_INFO, " -> present = allowed\n");
- break;
- case OSMO_CC_PRESENT_RESTRICTED:
- PDEBUG(DCC, DEBUG_INFO, " -> present = restricted\n");
- break;
- }
- if (routing_p && *routing_p)
- PDEBUG(DCC, DEBUG_INFO, " -> remote = %s\n", *routing_p);
-
- return 0;
-}
-
-osmo_cc_msg_t *osmo_cc_screen_msg(osmo_cc_endpoint_t *ep, osmo_cc_msg_t *old_msg, int in, const char **routing_p)
-{
- osmo_cc_msg_t *new_msg;
- char id[256], calling[256], called[256], redir[256];
- uint8_t calling_type, calling_plan, calling_present, calling_screen;
- uint8_t called_type, called_plan;
- uint8_t redir_type, redir_plan, redir_present, redir_screen, redir_reason;
- int calling_status = 0, called_status = 0, redir_status = 0;
- int rc;
- void *ie, *to_ie;
- uint8_t ie_type;
- uint16_t ie_length;
- void *ie_value;
-
- if (in && ep->screen_calling_in) {
- rc = osmo_cc_get_ie_calling(old_msg, 0, &calling_type, &calling_plan, &calling_present, &calling_screen, id, sizeof(id));
- if (rc >= 0) {
- rc = osmo_cc_screen("incoming caller ID", ep->screen_calling_in, &calling_type, &calling_present, calling, sizeof(calling), id, routing_p);
- if (rc >= 0)
- calling_status = 1;
- } else {
- calling_type = OSMO_CC_TYPE_UNKNOWN;
- calling_plan = OSMO_CC_PLAN_TELEPHONY;
- calling_present = OSMO_CC_PRESENT_ALLOWED;
- calling_screen = OSMO_CC_SCREEN_NETWORK;
- rc = osmo_cc_screen("incoming caller ID", ep->screen_calling_in, &calling_type, &calling_present, calling, sizeof(calling), "", routing_p);
- if (rc >= 0)
- calling_status = 1;
- }
- rc = osmo_cc_get_ie_redir(old_msg, 0, &redir_type, &redir_plan, &redir_present, &redir_screen, &redir_reason, id, sizeof(id));
- if (rc >= 0) {
- rc = osmo_cc_screen("incoming redirecting number", ep->screen_calling_in, &redir_type, &redir_present, redir, sizeof(redir), id, NULL);
- if (rc >= 0)
- redir_status = 1;
- }
- }
- if (in && ep->screen_called_in) {
- rc = osmo_cc_get_ie_called(old_msg, 0, &called_type, &called_plan, id, sizeof(id));
- if (rc >= 0) {
- rc = osmo_cc_screen("incoming dialed number", ep->screen_called_in, &called_type, NULL, called, sizeof(called), id, routing_p);
- if (rc >= 0)
- called_status = 1;
- } else {
- called_type = OSMO_CC_TYPE_UNKNOWN;
- called_plan = OSMO_CC_PLAN_TELEPHONY;
- rc = osmo_cc_screen("incoming dialed number", ep->screen_called_in, &called_type, NULL, called, sizeof(called), "", routing_p);
- if (rc >= 0)
- called_status = 1;
- }
- }
- if (!in && ep->screen_calling_out) {
- rc = osmo_cc_get_ie_calling(old_msg, 0, &calling_type, &calling_plan, &calling_present, &calling_screen, id, sizeof(id));
- if (rc >= 0) {
- rc = osmo_cc_screen("outgoing caller ID", ep->screen_calling_out, &calling_type, &calling_present, calling, sizeof(calling), id, NULL);
- if (rc >= 0)
- calling_status = 1;
- } else {
- calling_type = OSMO_CC_TYPE_UNKNOWN;
- calling_plan = OSMO_CC_PLAN_TELEPHONY;
- calling_present = OSMO_CC_PRESENT_ALLOWED;
- calling_screen = OSMO_CC_SCREEN_NETWORK;
- rc = osmo_cc_screen("outgoing caller ID", ep->screen_calling_out, &calling_type, &calling_present, calling, sizeof(calling), "", NULL);
- if (rc >= 0)
- calling_status = 1;
- }
- rc = osmo_cc_get_ie_redir(old_msg, 0, &redir_type, &redir_plan, &redir_present, &redir_screen, &redir_reason, id, sizeof(id));
- if (rc >= 0) {
- rc = osmo_cc_screen("outgoing redirecting number", ep->screen_calling_out, &redir_type, &redir_present, redir, sizeof(redir), id, NULL);
- if (rc >= 0)
- redir_status = 1;
- }
- }
- if (!in && ep->screen_called_out) {
- rc = osmo_cc_get_ie_called(old_msg, 0, &called_type, &called_plan, id, sizeof(id));
- if (rc >= 0) {
- rc = osmo_cc_screen("outgoing dialed number", ep->screen_called_out, &called_type, NULL, called, sizeof(called), id, NULL);
- if (rc >= 0)
- called_status = 1;
- } else {
- called_type = OSMO_CC_TYPE_UNKNOWN;
- called_plan = OSMO_CC_PLAN_TELEPHONY;
- rc = osmo_cc_screen("outgoing dialed number", ep->screen_called_out, &called_type, NULL, called, sizeof(called), "", NULL);
- if (rc >= 0)
- called_status = 1;
- }
- }
-
- /* nothing screened */
- if (!calling_status && !called_status && !redir_status)
- return old_msg;
-
- new_msg = osmo_cc_new_msg(old_msg->type);
-
- /* copy and replace */
- ie = old_msg->data;
- while ((ie_value = osmo_cc_msg_sep_ie(old_msg, &ie, &ie_type, &ie_length))) {
- switch (ie_type) {
- case OSMO_CC_IE_CALLING:
- if (calling_status) {
- osmo_cc_add_ie_calling(new_msg, calling_type, calling_plan, calling_present, calling_screen, calling);
- calling_status = 0;
- break;
- }
- goto copy;
- case OSMO_CC_IE_CALLED:
- if (called_status) {
- osmo_cc_add_ie_called(new_msg, called_type, called_plan, called);
- called_status = 0;
- break;
- }
- goto copy;
- case OSMO_CC_IE_REDIR:
- if (redir_status) {
- osmo_cc_add_ie_redir(new_msg, redir_type, redir_plan, redir_present, redir_screen, redir_reason, redir);
- redir_status = 0;
- break;
- }
- goto copy;
- default:
- copy:
- to_ie = osmo_cc_add_ie(new_msg, ie_type, ie_length);
- memcpy(to_ie, ie_value, ie_length);
- }
- }
-
- /* applend, if not yet in message (except redir, since it must exist) */
- if (calling_status)
- osmo_cc_add_ie_calling(new_msg, calling_type, calling_plan, calling_present, calling_screen, calling);
- if (called_status)
- osmo_cc_add_ie_called(new_msg, called_type, called_plan, called);
-
- free(old_msg);
- return new_msg;
-}
-
diff --git a/src/libosmocc/screen.h b/src/libosmocc/screen.h
deleted file mode 100644
index 29f4515..0000000
--- a/src/libosmocc/screen.h
+++ /dev/null
@@ -1,7 +0,0 @@
-
-void osmo_cc_help_screen(void);
-char *osmo_cc_strtok_quotes(const char **text_p);
-int osmo_cc_add_screen(osmo_cc_endpoint_t *ep, const char *text);
-void osmo_cc_flush_screen(osmo_cc_screen_list_t *list);
-osmo_cc_msg_t *osmo_cc_screen_msg(osmo_cc_endpoint_t *ep, osmo_cc_msg_t *old_msg, int in, const char **routing_p);
-
diff --git a/src/libosmocc/sdp.c b/src/libosmocc/sdp.c
deleted file mode 100644
index 849bfb9..0000000
--- a/src/libosmocc/sdp.c
+++ /dev/null
@@ -1,544 +0,0 @@
-/* Session Description Protocol parsing and generator
- * This shall be simple and is incomplete.
- *
- * (C) 2019 by Andreas Eversberg <jolly@eversberg.eu>
- * All Rights Reserved
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <errno.h>
-#include "../libdebug/debug.h"
-#include "../libtimer/timer.h"
-#include "endpoint.h"
-#include "sdp.h"
-
-#define strncat_printf(sdp, fmt, arg...) \
- { \
- snprintf(sdp + strlen(sdp), sizeof(sdp) - strlen(sdp), fmt, ## arg); \
- sdp[sizeof(sdp) - 1] = '\0'; \
- }
-
-/* generate SDP from session structure */
-char *osmo_cc_session_gensdp(osmo_cc_session_t *session)
-{
- /* calc max size of SDP: quick an dirty (close to max UDP payload size) */
- static char sdp[65000];
- const char *username, *sess_id, *sess_version, *nettype, *addrtype, *unicast_address;
- const char *session_name;
- int individual_connection_data = 1; /* in case there is no media, there is no connection data */
- int individual_send_receive = 1; /* in case there is no media, there is no send/receive attribute */
- struct osmo_cc_session_media *media;
- struct osmo_cc_session_codec *codec;
-
- sdp[0] = 0;
-
- /* Version */
- strncat_printf(sdp, "v=0\r\n");
-
- /* Origin */
- username = session->origin_local.username;
- sess_id = session->origin_local.sess_id;
- sess_version = session->origin_local.sess_version;
- nettype = session->origin_local.nettype;
- addrtype = session->origin_local.addrtype;
- unicast_address = session->origin_local.unicast_address;
- strncat_printf(sdp, "o=%s %s %s %s %s %s\r\n", username, sess_id, sess_version, nettype, addrtype, unicast_address);
-
- /* Session */
- session_name = session->name;
- strncat_printf(sdp, "s=%s\r\n", session_name);
-
- /* Connection Data (if all media have the same data) */
- if (session->media_list) {
- osmo_cc_session_for_each_media(session->media_list->next, media) {
- if (session->media_list->connection_data_local.nettype != media->connection_data_local.nettype)
- break;
- if (session->media_list->connection_data_local.addrtype != media->connection_data_local.addrtype)
- break;
- if (!!strcmp(session->media_list->connection_data_local.address, media->connection_data_local.address))
- break;
- }
- if (!media)
- individual_connection_data = 0;
- }
- if (!individual_connection_data)
- strncat_printf(sdp, "c=%s %s %s\r\n", osmo_cc_session_nettype2string(session->media_list->connection_data_local.nettype), osmo_cc_session_addrtype2string(session->media_list->connection_data_local.addrtype), session->media_list->connection_data_local.address);
-
- /* timestamp */
- strncat_printf(sdp, "t=0 0\r\n");
-
- /* sendonly /recvonly (if all media have the same data) */
- if (session->media_list) {
- osmo_cc_session_for_each_media(session->media_list->next, media) {
- if (session->media_list->send != media->send)
- break;
- if (session->media_list->receive != media->receive)
- break;
- }
- if (!media)
- individual_send_receive = 0;
- }
- if (!individual_send_receive) {
- if (session->media_list->send && !session->media_list->receive)
- strncat_printf(sdp, "a=sendonly\r\n");
- if (!session->media_list->send && session->media_list->receive)
- strncat_printf(sdp, "a=recvonly\r\n");
- if (!session->media_list->send && !session->media_list->receive)
- strncat_printf(sdp, "a=inactive\r\n");
- }
-
- /* media */
- osmo_cc_session_for_each_media(session->media_list, media) {
- strncat_printf(sdp, "m=%s %u %s",
- osmo_cc_session_media_type2string(media->description.type) ? : media->description.type_name,
- media->description.port_local,
- osmo_cc_session_media_proto2string(media->description.proto) ? : media->description.proto_name);
- osmo_cc_session_for_each_codec(media->codec_list, codec)
- strncat_printf(sdp, " %u", codec->payload_type_local);
- strncat_printf(sdp, "\r\n");
- /* don't list rtpmap when session was canceled by setting port to 0 */
- if (media->description.port_local == 0)
- continue;
- if (individual_connection_data)
- strncat_printf(sdp, "c=%s %s %s\r\n", osmo_cc_session_nettype2string(media->connection_data_local.nettype), osmo_cc_session_addrtype2string(media->connection_data_local.addrtype), media->connection_data_local.address);
- osmo_cc_session_for_each_codec(media->codec_list, codec) {
- strncat_printf(sdp, "a=rtpmap:%u %s/%d", codec->payload_type_local, codec->payload_name, codec->payload_rate);
- if (codec->payload_channels >= 2)
- strncat_printf(sdp, "/%d", codec->payload_channels);
- strncat_printf(sdp, "\r\n");
- }
- if (individual_send_receive) {
- if (media->send && !media->receive)
- strncat_printf(sdp, "a=sendonly\r\n");
- if (!media->send && media->receive)
- strncat_printf(sdp, "a=recvonly\r\n");
- if (!media->send && !media->receive)
- strncat_printf(sdp, "a=inactive\r\n");
- }
- }
-
- /* check for overflow and return */
- if (strlen(sdp) == sizeof(sdp) - 1) {
- PDEBUG(DCC, DEBUG_ERROR, "Fatal error: Allocated SDP buffer with %d bytes is too small, please fix!\n", (int)sizeof(sdp));
- return NULL;
- }
- return sdp;
-}
-
-/* separate a word from string that is delimited with one or more space characters */
-static char *wordsep(char **text_p)
-{
- char *text = *text_p;
- static char word[256];
- int i;
-
- /* no text */
- if (text == NULL || *text == '\0')
- return NULL;
- /* skip spaces before text */
- while (*text && *text <= ' ')
- text++;
- /* copy content */
- i = 0;
- while (*text > ' ' && i < (int)sizeof(word))
- word[i++] = *text++;
- word[i] = '\0';
- /* set next */
- *text_p = text;
- return word;
-}
-
-/*
- * codecs and their default values
- *
- * if format is -1, payload type is dynamic
- * if rate is 0, rate may be any rate
- */
-struct codec_defaults {
- int fmt;
- char *name;
- uint32_t rate;
- int channels;
-} codec_defaults[] = {
- { 0, "PCMU", 8000, 1 },
- { 3, "GSM", 8000, 1 },
- { 4, "G723", 8000, 1 },
- { 5, "DVI4", 8000, 1 },
- { 6, "DVI4", 16000, 1 },
- { 7, "LPC", 8000, 1 },
- { 8, "PCMA", 8000, 1 },
- { 9, "G722", 8000, 1 },
- { 10, "L16", 44100, 2 },
- { 11, "L16", 44100, 1 },
- { 12, "QCELP", 8000, 1 },
- { 13, "CN", 8000, 1 },
- { 14, "MPA", 90000, 1 },
- { 15, "G728", 8000, 1 },
- { 16, "DVI4", 11025, 1 },
- { 17, "DVI4", 22050, 1 },
- { 18, "G729", 8000, 1 },
- { 25, "CELB", 90000, 0 },
- { 26, "JPEG", 90000, 0 },
- { 28, "nv", 90000, 0 },
- { 31, "H261", 90000, 0 },
- { 32, "MPV", 90000, 0 },
- { 33, "MP2T", 90000, 0 },
- { 34, "H263", 90000, 0 },
- { -1, NULL, 0, 0 },
-};
-
-static void complete_codec_by_fmt(uint8_t fmt, const char **name, uint32_t *rate, int *channels)
-{
- int i;
-
- for (i = 0; codec_defaults[i].name; i++) {
- if (codec_defaults[i].fmt == fmt)
- break;
- }
- if (!codec_defaults[i].name)
- return;
-
- free((char *)*name);
- *name = strdup(codec_defaults[i].name);
- *rate = codec_defaults[i].rate;
- *channels = codec_defaults[i].channels;
-}
-
-int osmo_cc_payload_type_by_attrs(uint8_t *fmt, const char *name, uint32_t *rate, int *channels)
-{
- int i;
-
- for (i = 0; codec_defaults[i].name; i++) {
- if (!strcmp(codec_defaults[i].name, name)
- && (*rate == 0 || codec_defaults[i].rate == *rate)
- && (*channels == 0 || codec_defaults[i].channels == *channels))
- break;
- }
- if (!codec_defaults[i].name)
- return -EINVAL;
-
- *fmt = codec_defaults[i].fmt;
- *rate = codec_defaults[i].rate;
- *channels = codec_defaults[i].channels;
-
- return 0;
-}
-
-/* parses data and codec list from SDP
- *
- * sdp = given SDP text
- * return: SDP session description structure */
-struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf, void *priv, const char *_sdp)
-{
- char buffer[strlen(_sdp) + 1], *sdp = buffer;
- char *line, *p, *word, *next_word;
- int line_no = 0;
- struct osmo_cc_session_connection_data ccd, *cd;
- int csend = 1, creceive = 1; /* common default */
- struct osmo_cc_session *session = NULL;
- struct osmo_cc_session_media *media = NULL;
- struct osmo_cc_session_codec *codec = NULL;
-
- /* prepare data */
- strcpy(sdp, _sdp);
- memset(&ccd, 0, sizeof(ccd));
-
- /* create SDP session description */
- session = osmo_cc_new_session(conf, priv, NULL, NULL, NULL, 0, 0, NULL, NULL, 0);
-
- /* check every line of SDP and parse its data */
- while(*sdp) {
- if ((p = strchr(sdp, '\r'))) {
- *p++ = '\0';
- if (*p == '\n')
- p++;
- line = sdp;
- sdp = p;
- } else if ((p = strchr(sdp, '\n'))) {
- *p++ = '\0';
- line = sdp;
- sdp = p;
- } else {
- line = sdp;
- sdp = strchr(sdp, '\0');
- }
- next_word = line + 2;
- line_no++;
-
- if (line[0] == '\0')
- continue;
-
- if (line[1] != '=') {
- PDEBUG(DCC, DEBUG_NOTICE, "SDP line %d = '%s' is garbage, expecting '=' as second character.\n", line_no, line);
- continue;
- }
-
- switch(line[0]) {
- case 'v':
- PDEBUG(DCC, DEBUG_DEBUG, " -> Version: %s\n", next_word);
- if (atoi(next_word) != 0) {
- PDEBUG(DCC, DEBUG_NOTICE, "SDP line %d = '%s' describes unsupported version.\n", line_no, line);
- osmo_cc_free_session(session);
- return NULL;
- }
- break;
- case 'o':
- PDEBUG(DCC, DEBUG_DEBUG, " -> Originator: %s\n", next_word);
- /* Originator */
- word = wordsep(&next_word);
- if (!word)
- break;
- free((char *)session->origin_remote.username); // if already set
- session->origin_remote.username = strdup(word);
- word = wordsep(&next_word);
- if (!word)
- break;
- free((char *)session->origin_remote.sess_id); // if already set
- session->origin_remote.sess_id = strdup(word);
- word = wordsep(&next_word);
- if (!word)
- break;
- free((char *)session->origin_remote.sess_version); // if already set
- session->origin_remote.sess_version = strdup(word);
- word = wordsep(&next_word);
- if (!word)
- break;
- free((char *)session->origin_remote.nettype); // if already set
- session->origin_remote.nettype = strdup(word);
- word = wordsep(&next_word);
- if (!word)
- break;
- free((char *)session->origin_remote.addrtype); // if already set
- session->origin_remote.addrtype = strdup(word);
- word = wordsep(&next_word);
- if (!word)
- break;
- free((char *)session->origin_remote.unicast_address); // if already set
- session->origin_remote.unicast_address = strdup(word);
- break;
- case 's':
- /* Session Name */
- PDEBUG(DCC, DEBUG_DEBUG, " -> Session Name: %s\n", next_word);
- free((char *)session->name); // if already set
- session->name = strdup(next_word);
- break;
- case 'c': /* Connection Data */
- PDEBUG(DCC, DEBUG_DEBUG, " -> Connection Data: %s\n", next_word);
- if (media)
- cd = &media->connection_data_remote;
- else
- cd = &ccd;
- /* network type */
- if (!(word = wordsep(&next_word)))
- break;
- if (!strcmp(word, "IN"))
- cd->nettype = osmo_cc_session_nettype_inet;
- else {
- PDEBUG(DCC, DEBUG_NOTICE, "Unsupported network type '%s' in SDP line %d = '%s'\n", word, line_no, line);
- break;
- }
- /* address type */
- if (!(word = wordsep(&next_word)))
- break;
- if (!strcmp(word, "IP4")) {
- cd->addrtype = osmo_cc_session_addrtype_ipv4;
- PDEBUG(DCC, DEBUG_DEBUG, " -> Address Type = IPv4\n");
- } else
- if (!strcmp(word, "IP6")) {
- cd->addrtype = osmo_cc_session_addrtype_ipv6;
- PDEBUG(DCC, DEBUG_DEBUG, " -> Address Type = IPv6\n");
- } else {
- PDEBUG(DCC, DEBUG_NOTICE, "Unsupported address type '%s' in SDP line %d = '%s'\n", word, line_no, line);
- break;
- }
- /* connection address */
- if (!(word = wordsep(&next_word)))
- break;
- if ((p = strchr(word, '/')))
- *p++ = '\0';
- free((char *)cd->address); // in case of multiple lines of 'c'
- cd->address = strdup(word);
- PDEBUG(DCC, DEBUG_DEBUG, " -> Address = %s\n", word);
- break;
- case 'm': /* Media Description */
- PDEBUG(DCC, DEBUG_DEBUG, " -> Media Description: %s\n", next_word);
- /* add media description */
- media = osmo_cc_add_media(session, 0, 0, NULL, 0, 0, 0, csend, creceive, NULL, 0);
- /* copy common connection data from common connection, if exists */
- cd = &media->connection_data_remote;
- memcpy(cd, &ccd, sizeof(*cd));
- /* media type */
- if (!(word = wordsep(&next_word)))
- break;
- if (!strcmp(word, "audio"))
- media->description.type = osmo_cc_session_media_type_audio;
- else
- if (!strcmp(word, "video"))
- media->description.type = osmo_cc_session_media_type_video;
- else {
- media->description.type = osmo_cc_session_media_type_unknown;
- media->description.type_name = strdup(word);
- PDEBUG(DCC, DEBUG_DEBUG, "Unsupported media type in SDP line %d = '%s'\n", line_no, line);
- }
- /* port */
- if (!(word = wordsep(&next_word)))
- break;
- media->description.port_remote = atoi(word);
- /* proto */
- if (!(word = wordsep(&next_word)))
- break;
- if (!strcmp(word, "RTP/AVP"))
- media->description.proto = osmo_cc_session_media_proto_rtp;
- else {
- media->description.proto = osmo_cc_session_media_proto_unknown;
- media->description.proto_name = strdup(word);
- PDEBUG(DCC, DEBUG_NOTICE, "Unsupported protocol type in SDP line %d = '%s'\n", line_no, line);
- break;
- }
- /* create codec description for each codec and link */
- while ((word = wordsep(&next_word))) {
- /* create codec */
- codec = osmo_cc_add_codec(media, NULL, 0, 1, NULL, NULL, 0);
- /* fmt */
- codec->payload_type_remote = atoi(word);
- complete_codec_by_fmt(codec->payload_type_remote, &codec->payload_name, &codec->payload_rate, &codec->payload_channels);
- PDEBUG(DCC, DEBUG_DEBUG, " -> payload type = %d\n", codec->payload_type_remote);
- if (codec->payload_name)
- PDEBUG(DCC, DEBUG_DEBUG, " -> payload name = %s\n", codec->payload_name);
- if (codec->payload_rate)
- PDEBUG(DCC, DEBUG_DEBUG, " -> payload rate = %d\n", codec->payload_rate);
- if (codec->payload_channels)
- PDEBUG(DCC, DEBUG_DEBUG, " -> payload channels = %d\n", codec->payload_channels);
- }
- break;
- case 'a':
- PDEBUG(DCC, DEBUG_DEBUG, " -> Attribute: %s\n", next_word);
- word = wordsep(&next_word);
- if (!strcmp(word, "sendrecv")) {
- if (media) {
- media->receive = 1;
- media->send = 1;
- } else {
- creceive = 1;
- csend = 1;
- }
- break;
- } else
- if (!strcmp(word, "recvonly")) {
- if (media) {
- media->receive = 1;
- media->send = 0;
- } else {
- creceive = 1;
- csend = 0;
- }
- break;
- } else
- if (!strcmp(word, "sendonly")) {
- if (media) {
- media->receive = 0;
- media->send = 1;
- } else {
- creceive = 0;
- csend = 1;
- }
- break;
- } else
- if (!strcmp(word, "inactive")) {
- if (media) {
- media->receive = 0;
- media->send = 0;
- } else {
- creceive = 0;
- csend = 0;
- }
- break;
- } else
- if (!media) {
- PDEBUG(DCC, DEBUG_NOTICE, "Attribute without previously defined media in SDP line %d = '%s'\n", line_no, line);
- break;
- }
- if (!strncmp(word, "rtpmap:", 7)) {
- int fmt = atoi(word + 7);
- osmo_cc_session_for_each_codec(media->codec_list, codec) {
- if (codec->payload_type_remote == fmt)
- break;
- }
- if (!codec) {
- PDEBUG(DCC, DEBUG_NOTICE, "Attribute without previously defined codec in SDP line %d = '%s'\n", line_no, line);
- break;
- }
- PDEBUG(DCC, DEBUG_DEBUG, " -> (rtpmap) payload type = %d\n", codec->payload_type_remote);
- if (!(word = wordsep(&next_word)))
- goto rtpmap_done;
- if ((p = strchr(word, '/')))
- *p++ = '\0';
- free((char *)codec->payload_name); // in case it is already set above
- codec->payload_name = strdup(word);
- PDEBUG(DCC, DEBUG_DEBUG, " -> (rtpmap) payload name = %s\n", codec->payload_name);
- if (!(word = p))
- goto rtpmap_done;
- if ((p = strchr(word, '/')))
- *p++ = '\0';
- codec->payload_rate = atoi(word);
- PDEBUG(DCC, DEBUG_DEBUG, " -> (rtpmap) payload rate = %d\n", codec->payload_rate);
- if (!(word = p)) {
- /* if no channel is given and no default was specified, we must set 1 channel */
- if (!codec->payload_channels)
- codec->payload_channels = 1;
- goto rtpmap_done;
- }
- codec->payload_channels = atoi(word);
- PDEBUG(DCC, DEBUG_DEBUG, " -> (rtpmap) payload channels = %d\n", codec->payload_channels);
- rtpmap_done:
- if (!codec->payload_name || !codec->payload_rate || !codec->payload_channels) {
- PDEBUG(DCC, DEBUG_NOTICE, "Broken 'rtpmap' definition in SDP line %d = '%s' Skipping codec!\n", line_no, line);
- osmo_cc_free_codec(codec);
- }
- }
- break;
- }
- }
-
- /* if something is incomplete, abort here */
- if (osmo_cc_session_check(session, 1)) {
- PDEBUG(DCC, DEBUG_NOTICE, "Parsing SDP failed.\n");
- osmo_cc_free_session(session);
- return NULL;
- }
-
- return session;
-}
-
-void osmo_cc_debug_sdp(const char *_sdp)
-{
- const unsigned char *sdp = (const unsigned char *)_sdp;
- char text[256];
- int i;
-
- while (*sdp) {
- for (i = 0; *sdp > 0 && *sdp >= 32 && i < (int)sizeof(text) - 1; i++)
- text[i] = *sdp++;
- text[i] = '\0';
- PDEBUG(DCC, DEBUG_DEBUG, " | %s\n", text);
- while (*sdp > 0 && *sdp < 32)
- sdp++;
- }
-}
-
diff --git a/src/libosmocc/sdp.h b/src/libosmocc/sdp.h
deleted file mode 100644
index c9bc721..0000000
--- a/src/libosmocc/sdp.h
+++ /dev/null
@@ -1,6 +0,0 @@
-
-char *osmo_cc_session_gensdp(struct osmo_cc_session *session);
-struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf, void *priv, const char *_sdp);
-int osmo_cc_payload_type_by_attrs(uint8_t *fmt, const char *name, uint32_t *rate, int *channels);
-void osmo_cc_debug_sdp(const char *sdp);
-
diff --git a/src/libosmocc/session.c b/src/libosmocc/session.c
deleted file mode 100644
index 427eca7..0000000
--- a/src/libosmocc/session.c
+++ /dev/null
@@ -1,640 +0,0 @@
-/* Osmo-CC: Media Session handling
- *
- * (C) 2016 by Andreas Eversberg <jolly@eversberg.eu>
- * All Rights Reserved
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <inttypes.h>
-#include "../libtimer/timer.h"
-#include "../libdebug/debug.h"
-#include "../liboptions/options.h"
-#include "endpoint.h"
-
-#define NTP_OFFSET 2208988800U
-
-void osmo_cc_set_local_peer(osmo_cc_session_config_t *conf, enum osmo_cc_session_nettype nettype, enum osmo_cc_session_addrtype addrtype, const char *address)
-{
- conf->default_nettype = nettype;
- conf->default_addrtype = addrtype;
- conf->default_unicast_address = options_strdup(address);
-}
-
-osmo_cc_session_t *osmo_cc_new_session(osmo_cc_session_config_t *conf, void *priv, const char *username, const char *sess_id, const char *sess_version, enum osmo_cc_session_nettype nettype, enum osmo_cc_session_addrtype addrtype, const char *unicast_address, const char *session_name, int debug)
-{
- osmo_cc_session_t *session;
-
- if (debug) PDEBUG(DCC, DEBUG_DEBUG, "Creating session structure.\n");
-
- session = calloc(1, sizeof(*session));
- if (!session) {
- PDEBUG(DCC, DEBUG_ERROR, "No mem!\n");
- abort();
- }
- session->config = conf;
- session->priv = priv;
- if (username) {
- int i;
- for (i = 0; username[i]; i++) {
- if ((uint8_t)username[i] < 33) {
- PDEBUG(DCC, DEBUG_ERROR, "Fatal error: SDP's originator (username) uses invalid characters, please fix!\n");
- abort();
- }
- }
- session->origin_local.username = strdup(username);
- }
- if (!username)
- session->origin_local.username = strdup("-");
- if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> user name = %s\n", session->origin_local.username);
- if (sess_id)
- session->origin_local.sess_id = strdup(sess_id);
- if (sess_version)
- session->origin_local.sess_version = strdup(sess_version);
- if (!sess_id || !sess_version) {
- struct timeval tv;
- char ntp_timestamp[32];
- /* get time NTP format time stamp (time since 1900) */
- gettimeofday(&tv, NULL);
- sprintf(ntp_timestamp, "%" PRIu64, (uint64_t)tv.tv_sec + NTP_OFFSET);
- if (!sess_id)
- session->origin_local.sess_id = strdup(ntp_timestamp);
- if (!sess_version)
- session->origin_local.sess_version = strdup(ntp_timestamp);
- }
- if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> session ID = %s\n", session->origin_local.sess_id);
- if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> session version = %s\n", session->origin_local.sess_version);
- if (nettype)
- session->origin_local.nettype = strdup(osmo_cc_session_nettype2string(nettype));
- else
- session->origin_local.nettype = strdup(osmo_cc_session_nettype2string(conf->default_nettype));
- if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> network type = %s\n", session->origin_local.nettype);
- if (addrtype)
- session->origin_local.addrtype = strdup(osmo_cc_session_addrtype2string(addrtype));
- else
- session->origin_local.addrtype = strdup(osmo_cc_session_addrtype2string(conf->default_addrtype));
- if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> address type = %s\n", session->origin_local.addrtype);
- if (unicast_address)
- session->origin_local.unicast_address = strdup(unicast_address);
- else
- session->origin_local.unicast_address = strdup(conf->default_unicast_address);
- if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> unicast address = %s\n", session->origin_local.unicast_address);
- if (session_name)
- session->name = strdup(session_name);
- if (!session_name)
- session->name = strdup("-");
- if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> session name = %s\n", session->name);
-
- return session;
-}
-
-void osmo_cc_free_session(osmo_cc_session_t *session)
-{
- PDEBUG(DCC, DEBUG_DEBUG, "Free session structure.\n");
-
- free((char *)session->origin_local.username);
- free((char *)session->origin_local.sess_id);
- free((char *)session->origin_local.sess_version);
- free((char *)session->origin_local.nettype);
- free((char *)session->origin_local.addrtype);
- free((char *)session->origin_local.unicast_address);
- free((char *)session->origin_remote.username);
- free((char *)session->origin_remote.sess_id);
- free((char *)session->origin_remote.sess_version);
- free((char *)session->origin_remote.nettype);
- free((char *)session->origin_remote.addrtype);
- free((char *)session->origin_remote.unicast_address);
- free((char *)session->name);
- while (session->media_list)
- osmo_cc_free_media(session->media_list);
- free(session);
-}
-
-osmo_cc_session_media_t *osmo_cc_add_media(osmo_cc_session_t *session, enum osmo_cc_session_nettype nettype, enum osmo_cc_session_addrtype addrtype, const char *address, enum osmo_cc_session_media_type type, uint16_t port, enum osmo_cc_session_media_proto proto, int send, int receive, void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len), int debug)
-{
- osmo_cc_session_config_t *conf = session->config;
- osmo_cc_session_media_t *media, **mediap;
-
- media = calloc(1, sizeof(*media));
- if (!media) {
- PDEBUG(DCC, DEBUG_ERROR, "No mem!\n");
- abort();
- }
- media->session = session;
- if (nettype)
- media->connection_data_local.nettype = nettype;
- else
- media->connection_data_local.nettype = conf->default_nettype;
- if (addrtype)
- media->connection_data_local.addrtype = addrtype;
- else
- media->connection_data_local.addrtype = conf->default_addrtype;
- if (address)
- media->connection_data_local.address = strdup(address);
- else
- media->connection_data_local.address = strdup(conf->default_unicast_address);
- media->description.type = type;
- media->description.port_local = port;
- media->description.proto = proto;
- media->send = send;
- media->receive = receive;
- media->receiver = receiver;
- media->tx_sequence = random();
- media->tx_timestamp = random();
- mediap = &media->session->media_list;
- while (*mediap)
- mediap = &((*mediap)->next);
- *mediap = media;
-
- if (debug) PDEBUG(DCC, DEBUG_DEBUG, "Adding session media.\n");
- if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> network type = %s\n", osmo_cc_session_nettype2string(media->connection_data_local.nettype));
- if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> address type = %s\n", osmo_cc_session_addrtype2string(media->connection_data_local.addrtype));
- if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> address = %s\n", media->connection_data_local.address);
- if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> media type = %s\n", osmo_cc_session_media_type2string(media->description.type));
- if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> media port = %d\n", media->description.port_local);
- if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> media proto = %s\n", osmo_cc_session_media_proto2string(media->description.proto));
- if (debug) PDEBUG(DCC, DEBUG_DEBUG, "Opening and binding media port %d\n", media->description.port_local);
-
- return media;
-}
-
-void osmo_cc_free_media(osmo_cc_session_media_t *media)
-{
- osmo_cc_session_media_t **mediap;
-
- PDEBUG(DCC, DEBUG_DEBUG, "Free session media.\n");
-
- osmo_cc_rtp_close(media);
- free((char *)media->connection_data_local.nettype_name);
- free((char *)media->connection_data_local.addrtype_name);
- free((char *)media->connection_data_local.address);
- free((char *)media->connection_data_remote.nettype_name);
- free((char *)media->connection_data_remote.addrtype_name);
- free((char *)media->connection_data_remote.address);
- while (media->codec_list)
- osmo_cc_free_codec(media->codec_list);
- mediap = &media->session->media_list;
- while (*mediap != media)
- mediap = &((*mediap)->next);
- *mediap = media->next;
- free(media);
-}
-
-osmo_cc_session_codec_t *osmo_cc_add_codec(osmo_cc_session_media_t *media, const char *payload_name, uint32_t payload_rate, int payload_channels, void (*encoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *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) {
- PDEBUG(DCC, DEBUG_ERROR, "No mem!\n");
- abort();
- }
- codec->media = media;
- if (payload_name) {
- codec->payload_name = strdup(payload_name);
- codec->payload_rate = payload_rate;
- codec->payload_channels = payload_channels;
- rc = osmo_cc_payload_type_by_attrs(&codec->payload_type_local, payload_name, &payload_rate, &payload_channels);
- if (rc < 0) {
- /* hunt for next free dynamic payload type */
- uint8_t fmt = 96;
- osmo_cc_session_codec_t *c;
- osmo_cc_session_for_each_codec(media->codec_list, c) {
- if (c->payload_type_local >= fmt)
- fmt = c->payload_type_local + 1;
- }
- codec->payload_type_local = fmt;
- }
- }
- codec->encoder = encoder;
- codec->decoder = decoder;
- codecp = &codec->media->codec_list;
- while (*codecp)
- codecp = &((*codecp)->next);
- *codecp = codec;
-
- if (debug) PDEBUG(DCC, DEBUG_DEBUG, "Adding session codec.\n");
- if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> payload type = %d\n", codec->payload_type_local);
- if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> payload name = %s\n", codec->payload_name);
- if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> payload rate = %d\n", codec->payload_rate);
- if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> payload channels = %d\n", codec->payload_channels);
-
- return codec;
-}
-
-void osmo_cc_free_codec(osmo_cc_session_codec_t *codec)
-{
- osmo_cc_session_codec_t **codecp;
-
- PDEBUG(DCC, DEBUG_DEBUG, "Free session codec.\n");
-
- free((char *)codec->payload_name);
- codecp = &codec->media->codec_list;
- while (*codecp != codec)
- codecp = &((*codecp)->next);
- *codecp = codec->next;
- free(codec);
-}
-
-int osmo_cc_session_check(osmo_cc_session_t *session, int remote)
-{
- struct osmo_cc_session_origin *orig;
- struct osmo_cc_session_media *media;
- struct osmo_cc_session_connection_data *cd;
- struct osmo_cc_session_media_description *md;
- struct osmo_cc_session_codec *codec;
- int i, j;
-
- if (remote)
- orig = &session->origin_remote;
- else
- orig = &session->origin_local;
- if (!orig->username
- || !orig->sess_id
- || !orig->sess_version
- || !orig->nettype
- || !orig->addrtype
- || !orig->unicast_address) {
- PDEBUG(DCC, DEBUG_NOTICE, "Missing data in session origin\n");
- return -EINVAL;
- }
- if (!session->name) {
- PDEBUG(DCC, DEBUG_NOTICE, "Missing data in session origin\n");
- return -EINVAL;
- }
- if (!session->media_list) {
- PDEBUG(DCC, DEBUG_NOTICE, "Missing media session\n");
- return -EINVAL;
- }
- i = 0;
- osmo_cc_session_for_each_media(session->media_list, media) {
- i++;
- if (remote)
- cd = &media->connection_data_remote;
- else
- cd = &media->connection_data_local;
- if (!cd->nettype && !cd->nettype_name) {
- PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d is missing connection network type\n", i);
- return -EINVAL;
- }
- if (!cd->addrtype && !cd->addrtype_name) {
- PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d is missing connection address type\n", i);
- return -EINVAL;
- }
- if (!cd->address) {
- PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d is missing connection address\n", i);
- return -EINVAL;
- }
- md = &media->description;
- if (!md->type && !md->type_name) {
- PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d is missing media type\n", i);
- return -EINVAL;
- }
- if (!md->proto && !md->proto_name) {
- PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d is missing protocol\n", i);
- return -EINVAL;
- }
- j = 0;
- osmo_cc_session_for_each_codec(media->codec_list, codec) {
- j++;
- if (!codec->payload_name) {
- PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d, codec #%d is missing name\n", i, j);
- return -EINVAL;
- }
- if (!codec->payload_rate) {
- PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d, codec #%d is missing rate\n", i, j);
- return -EINVAL;
- }
- if (!codec->payload_channels) {
- PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d, codec #%d is missing channel count\n", i, j);
- return -EINVAL;
- }
- }
- }
-
- return 0;
-}
-
-/* check session description and generate SDP */
-const char *osmo_cc_session_send_offer(osmo_cc_session_t *session)
-{
- const char *sdp;
- int rc;
-
- PDEBUG(DCC, DEBUG_DEBUG, "Generating session offer and opening RTP stream.\n");
-
- rc = osmo_cc_session_check(session, 0);
- if (rc < 0) {
- PDEBUG(DCC, DEBUG_ERROR, "Please fix!\n");
- abort();
- }
-
- sdp = osmo_cc_session_gensdp(session);
- osmo_cc_debug_sdp(sdp);
-
- return sdp;
-}
-
-osmo_cc_session_t *osmo_cc_session_receive_offer(osmo_cc_session_config_t *conf, void *priv, const char *sdp)
-{
- osmo_cc_session_t *session;
- int rc;
-
- PDEBUG(DCC, DEBUG_DEBUG, "Parsing session offer.\n");
-
- osmo_cc_debug_sdp(sdp);
- session = osmo_cc_session_parsesdp(conf, priv, sdp);
- if (!session)
- return NULL;
-
- rc = osmo_cc_session_check(session, 0);
- if (rc < 0) {
- osmo_cc_free_session(session);
- return NULL;
- }
-
- return session;
-}
-
-void osmo_cc_session_accept_media(osmo_cc_session_media_t *media, enum osmo_cc_session_nettype nettype, enum osmo_cc_session_addrtype addrtype, const char *address, int send, int receive, void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len))
-{
- osmo_cc_session_config_t *conf = media->session->config;
-
- media->accepted = 1;
- if (nettype)
- media->connection_data_local.nettype = nettype;
- else
- media->connection_data_local.nettype = conf->default_nettype;
- if (addrtype)
- media->connection_data_local.addrtype = addrtype;
- else
- media->connection_data_local.addrtype = conf->default_addrtype;
- free((char *)media->connection_data_local.address);
- if (address)
- media->connection_data_local.address = strdup(address);
- else
- media->connection_data_local.address = strdup(conf->default_unicast_address);
- media->send = send;
- media->receive = receive;
- media->receiver = receiver;
-
- PDEBUG(DCC, DEBUG_DEBUG, "Accepting session media.\n");
- PDEBUG(DCC, DEBUG_DEBUG, " -> network type = %s\n", osmo_cc_session_nettype2string(media->connection_data_local.nettype));
- PDEBUG(DCC, DEBUG_DEBUG, " -> address type = %s\n", osmo_cc_session_addrtype2string(media->connection_data_local.addrtype));
- PDEBUG(DCC, DEBUG_DEBUG, " -> address = %s\n", media->connection_data_local.address);
-}
-
-
-void osmo_cc_session_accept_codec(osmo_cc_session_codec_t *codec, void (*encoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *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;
-
- PDEBUG(DCC, DEBUG_DEBUG, "Accepting session codec.\n");
- PDEBUG(DCC, DEBUG_DEBUG, " -> payload type = %d\n", codec->payload_type_local);
- PDEBUG(DCC, DEBUG_DEBUG, " -> payload name = %s\n", codec->payload_name);
- PDEBUG(DCC, DEBUG_DEBUG, " -> payload rate = %d\n", codec->payload_rate);
- PDEBUG(DCC, DEBUG_DEBUG, " -> payload channels = %d\n", codec->payload_channels);
-}
-
-/* remove codecs/media that have not been accepted and generate SDP */
-const char *osmo_cc_session_send_answer(osmo_cc_session_t *session)
-{
- osmo_cc_session_media_t *media;
- osmo_cc_session_codec_t *codec, **codec_p;
- const char *sdp;
- int rc;
-
- PDEBUG(DCC, DEBUG_DEBUG, "Generating session answer.\n");
-
- /* loop all media */
- osmo_cc_session_for_each_media(session->media_list, media) {
- /* remove unaccepted codecs */
- codec_p = &media->codec_list;
- codec = *codec_p;
- while (codec) {
- if (!codec->accepted) {
- osmo_cc_free_codec(codec);
- codec = *codec_p;
- continue;
- }
- codec_p = &codec->next;
- codec = *codec_p;
- }
- /* mark media as unused, if no codec or not accepted */
- if (!media->accepted || !media->codec_list)
- media->description.port_local = 0;
- }
-
- rc = osmo_cc_session_check(session, 0);
- if (rc < 0) {
- PDEBUG(DCC, DEBUG_ERROR, "Please fix!\n");
- abort();
- }
-
- sdp = osmo_cc_session_gensdp(session);
- osmo_cc_debug_sdp(sdp);
-
- return sdp;
-}
-
-/* Apply remote session description to local session description.
- * If remote media's port is 0, remove from local session description.
- * If codecs in the remote session description are missing, remove from local session description.
- */
-static int osmo_cc_session_negotiate(osmo_cc_session_t *session_local, struct osmo_cc_session *session_remote)
-{
- osmo_cc_session_media_t *media_local, *media_remote, **media_local_p;
- osmo_cc_session_codec_t *codec_local, *codec_remote, **codec_local_p;
- int rc;
-
- PDEBUG(DCC, DEBUG_DEBUG, "Negotiating session.\n");
-
- /* copy remote session information */
- session_local->origin_remote.username = strdup(session_remote->origin_remote.username);
- session_local->origin_remote.sess_id = strdup(session_remote->origin_remote.sess_id);
- session_local->origin_remote.sess_version = strdup(session_remote->origin_remote.sess_version);
- session_local->origin_remote.nettype = strdup(session_remote->origin_remote.nettype);
- session_local->origin_remote.addrtype = strdup(session_remote->origin_remote.addrtype);
- session_local->origin_remote.unicast_address = strdup(session_remote->origin_remote.unicast_address);
-
- /* loop all media */
- for (media_local = session_local->media_list, media_remote = session_remote->media_list; media_local && media_remote; media_local = media_local->next, media_remote = media_remote->next) {
- /* copy remote media information */
- media_local->connection_data_remote.nettype = media_remote->connection_data_remote.nettype;
- if (media_remote->connection_data_remote.nettype_name)
- media_local->connection_data_remote.nettype_name = strdup(media_remote->connection_data_remote.nettype_name);
- media_local->connection_data_remote.addrtype = media_remote->connection_data_remote.addrtype;
- if (media_remote->connection_data_remote.addrtype_name)
- media_local->connection_data_remote.addrtype_name = strdup(media_remote->connection_data_remote.addrtype_name);
- if (media_remote->connection_data_remote.address)
- media_local->connection_data_remote.address = strdup(media_remote->connection_data_remote.address);
- media_local->description.port_remote = media_remote->description.port_remote;
- media_local->send = media_remote->send;
- media_local->receive = media_remote->receive;
- /* loop all codecs and remove if they are not found in local session description */
- codec_local_p = &media_local->codec_list;
- codec_local = *codec_local_p;
- while (codec_local) {
- /* search for equal codec, payload type may differe for each direction */
- osmo_cc_session_for_each_codec(media_remote->codec_list, codec_remote) {
- if (!strcmp(codec_local->payload_name, codec_remote->payload_name)
- && codec_local->payload_rate == codec_remote->payload_rate
- && codec_local->payload_channels == codec_remote->payload_channels)
- break;
- }
- if (!codec_remote) {
- osmo_cc_free_codec(codec_local);
- codec_local = *codec_local_p;
- continue;
- }
- /* copy remote codec information */
- codec_local->payload_type_remote = codec_remote->payload_type_remote;
- codec_local_p = &codec_local->next;
- codec_local = *codec_local_p;
- }
- }
- if (media_local) {
- PDEBUG(DCC, DEBUG_NOTICE, "Negotiation failed, because remote endpoint returns less media streams than we offered.\n");
- return -EINVAL;
- }
- if (media_remote) {
- PDEBUG(DCC, DEBUG_NOTICE, "Negotiation failed, because remote endpoint returns more media streams than we offered.\n");
- return -EINVAL;
- }
-
- /* remove media with port == 0 or no codec at all */
- media_local_p = &session_local->media_list;
- media_local = *media_local_p;
- while (media_local) {
- if (media_local->description.port_remote == 0 || !media_local->codec_list) {
- osmo_cc_free_media(media_local);
- media_local = *media_local_p;
- continue;
- }
- media_local_p = &media_local->next;
- media_local = *media_local_p;
- }
-
- rc = osmo_cc_session_check(session_local, 1);
- if (rc < 0)
- return rc;
-
- return 0;
-}
-
-int osmo_cc_session_receive_answer(osmo_cc_session_t *session, const char *sdp)
-{
- osmo_cc_session_t *session_remote;
- int rc;
-
- PDEBUG(DCC, DEBUG_DEBUG, "Parsing session answer.\n");
-
- osmo_cc_debug_sdp(sdp);
- session_remote = osmo_cc_session_parsesdp(session->config, NULL, sdp);
- if (!session_remote)
- return -EINVAL;
-
- rc = osmo_cc_session_check(session_remote, 1);
- if (rc < 0) {
- osmo_cc_free_session(session_remote);
- return rc;
- }
- rc = osmo_cc_session_negotiate(session, session_remote);
- if (rc < 0) {
- osmo_cc_free_session(session_remote);
- return rc;
- }
- osmo_cc_free_session(session_remote);
-
- return 0;
-}
-
-const char *osmo_cc_session_nettype2string(enum osmo_cc_session_nettype nettype)
-{
- switch (nettype) {
- case osmo_cc_session_nettype_inet:
- return "IN";
- default:
- return NULL;
- }
-}
-
-const char *osmo_cc_session_addrtype2string(enum osmo_cc_session_addrtype addrtype)
-{
- switch (addrtype) {
- case osmo_cc_session_addrtype_ipv4:
- return "IP4";
- case osmo_cc_session_addrtype_ipv6:
- return "IP6";
- default:
- return NULL;
- }
-}
-
-const char *osmo_cc_session_media_type2string(enum osmo_cc_session_media_type media_type)
-{
- switch (media_type) {
- case osmo_cc_session_media_type_audio:
- return "audio";
- case osmo_cc_session_media_type_video:
- return "video";
- default:
- return NULL;
- }
-}
-
-const char *osmo_cc_session_media_proto2string(enum osmo_cc_session_media_proto media_proto)
-{
- switch (media_proto) {
- case osmo_cc_session_media_proto_rtp:
- return "RTP/AVP";
- default:
- return NULL;
- }
-}
-
-int osmo_cc_session_if_codec(osmo_cc_session_codec_t *codec, const char *name, uint32_t rate, int channels)
-{
- return (!strcmp(codec->payload_name, name)
- && codec->payload_rate == rate
- && codec->payload_channels == channels);
-}
-
-int osmo_cc_session_handle(osmo_cc_session_t *session, void *codec_priv)
-{
- osmo_cc_session_media_t *media;
- int w = 0, rc;
-
- osmo_cc_session_for_each_media(session->media_list, media) {
- do {
- rc = osmo_cc_rtp_receive(media, codec_priv);
- if (rc >= 0)
- w = 1;
- } while (rc >= 0);
- }
-
- return w;
-}
-
diff --git a/src/libosmocc/session.h b/src/libosmocc/session.h
deleted file mode 100644
index 0330f51..0000000
--- a/src/libosmocc/session.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/* configuration */
-
-enum osmo_cc_session_nettype {
- osmo_cc_session_nettype_unknown = 0,
- osmo_cc_session_nettype_inet,
-};
-
-enum osmo_cc_session_addrtype {
- osmo_cc_session_addrtype_unknown = 0,
- osmo_cc_session_addrtype_ipv4,
- osmo_cc_session_addrtype_ipv6,
-};
-
-typedef struct osmo_cc_session_config {
- enum osmo_cc_session_nettype default_nettype;
- enum osmo_cc_session_addrtype default_addrtype;
- const char *default_unicast_address;
- uint16_t rtp_port_next;
- uint16_t rtp_port_from;
- uint16_t rtp_port_to;
-} osmo_cc_session_config_t;
-
-/* session description, global part: */
-
-typedef struct osmo_cc_session_origin {
- const char *username;
- const char *sess_id;
- const char *sess_version;
- const char *nettype;
- const char *addrtype;
- const char *unicast_address;
-} osmo_cc_session_origin_t;
-
-/* session instance */
-typedef struct osmo_cc_session {
- osmo_cc_session_config_t *config;
- void *priv;
- osmo_cc_session_origin_t origin_local, origin_remote;
- const char *name;
- struct osmo_cc_session_media *media_list;
-} osmo_cc_session_t;
-
-/* connection description: */
-
-typedef struct osmo_cc_session_connection_data {
- enum osmo_cc_session_nettype nettype;
- const char *nettype_name;
- enum osmo_cc_session_addrtype addrtype;
- const char *addrtype_name;
- const char *address;
-} osmo_cc_session_connection_data_t;
-
-/* one media of session description: */
-
-enum osmo_cc_session_media_type {
- osmo_cc_session_media_type_unknown,
- osmo_cc_session_media_type_audio,
- osmo_cc_session_media_type_video,
-};
-
-enum osmo_cc_session_media_proto {
- osmo_cc_session_media_proto_unknown,
- osmo_cc_session_media_proto_rtp,
-};
-
-typedef struct osmo_cc_session_media_description {
- enum osmo_cc_session_media_type type;
- const char *type_name;
- uint16_t port_local, port_remote;
- enum osmo_cc_session_media_proto proto;
- const char *proto_name;
-} osmo_cc_session_media_description_t;
-
-/* media entry */
-typedef struct osmo_cc_session_media {
- struct osmo_cc_session_media *next;
- osmo_cc_session_t *session;
- osmo_cc_session_media_description_t description;
- osmo_cc_session_connection_data_t connection_data_local, connection_data_remote;
- struct osmo_cc_session_codec *codec_list;
- int send, receive;
- void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len);
- int rtp_socket;
- int rtcp_socket;
- uint32_t tx_ssrc, rx_ssrc;
- uint16_t tx_sequence, rx_sequence;
- uint32_t tx_timestamp, rx_timestamp;
- int accepted;
-} osmo_cc_session_media_t;
-
-/* codec entry */
-typedef struct osmo_cc_session_codec {
- struct osmo_cc_session_codec *next;
- osmo_cc_session_media_t *media;
- uint8_t payload_type_local, payload_type_remote; /* local = towards local, remote = toward remote */
- const char *payload_name;
- uint32_t payload_rate;
- int payload_channels;
- void (*encoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *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);
-int osmo_cc_session_handle(osmo_cc_session_t *session, void *codec_priv);
-
diff --git a/src/libosmocc/socket.c b/src/libosmocc/socket.c
deleted file mode 100644
index d25e1f1..0000000
--- a/src/libosmocc/socket.c
+++ /dev/null
@@ -1,583 +0,0 @@
-/* Osmo-CC: Socket handling
- *
- * (C) 2016 by Andreas Eversberg <jolly@eversberg.eu>
- * All Rights Reserved
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include "../libdebug/debug.h"
-#include "../libtimer/timer.h"
-#include "message.h"
-#include "cause.h"
-#include "socket.h"
-
-static const char version_string[] = OSMO_CC_VERSION;
-
-static int _getaddrinfo(const char *host, uint16_t port, struct addrinfo **result)
-{
- char portstr[8];
- struct addrinfo hints;
- int rc;
-
- sprintf(portstr, "%d", port);
-
- /* bind socket */
- memset(&hints, 0, sizeof(struct addrinfo));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_PASSIVE;
- hints.ai_protocol = 0;
- hints.ai_canonname = NULL;
- hints.ai_addr = NULL;
- hints.ai_next = NULL;
-
- rc = getaddrinfo(host, portstr, &hints, result);
- if (rc < 0) {
- PDEBUG(DCC, DEBUG_ERROR, "Failed to create socket for host '%s', port '%d': %s.\n", host, port, gai_strerror(rc));
- return rc;
- }
- return rc;
-}
-
-/* send a reject message toward CC process.
- * the CC process will change the reject message to a release message when not in INIT_IN state
- */
-static void rej_msg(osmo_cc_socket_t *os, uint32_t callref, uint8_t socket_cause, uint8_t isdn_cause, uint16_t sip_cause)
-{
- osmo_cc_msg_t *msg;
-
- /* create message */
- msg = osmo_cc_new_msg(OSMO_CC_MSG_REJ_REQ);
- if (!msg)
- abort();
-
- /* add cause */
- osmo_cc_add_ie_cause(msg, os->location, isdn_cause, sip_cause, socket_cause);
- osmo_cc_convert_cause_msg(msg);
-
- /* message down */
- os->recv_msg_cb(os->priv, callref, msg);
-}
-
-void tx_keepalive_timeout(struct timer *timer)
-{
- osmo_cc_conn_t *conn = (osmo_cc_conn_t *)timer->priv;
- osmo_cc_msg_t *msg;
-
- /* send keepalive message */
- msg = osmo_cc_new_msg(OSMO_CC_MSG_DUMMY_REQ);
- osmo_cc_msg_list_enqueue(&conn->os->write_list, msg, conn->callref);
- timer_start(&conn->tx_keepalive_timer, OSMO_CC_SOCKET_TX_KEEPALIVE);
-}
-
-static void close_conn(osmo_cc_conn_t *conn, uint8_t socket_cause);
-
-void rx_keepalive_timeout(struct timer *timer)
-{
- osmo_cc_conn_t *conn = (osmo_cc_conn_t *)timer->priv;
-
- PDEBUG(DCC, DEBUG_ERROR, "OsmoCC-Socket failed due to timeout.\n");
- close_conn(conn, OSMO_CC_SOCKET_CAUSE_TIMEOUT);
-}
-
-/* create socket process and bind socket */
-int osmo_cc_open_socket(osmo_cc_socket_t *os, const char *host, uint16_t port, void *priv, void (*recv_msg_cb)(void *priv, uint32_t callref, osmo_cc_msg_t *msg), uint8_t location)
-{
- int try = 0, auto_port = 0;
- struct addrinfo *result, *rp;
- int rc, sock, flags;
-
- memset(os, 0, sizeof(*os));
-
-try_again:
- /* check for given port, if NULL, autoselect port */
- if (!port || auto_port) {
- port = OSMO_CC_DEFAULT_PORT + try;
- try++;
- auto_port = 1;
- }
-
- PDEBUG(DCC, DEBUG_DEBUG, "Create socket for host %s port %d.\n", host, port);
-
- rc = _getaddrinfo(host, port, &result);
- if (rc < 0)
- return rc;
- for (rp = result; rp; rp = rp->ai_next) {
- int on = 1;
- sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
- if (sock < 0)
- continue;
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&on, sizeof(on));
- rc = bind(sock, rp->ai_addr, rp->ai_addrlen);
- if (rc == 0)
- break;
- close(sock);
- }
- freeaddrinfo(result);
- if (rp == NULL) {
- if (auto_port && port < OSMO_CC_DEFAULT_PORT_MAX) {
- PDEBUG(DCC, DEBUG_DEBUG, "Failed to bind host %s port %d, trying again.\n", host, port);
- goto try_again;
- }
- PDEBUG(DCC, DEBUG_ERROR, "Failed to bind given host %s port %d.\n", host, port);
- return -EIO;
- }
-
- /* listen to socket */
- rc = listen(sock, 10);
- if (rc < 0) {
- PDEBUG(DCC, DEBUG_ERROR, "Failed to listen on socket.\n");
- return rc;
- }
-
- /* set nonblocking io */
- flags = fcntl(sock, F_GETFL);
- flags |= O_NONBLOCK;
- fcntl(sock, F_SETFL, flags);
-
- os->socket = sock;
- os->recv_msg_cb = recv_msg_cb;
- os->priv = priv;
- os->location = location;
-
- return port;
-}
-
-/* create a connection */
-static osmo_cc_conn_t *open_conn(osmo_cc_socket_t *os, int sock, uint32_t callref, int read_setup)
-{
- osmo_cc_conn_t *conn, **connp;
-
- /* create connection */
- conn = calloc(1, sizeof(*conn));
- if (!conn) {
- PDEBUG(DCC, DEBUG_ERROR, "No mem!\n");
- abort();
- }
- conn->os = os;
- conn->socket = sock;
- conn->read_version = 1;
- conn->write_version = 1;
- conn->read_setup = read_setup;
- if (callref)
- conn->callref = callref;
- else
- conn->callref = osmo_cc_new_callref();
-
- timer_init(&conn->tx_keepalive_timer, tx_keepalive_timeout, conn);
- timer_init(&conn->rx_keepalive_timer, rx_keepalive_timeout, conn);
- timer_start(&conn->tx_keepalive_timer, OSMO_CC_SOCKET_TX_KEEPALIVE);
- timer_start(&conn->rx_keepalive_timer, OSMO_CC_SOCKET_RX_KEEPALIVE);
-
- PDEBUG(DCC, DEBUG_DEBUG, "New socket connection (callref %d).\n", conn->callref);
-
- /* attach to list */
- connp = &os->conn_list;
- while (*connp)
- connp = &((*connp)->next);
- *connp = conn;
-
- return conn;
-}
-
-/* remove a connection */
-static void close_conn(osmo_cc_conn_t *conn, uint8_t socket_cause)
-{
- osmo_cc_conn_t **connp;
- osmo_cc_msg_list_t *ml;
-
- /* detach connection first, to prevent a destruction during message handling (double free) */
- connp = &conn->os->conn_list;
- while (*connp != conn)
- connp = &((*connp)->next);
- *connp = conn->next;
- /* send reject message, if socket_cause is set */
- if (socket_cause && !conn->read_setup) {
- /* receive a release or reject (depending on state), but only if we sent a setup */
- rej_msg(conn->os, conn->callref, socket_cause, 0, 0);
- }
-
- PDEBUG(DCC, DEBUG_DEBUG, "Destroy socket connection (callref %d).\n", conn->callref);
-
- /* close socket */
- if (conn->socket)
- close(conn->socket);
- /* free partly received message */
- if (conn->read_msg)
- osmo_cc_free_msg(conn->read_msg);
- /* free send queue */
- while ((ml = conn->write_list)) {
- osmo_cc_free_msg(ml->msg);
- conn->write_list = ml->next;
- free(ml);
- }
- /* free timers */
- timer_exit(&conn->tx_keepalive_timer);
- timer_exit(&conn->rx_keepalive_timer);
- /* free connection (already detached above) */
- free(conn);
-}
-
-/* close socket and remove */
-void osmo_cc_close_socket(osmo_cc_socket_t *os)
-{
- osmo_cc_msg_list_t *ml;
-
- PDEBUG(DCC, DEBUG_DEBUG, "Destroy socket.\n");
-
- /* free all connections */
- while (os->conn_list)
- close_conn(os->conn_list, 0);
- /* close socket */
- if (os->socket > 0) {
- close(os->socket);
- os->socket = 0;
- }
- /* free send queue */
- while ((ml = os->write_list)) {
- osmo_cc_free_msg(ml->msg);
- os->write_list = ml->next;
- free(ml);
- }
-}
-
-/* send message to send_queue of sock instance */
-int osmo_cc_sock_send_msg(osmo_cc_socket_t *os, uint32_t callref, osmo_cc_msg_t *msg, const char *host, uint16_t port)
-{
- osmo_cc_msg_list_t *ml;
-
- /* turn _IND into _REQ and _CNF into _RSP */
- msg->type &= ~1;
-
- /* create list entry */
- ml = osmo_cc_msg_list_enqueue(&os->write_list, msg, callref);
- if (host)
- strncpy(ml->host, host, sizeof(ml->host) - 1);
- ml->port = port;
-
- return 0;
-}
-
-/* receive message
- * return 1 if work was done.
- */
-static int receive_conn(osmo_cc_conn_t *conn)
-{
- uint8_t socket_cause = OSMO_CC_SOCKET_CAUSE_BROKEN_PIPE;
- int rc;
- osmo_cc_msg_t *msg;
- uint8_t msg_type;
- int len;
- int work = 0;
-
- /* get version from remote */
- if (conn->read_version) {
- rc = recv(conn->socket, conn->read_version_string + conn->read_version_pos, strlen(version_string) - conn->read_version_pos, 0);
- if (rc < 0 && errno == EAGAIN)
- return work;
- work = 1;
- if (rc <= 0) {
- goto close;
- }
- conn->read_version_pos += rc;
- if (conn->read_version_pos == strlen(version_string)) {
- conn->read_version = 0;
- if (!!memcmp(conn->read_version_string, version_string, strlen(version_string) - 1)) {
- PDEBUG(DCC, DEBUG_NOTICE, "Remote does not seem to be an Osmo-CC socket, rejecting!\n");
- socket_cause = OSMO_CC_SOCKET_CAUSE_FAILED;
- goto close;
- }
- if (conn->read_version_string[strlen(version_string) - 1] != version_string[strlen(version_string) - 1]) {
- PDEBUG(DCC, DEBUG_NOTICE, "Remote Osmo-CC socket has wrong version (local=%s, remote=%s), rejecting!\n", version_string, conn->read_version_string);
- socket_cause = OSMO_CC_SOCKET_CAUSE_VERSION_MISMATCH;
- goto close;
- }
- } else
- return work;
- }
-
-try_next_message:
- /* read message header from remote */
- if (!conn->read_msg) {
- rc = recv(conn->socket, ((uint8_t *)&conn->read_hdr) + conn->read_pos, sizeof(conn->read_hdr) - conn->read_pos, 0);
- if (rc < 0 && errno == EAGAIN)
- return work;
- work = 1;
- if (rc <= 0) {
- goto close;
- }
- conn->read_pos += rc;
- if (conn->read_pos == sizeof(conn->read_hdr)) {
- conn->read_msg = osmo_cc_new_msg(conn->read_hdr.type);
- if (!conn->read_msg)
- abort();
- conn->read_msg->length_networkorder = conn->read_hdr.length_networkorder;
- /* prepare for reading message */
- conn->read_pos = 0;
- } else
- return work;
- }
-
- /* read message data from remote */
- msg = conn->read_msg;
- len = ntohs(msg->length_networkorder);
- if (len == 0)
- goto empty_message;
- rc = recv(conn->socket, msg->data + conn->read_pos, len - conn->read_pos, 0);
- if (rc < 0 && errno == EAGAIN)
- return work;
- work = 1;
- if (rc <= 0) {
- goto close;
- }
- conn->read_pos += rc;
- if (conn->read_pos == len) {
-empty_message:
- /* start RX keepalive timeer, if not already */
- timer_start(&conn->rx_keepalive_timer, OSMO_CC_SOCKET_RX_KEEPALIVE);
- /* we got our setup message, so we clear the flag */
- conn->read_setup = 0;
- /* prepare for reading header */
- conn->read_pos = 0;
- /* detach message first, because the connection might be destroyed during message handling */
- msg_type = conn->read_msg->type;
- conn->read_msg = NULL;
- /* drop dummy or forward message */
- if (msg_type == OSMO_CC_MSG_DUMMY_REQ)
- osmo_cc_free_msg(msg);
- else
- conn->os->recv_msg_cb(conn->os->priv, conn->callref, msg);
- if (msg_type == OSMO_CC_MSG_REL_REQ || msg_type == OSMO_CC_MSG_REJ_REQ) {
- PDEBUG(DCC, DEBUG_DEBUG, "closing socket because we received a release or reject message.\n");
- close_conn(conn, 0);
- return 1; /* conn removed */
- }
- goto try_next_message;
- }
- return work;
-
-close:
- PDEBUG(DCC, DEBUG_ERROR, "OsmoCC-Socket failed, socket cause %d.\n", socket_cause);
- close_conn(conn, socket_cause);
- return work; /* conn removed */
-}
-
-/* transmit message
- * return 1 if work was done.
- */
-static int transmit_conn(osmo_cc_conn_t *conn)
-{
- uint8_t socket_cause = OSMO_CC_SOCKET_CAUSE_BROKEN_PIPE;
- int rc;
- osmo_cc_msg_t *msg;
- int len;
- osmo_cc_msg_list_t *ml;
- int work = 0;
-
- /* send socket version to remote */
- if (conn->write_version) {
- rc = write(conn->socket, version_string, strlen(version_string));
- if (rc < 0 && errno == EAGAIN)
- return work;
- work = 1;
- if (rc <= 0) {
- goto close;
- }
- if (rc != strlen(version_string)) {
- PDEBUG(DCC, DEBUG_ERROR, "short write, please fix handling!\n");
- abort();
- }
- conn->write_version = 0;
- }
-
- /* send message to remote */
- while (conn->write_list) {
- timer_stop(&conn->tx_keepalive_timer);
- msg = conn->write_list->msg;
- len = sizeof(*msg) + ntohs(msg->length_networkorder);
- rc = write(conn->socket, msg, len);
- if (rc < 0 && errno == EAGAIN)
- return work;
- work = 1;
- if (rc <= 0) {
- goto close;
- }
- if (rc != len) {
- PDEBUG(DCC, DEBUG_ERROR, "short write, please fix handling!\n");
- abort();
- }
- /* close socket after sending release/reject message */
- if (msg->type == OSMO_CC_MSG_REL_REQ || msg->type == OSMO_CC_MSG_REJ_REQ) {
- PDEBUG(DCC, DEBUG_DEBUG, "closing socket because we sent a release or reject message.\n");
- close_conn(conn, 0);
- return work; /* conn removed */
- }
- /* free message after sending */
- ml = conn->write_list;
- conn->write_list = ml->next;
- osmo_cc_free_msg(msg);
- free(ml);
- }
-
- /* start TX keepalive timeer, if not already
- * because we stop at every message above, we actually restart the timer here.
- * only if there is no message for the amount of time, the timer fires.
- */
- if (!timer_running(&conn->tx_keepalive_timer))
- timer_start(&conn->tx_keepalive_timer, OSMO_CC_SOCKET_TX_KEEPALIVE);
-
- return work;
-
-close:
- PDEBUG(DCC, DEBUG_NOTICE, "OsmoCC-Socket failed.\n");
- close_conn(conn, socket_cause);
- return work; /* conn removed */
-}
-
-/* handle all sockets of a socket interface
- * return 1 if work was done.
- */
-int osmo_cc_handle_socket(osmo_cc_socket_t *os)
-{
- struct sockaddr_storage sa;
- socklen_t slen = sizeof(sa);
- int sock;
- osmo_cc_conn_t *conn;
- osmo_cc_msg_list_t *ml, **mlp;
- int flags;
- struct addrinfo *result, *rp;
- int rc;
- int work = 0;
-
- /* handle messages in send queue */
- while ((ml = os->write_list)) {
- work = 1;
- /* detach list entry */
- os->write_list = ml->next;
- ml->next = NULL;
- /* search for socket connection */
- for (conn = os->conn_list; conn; conn=conn->next) {
- if (conn->callref == ml->callref)
- break;
- }
- if (conn) {
- /* attach to list */
- mlp = &conn->write_list;
- while (*mlp)
- mlp = &((*mlp)->next);
- *mlp = ml;
- /* done with message */
- continue;
- }
-
- /* reject and release are ignored */
- if (ml->msg->type == OSMO_CC_MSG_REJ_REQ
- || ml->msg->type == OSMO_CC_MSG_REL_REQ) {
- /* drop message */
- osmo_cc_free_msg(ml->msg);
- free(ml);
- /* done with message */
- continue;
- }
-
- /* reject, if this is not a setup message */
- if (ml->msg->type != OSMO_CC_MSG_SETUP_REQ
- && ml->msg->type != OSMO_CC_MSG_ATTACH_REQ) {
- PDEBUG(DCC, DEBUG_ERROR, "Message with unknown callref.\n");
- rej_msg(os, ml->callref, 0, OSMO_CC_ISDN_CAUSE_INVAL_CALLREF, 0);
- /* drop message */
- osmo_cc_free_msg(ml->msg);
- free(ml);
- /* done with message */
- continue;
- }
- /* connect to remote */
- rc = _getaddrinfo(ml->host, ml->port, &result);
- if (rc < 0) {
- rej_msg(os, ml->callref, OSMO_CC_SOCKET_CAUSE_FAILED, 0, 0);
- /* drop message */
- osmo_cc_free_msg(ml->msg);
- free(ml);
- /* done with message */
- continue;
- }
- for (rp = result; rp; rp = rp->ai_next) {
- sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
- if (sock < 0)
- continue;
- /* set nonblocking io */
- flags = fcntl(sock, F_GETFL);
- flags |= O_NONBLOCK;
- fcntl(sock, F_SETFL, flags);
- /* connect */
- rc = connect(sock, rp->ai_addr, rp->ai_addrlen);
- if (rc == 0 || errno == EINPROGRESS)
- break;
- close(sock);
- }
- freeaddrinfo(result);
- if (rp == NULL) {
- PDEBUG(DCC, DEBUG_ERROR, "Failed to connect to given host %s port %d.\n", ml->host, ml->port);
- rej_msg(os, ml->callref, OSMO_CC_SOCKET_CAUSE_FAILED, 0, 0);
- /* drop message */
- osmo_cc_free_msg(ml->msg);
- free(ml);
- /* done with message */
- continue;
- }
- /* create connection */
- conn = open_conn(os, sock, ml->callref, 0);
- /* attach to list */
- conn->write_list = ml;
- /* done with (setup) message */
- }
-
- /* handle new socket connection */
- while ((sock = accept(os->socket, (struct sockaddr *)&sa, &slen)) > 0) {
- work = 1;
- /* set nonblocking io */
- flags = fcntl(sock, F_GETFL);
- flags |= O_NONBLOCK;
- fcntl(sock, F_SETFL, flags);
- /* create connection */
- open_conn(os, sock, 0, 1);
- }
-
- /* start with list after each read/write, because while handling (the message), one or more connections may be destroyed */
- for (conn = os->conn_list; conn; conn=conn->next) {
- /* check for rx */
- work = receive_conn(conn);
- /* if "change" is set, connection list might have changed, so we restart processing the list */
- if (work)
- break;
- /* check for tx */
- work = transmit_conn(conn);
- /* if "change" is set, connection list might have changed, so we restart processing the list */
- if (work)
- break;
- }
-
- return work;
-}
-
diff --git a/src/libosmocc/socket.h b/src/libosmocc/socket.h
deleted file mode 100644
index bcd8b7c..0000000
--- a/src/libosmocc/socket.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef OSMO_CC_SOCKET_H
-#define OSMO_CC_SOCKET_H
-
-#define OSMO_CC_DEFAULT_PORT 4200
-#define OSMO_CC_DEFAULT_PORT_MAX 4219
-
-#define OSMO_CC_SOCKET_TX_KEEPALIVE 10.0
-#define OSMO_CC_SOCKET_RX_KEEPALIVE 20.0
-
-struct osmo_cc_socket;
-
-typedef struct osmo_cc_conn {
- struct osmo_cc_conn *next;
- struct osmo_cc_socket *os;
- int socket;
- uint32_t callref;
- int read_setup;
- int read_version;
- char read_version_string[sizeof(OSMO_CC_VERSION)]; /* must include 0-termination */
- int read_version_pos;
- int write_version;
- osmo_cc_msg_t read_hdr;
- osmo_cc_msg_t *read_msg;
- int read_pos;
- osmo_cc_msg_list_t *write_list;
- struct timer tx_keepalive_timer;
- struct timer rx_keepalive_timer;
-} osmo_cc_conn_t;
-
-typedef struct osmo_cc_socket {
- int socket;
- osmo_cc_conn_t *conn_list;
- osmo_cc_msg_list_t *write_list;
- void (*recv_msg_cb)(void *priv, uint32_t callref, osmo_cc_msg_t *msg);
- void *priv;
- uint8_t location;
-} osmo_cc_socket_t;
-
-int osmo_cc_open_socket(osmo_cc_socket_t *os, const char *host, uint16_t port, void *priv, void (*recv_msg_cb)(void *priv, uint32_t callref, osmo_cc_msg_t *msg), uint8_t location);
-void osmo_cc_close_socket(osmo_cc_socket_t *os);
-int osmo_cc_sock_send_msg(osmo_cc_socket_t *os, uint32_t callref, osmo_cc_msg_t *msg, const char *host, uint16_t port);
-int osmo_cc_handle_socket(osmo_cc_socket_t *os);
-
-#endif /* OSMO_CC_SOCKET_H */