Updated libs

This commit is contained in:
Andreas Eversberg 2023-01-27 09:02:18 +01:00
parent 7ffa1c11a0
commit 7da5a3f42b
21 changed files with 600 additions and 449 deletions

View File

@ -84,3 +84,10 @@ extern int debug_limit_scroll;
const char *debug_hex(const uint8_t *data, int len); const char *debug_hex(const uint8_t *data, int len);
#define LOGP PDEBUG
#define LOGL_DEBUG DEBUG_DEBUG
#define LOGL_INFO DEBUG_INFO
#define LOGL_NOTICE DEBUG_NOTICE
#define LOGL_ERROR DEBUG_ERROR
#define osmo_hexdump debug_hex

View File

@ -242,7 +242,7 @@ void g711_init(void)
g711_initialized = 1; g711_initialized = 1;
} }
void g711_encode_alaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) void g711_encode_alaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void __attribute__((unused)) *priv)
{ {
int16_t *src = (int16_t *)src_data; int16_t *src = (int16_t *)src_data;
uint8_t *dst; uint8_t *dst;
@ -262,7 +262,7 @@ void g711_encode_alaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data
*dst_len = len; *dst_len = len;
} }
void g711_encode_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) void g711_encode_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void __attribute__((unused)) *priv)
{ {
int16_t *src = (int16_t *)src_data; int16_t *src = (int16_t *)src_data;
uint8_t *dst; uint8_t *dst;
@ -282,7 +282,7 @@ void g711_encode_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data
*dst_len = len; *dst_len = len;
} }
void g711_decode_alaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) void g711_decode_alaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void __attribute__((unused)) *priv)
{ {
uint8_t *src = src_data; uint8_t *src = src_data;
int16_t *dst; int16_t *dst;
@ -302,7 +302,7 @@ void g711_decode_alaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data
*dst_len = len * 2; *dst_len = len * 2;
} }
void g711_decode_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) void g711_decode_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void __attribute__((unused)) *priv)
{ {
uint8_t *src = src_data; uint8_t *src = src_data;
int16_t *dst; int16_t *dst;
@ -322,7 +322,7 @@ void g711_decode_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data
*dst_len = len * 2; *dst_len = len * 2;
} }
void g711_encode_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) void g711_encode_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void __attribute__((unused)) *priv)
{ {
int16_t *src = (int16_t *)src_data; int16_t *src = (int16_t *)src_data;
uint8_t *dst; uint8_t *dst;
@ -342,7 +342,7 @@ void g711_encode_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *d
*dst_len = len; *dst_len = len;
} }
void g711_encode_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) void g711_encode_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void __attribute__((unused)) *priv)
{ {
int16_t *src = (int16_t *)src_data; int16_t *src = (int16_t *)src_data;
uint8_t *dst; uint8_t *dst;
@ -362,7 +362,7 @@ void g711_encode_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *d
*dst_len = len; *dst_len = len;
} }
void g711_decode_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) void g711_decode_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void __attribute__((unused)) *priv)
{ {
uint8_t *src = src_data; uint8_t *src = src_data;
int16_t *dst; int16_t *dst;
@ -382,7 +382,7 @@ void g711_decode_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *d
*dst_len = len * 2; *dst_len = len * 2;
} }
void g711_decode_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) void g711_decode_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void __attribute__((unused)) *priv)
{ {
uint8_t *src = src_data; uint8_t *src = src_data;
int16_t *dst; int16_t *dst;
@ -402,7 +402,7 @@ void g711_decode_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *d
*dst_len = len * 2; *dst_len = len * 2;
} }
void g711_transcode_alaw_to_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) void g711_transcode_alaw_to_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void __attribute__((unused)) *priv)
{ {
uint8_t *src = src_data, *dst; uint8_t *src = src_data, *dst;
int len = src_len, i; int len = src_len, i;
@ -421,7 +421,7 @@ void g711_transcode_alaw_to_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_d
*dst_len = len; *dst_len = len;
} }
void g711_transcode_alaw_flipped_to_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) void g711_transcode_alaw_flipped_to_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void __attribute__((unused)) *priv)
{ {
uint8_t *src = src_data, *dst; uint8_t *src = src_data, *dst;
int len = src_len, i; int len = src_len, i;
@ -440,7 +440,7 @@ void g711_transcode_alaw_flipped_to_ulaw(uint8_t *src_data, int src_len, uint8_t
*dst_len = len; *dst_len = len;
} }
void g711_transcode_alaw_to_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) void g711_transcode_alaw_to_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void __attribute__((unused)) *priv)
{ {
uint8_t *src = src_data, *dst; uint8_t *src = src_data, *dst;
int len = src_len, i; int len = src_len, i;
@ -459,7 +459,7 @@ void g711_transcode_alaw_to_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t
*dst_len = len; *dst_len = len;
} }
void g711_transcode_ulaw_to_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) void g711_transcode_ulaw_to_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void __attribute__((unused)) *priv)
{ {
uint8_t *src = src_data, *dst; uint8_t *src = src_data, *dst;
int len = src_len, i; int len = src_len, i;
@ -478,7 +478,7 @@ void g711_transcode_ulaw_to_alaw(uint8_t *src_data, int src_len, uint8_t **dst_d
*dst_len = len; *dst_len = len;
} }
void g711_transcode_ulaw_flipped_to_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) void g711_transcode_ulaw_flipped_to_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void __attribute__((unused)) *priv)
{ {
uint8_t *src = src_data, *dst; uint8_t *src = src_data, *dst;
int len = src_len, i; int len = src_len, i;
@ -497,7 +497,7 @@ void g711_transcode_ulaw_flipped_to_alaw(uint8_t *src_data, int src_len, uint8_t
*dst_len = len; *dst_len = len;
} }
void g711_transcode_ulaw_to_alaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) void g711_transcode_ulaw_to_alaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void __attribute__((unused)) *priv)
{ {
uint8_t *src = src_data, *dst; uint8_t *src = src_data, *dst;
int len = src_len, i; int len = src_len, i;
@ -516,7 +516,7 @@ void g711_transcode_ulaw_to_alaw_flipped(uint8_t *src_data, int src_len, uint8_t
*dst_len = len; *dst_len = len;
} }
void g711_transcode_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len) void g711_transcode_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void __attribute__((unused)) *priv)
{ {
uint8_t *src = src_data, *dst; uint8_t *src = src_data, *dst;
int len = src_len, i; int len = src_len, i;

View File

@ -1,17 +1,17 @@
void g711_init(void); void g711_init(void);
void g711_encode_alaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); void g711_encode_alaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv);
void g711_encode_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); void g711_encode_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv);
void g711_decode_alaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); void g711_decode_alaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv);
void g711_decode_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); void g711_decode_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv);
void g711_encode_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); void g711_encode_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv);
void g711_encode_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); void g711_encode_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv);
void g711_decode_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); void g711_decode_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv);
void g711_decode_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); void g711_decode_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv);
void g711_transcode_alaw_to_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); void g711_transcode_alaw_to_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv);
void g711_transcode_alaw_flipped_to_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); void g711_transcode_alaw_flipped_to_ulaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv);
void g711_transcode_alaw_to_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); void g711_transcode_alaw_to_ulaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv);
void g711_transcode_ulaw_to_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); void g711_transcode_ulaw_to_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv);
void g711_transcode_ulaw_flipped_to_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); void g711_transcode_ulaw_flipped_to_alaw(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv);
void g711_transcode_ulaw_to_alaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); void g711_transcode_ulaw_to_alaw_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv);
void g711_transcode_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); void g711_transcode_flipped(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv);

View File

@ -24,6 +24,7 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <unistd.h> #include <unistd.h>
#include "../libtimer/timer.h" #include "../libtimer/timer.h"
#include "../libselect/select.h"
#include "../libdebug/debug.h" #include "../libdebug/debug.h"
#include "endpoint.h" #include "endpoint.h"
@ -35,11 +36,11 @@ static osmo_cc_call_t *call_new(osmo_cc_endpoint_t *ep, uint32_t callref)
call = calloc(1, sizeof(*call)); call = calloc(1, sizeof(*call));
if (!call) { if (!call) {
PDEBUG(DCC, DEBUG_ERROR, "No memory for call process instance.\n"); LOGP(DCC, LOGL_ERROR, "No memory for call process instance.\n");
abort(); abort();
} }
PDEBUG(DCC, DEBUG_DEBUG, "Creating new call with callref %u.\n", callref); LOGP(DCC, LOGL_DEBUG, "Creating new call with callref %u.\n", callref);
call->ep = ep; call->ep = ep;
call->callref = callref; call->callref = callref;
@ -58,7 +59,7 @@ static void call_delete(osmo_cc_call_t *call)
{ {
osmo_cc_call_t **cp; osmo_cc_call_t **cp;
PDEBUG(DCC, DEBUG_DEBUG, "Destroying call with callref %u.\n", call->callref); LOGP(DCC, LOGL_DEBUG, "Destroying call with callref %u.\n", call->callref);
/* detach from call process list */ /* detach from call process list */
cp = &call->ep->call_list; cp = &call->ep->call_list;
@ -104,7 +105,7 @@ static const char *state_names[] = {
static void new_call_state(osmo_cc_call_t *call, enum osmo_cc_state new_state) 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]); LOGP(DCC, LOGL_DEBUG, "Changing call state with callref %u from %s to %s.\n", call->callref, state_names[call->state], state_names[new_state]);
call->state = new_state; call->state = new_state;
} }
@ -159,12 +160,12 @@ static int split_address(const char *address, const char **host_p, uint16_t *por
*host_p = osmo_cc_host_of_address(address); *host_p = osmo_cc_host_of_address(address);
if (!(*host_p)) { if (!(*host_p)) {
PDEBUG(DCC, DEBUG_ERROR, "Host IP in given address '%s' is invalid.\n", address); LOGP(DCC, LOGL_ERROR, "Host IP in given address '%s' is invalid.\n", address);
return -EINVAL; return -EINVAL;
} }
portstring = osmo_cc_port_of_address(address); portstring = osmo_cc_port_of_address(address);
if (!portstring) { if (!portstring) {
PDEBUG(DCC, DEBUG_ERROR, "Port number in given address '%s' is not specified or invalid.\n", address); LOGP(DCC, LOGL_ERROR, "Port number in given address '%s' is not specified or invalid.\n", address);
return -EINVAL; return -EINVAL;
} }
*port_p = atoi(portstring); *port_p = atoi(portstring);
@ -219,7 +220,7 @@ static void forward_to_ul(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
if (address && msg->type == OSMO_CC_MSG_SETUP_IND) { if (address && msg->type == OSMO_CC_MSG_SETUP_IND) {
rc = split_address(address, &host, &port); rc = split_address(address, &host, &port);
if (rc < 0) { if (rc < 0) {
PDEBUG(DCC, DEBUG_ERROR, "Given remote peer's address '%s' in setup message is invalid, rejecting call.\n", address); LOGP(DCC, LOGL_ERROR, "Given remote peer's address '%s' in setup message is invalid, rejecting call.\n", address);
reject: reject:
/* reject, due to error */ /* reject, due to error */
osmo_cc_free_msg(msg); osmo_cc_free_msg(msg);
@ -228,21 +229,21 @@ reject:
call_delete(call); call_delete(call);
return; return;
} }
PDEBUG(DCC, DEBUG_DEBUG, "Using host IP '%s' and port '%d' from setup message.\n", host, port); LOGP(DCC, LOGL_DEBUG, "Using host IP '%s' and port '%d' from setup message.\n", host, port);
} }
/* for attach message, use remote peer */ /* for attach message, use remote peer */
if (msg->type == OSMO_CC_MSG_ATTACH_IND) { if (msg->type == OSMO_CC_MSG_ATTACH_IND) {
host = call->ep->remote_host; host = call->ep->remote_host;
port = call->ep->remote_port; 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); LOGP(DCC, LOGL_DEBUG, "Using host IP '%s' and port '%d' from remote address for attach message.\n", host, port);
} }
/* if there is no remote peer in the setup message, use remote peer */ /* if 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) { if (!address && msg->type == OSMO_CC_MSG_SETUP_IND && call->ep->remote_host) {
host = call->ep->remote_host; host = call->ep->remote_host;
port = call->ep->remote_port; 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); LOGP(DCC, LOGL_DEBUG, "Using host IP '%s' and port '%d' from remote address for setup message.\n", host, port);
} }
/* if there is no remote peer set, try to use the interface name */ /* if there is no remote peer set, try to use the interface name */
@ -256,16 +257,16 @@ reject:
/* check for incoming attachment */ /* check for incoming attachment */
att = osmo_cc_get_attached_interface(call->ep, interface); att = osmo_cc_get_attached_interface(call->ep, interface);
if (!att && !interface[0]) { if (!att && !interface[0]) {
PDEBUG(DCC, DEBUG_ERROR, "No remote peer attached, rejecting call.\n"); LOGP(DCC, LOGL_ERROR, "No remote peer attached, rejecting call.\n");
goto reject; goto reject;
} }
if (!att) { if (!att) {
PDEBUG(DCC, DEBUG_ERROR, "No remote peer attached for given interface '%s', rejecting call.\n", interface); LOGP(DCC, LOGL_ERROR, "No remote peer attached for given interface '%s', rejecting call.\n", interface);
goto reject; goto reject;
} }
host = att->attached_host; host = att->attached_host;
port = att->attached_port; port = att->attached_port;
PDEBUG(DCC, DEBUG_DEBUG, "Using host IP '%s' and port '%d' from attached peer for setup message.\n", host, port); LOGP(DCC, LOGL_DEBUG, "Using host IP '%s' and port '%d' from attached peer for setup message.\n", host, port);
} }
/* add local interface name to setup message */ /* add local interface name to setup message */
@ -278,13 +279,13 @@ reject:
} }
/* send attach indication to socket */ /* send attach indication to socket */
void send_attach_ind(struct timer *timer) void send_attach_ind(void *data)
{ {
osmo_cc_endpoint_t *ep = (osmo_cc_endpoint_t *)timer->priv; osmo_cc_endpoint_t *ep = data;
osmo_cc_call_t *call; osmo_cc_call_t *call;
osmo_cc_msg_t *msg; osmo_cc_msg_t *msg;
PDEBUG(DCC, DEBUG_DEBUG, "Trying to attach to remote peer \"%s\".\n", ep->remote_host); LOGP(DCC, LOGL_DEBUG, "Trying to attach to remote peer \"%s\".\n", ep->remote_host);
/* create new call for attachment */ /* create new call for attachment */
call = osmo_cc_call_new(ep); call = osmo_cc_call_new(ep);
@ -305,7 +306,7 @@ void send_attach_ind(struct timer *timer)
void attach_rsp(osmo_cc_call_t *call, osmo_cc_msg_t *msg) 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); LOGP(DCC, LOGL_INFO, "Attached to remote peer \"%s\".\n", call->ep->remote_address);
/* set state */ /* set state */
new_call_state(call, OSMO_CC_STATE_ATTACH_OUT); new_call_state(call, OSMO_CC_STATE_ATTACH_OUT);
@ -320,11 +321,11 @@ void attach_rel(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
if (call->state == OSMO_CC_STATE_ATTACH_SENT if (call->state == OSMO_CC_STATE_ATTACH_SENT
|| call->state == OSMO_CC_STATE_ATTACH_OUT) { || call->state == OSMO_CC_STATE_ATTACH_OUT) {
timer_start(&call->ep->attach_timer, OSMO_CC_ATTACH_TIMER); 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); LOGP(DCC, LOGL_INFO, "Attachment to remote peer \"%s\" failed, retrying.\n", call->ep->remote_address);
} }
if (call->attached_name) if (call->attached_name)
PDEBUG(DCC, DEBUG_INFO, "Peer with remote interface \"%s\" detached from us.\n", call->attached_name); LOGP(DCC, LOGL_INFO, "Peer with remote interface \"%s\" detached from us.\n", call->attached_name);
/* change state */ /* change state */
new_call_state(call, OSMO_CC_STATE_IDLE); new_call_state(call, OSMO_CC_STATE_IDLE);
@ -355,12 +356,12 @@ void attach_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
if (rc < 0) if (rc < 0)
address[0] = '\0'; address[0] = '\0';
if (!address[0]) { if (!address[0]) {
PDEBUG(DCC, DEBUG_ERROR, "Attachment request from remote peer has no remote address set, rejecting.\n"); LOGP(DCC, LOGL_ERROR, "Attachment request from remote peer has no remote address set, rejecting.\n");
rel: rel:
/* change to REL_REQ */ /* change to REL_REQ */
msg->type = OSMO_CC_MSG_REL_IND; msg->type = OSMO_CC_MSG_REL_IND;
PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type)); LOGP(DCC, LOGL_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type));
/* message to socket */ /* message to socket */
forward_to_ul(call, msg); forward_to_ul(call, msg);
@ -372,7 +373,7 @@ rel:
} }
rc = split_address(address, &host, &port); rc = split_address(address, &host, &port);
if (rc < 0) { if (rc < 0) {
PDEBUG(DCC, DEBUG_ERROR, "Given remote peer's address '%s' in attach message is invalid, rejecting call.\n", address); LOGP(DCC, LOGL_ERROR, "Given remote peer's address '%s' in attach message is invalid, rejecting call.\n", address);
goto rel; goto rel;
} }
free((char *)call->attached_host); free((char *)call->attached_host);
@ -387,11 +388,11 @@ rel:
call->attached_name = strdup(interface); 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); LOGP(DCC, LOGL_INFO, "Remote peer with socket address '%s' and port '%d' and interface '%s' attached to us.\n", call->attached_host, call->attached_port, call->attached_name);
/* changing to confirm message */ /* changing to confirm message */
msg->type = OSMO_CC_MSG_ATTACH_CNF; msg->type = OSMO_CC_MSG_ATTACH_CNF;
PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type)); LOGP(DCC, LOGL_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type));
/* message to socket */ /* message to socket */
forward_to_ul(call, msg); forward_to_ul(call, msg);
@ -568,18 +569,30 @@ static void notify_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
forward_to_ul(call, msg); forward_to_ul(call, msg);
} }
static void update_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg) static void modify_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
{ {
/* to lower layer */ /* to lower layer */
forward_to_ll(call, msg); forward_to_ll(call, msg);
} }
static void update_cnf(osmo_cc_call_t *call, osmo_cc_msg_t *msg) static void modify_cnf(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
{ {
/* to upper layer */ /* to upper layer */
forward_to_ul(call, msg); 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) static void disc_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
{ {
/* change state */ /* change state */
@ -654,7 +667,7 @@ static void disc_collision_ind(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
/* change to REL_REQ */ /* change to REL_REQ */
msg->type = OSMO_CC_MSG_REL_REQ; msg->type = OSMO_CC_MSG_REL_REQ;
PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type)); LOGP(DCC, LOGL_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type));
/* to lower layer */ /* to lower layer */
forward_to_ll(call, msg); forward_to_ll(call, msg);
@ -675,7 +688,7 @@ static void disc_collision_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
if (call->lower_layer_released) { if (call->lower_layer_released) {
/* change to REL_REQ */ /* change to REL_REQ */
msg->type = OSMO_CC_MSG_REL_IND; msg->type = OSMO_CC_MSG_REL_IND;
PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type)); LOGP(DCC, LOGL_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type));
/* to upper layer */ /* to upper layer */
forward_to_ul(call, msg); forward_to_ul(call, msg);
@ -713,7 +726,7 @@ static void rej_ind_disc(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
/* change to REL_IND */ /* change to REL_IND */
msg->type = OSMO_CC_MSG_REL_IND; msg->type = OSMO_CC_MSG_REL_IND;
PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type)); LOGP(DCC, LOGL_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type));
/* to upper layer */ /* to upper layer */
forward_to_ul(call, msg); forward_to_ul(call, msg);
@ -729,7 +742,7 @@ static void rej_req_disc(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
/* change to REL_REQ */ /* change to REL_REQ */
msg->type = OSMO_CC_MSG_REL_REQ; msg->type = OSMO_CC_MSG_REL_REQ;
PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type)); LOGP(DCC, LOGL_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type));
/* to lower layer */ /* to lower layer */
forward_to_ll(call, msg); forward_to_ll(call, msg);
@ -758,7 +771,7 @@ static void rel_ind_other(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
/* change to DISC_IND */ /* change to DISC_IND */
msg->type = OSMO_CC_MSG_DISC_IND; msg->type = OSMO_CC_MSG_DISC_IND;
PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type)); LOGP(DCC, LOGL_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type));
call->lower_layer_released = 1; call->lower_layer_released = 1;
/* to upper layer */ /* to upper layer */
@ -785,7 +798,7 @@ static void rel_req_other(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
/* change to DISC_REQ */ /* change to DISC_REQ */
msg->type = OSMO_CC_MSG_DISC_REQ; msg->type = OSMO_CC_MSG_DISC_REQ;
PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type)); LOGP(DCC, LOGL_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type));
call->upper_layer_released = 1; call->upper_layer_released = 1;
/* to lower layer */ /* to lower layer */
@ -866,9 +879,13 @@ static struct statemachine {
{SBIT(OSMO_CC_STATE_ACTIVE), {SBIT(OSMO_CC_STATE_ACTIVE),
OSMO_CC_MSG_INFO_REQ, info_req}, OSMO_CC_MSG_INFO_REQ, info_req},
{SBIT(OSMO_CC_STATE_ACTIVE), {SBIT(OSMO_CC_STATE_ACTIVE),
OSMO_CC_MSG_UPDATE_REQ, update_req}, OSMO_CC_MSG_MODIFY_REQ, modify_req},
{SBIT(OSMO_CC_STATE_ACTIVE), {SBIT(OSMO_CC_STATE_ACTIVE),
OSMO_CC_MSG_UPDATE_CNF, update_cnf}, 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 */ /* call release */
{SBIT(OSMO_CC_STATE_INIT_OUT) | SBIT(OSMO_CC_STATE_INIT_IN) | {SBIT(OSMO_CC_STATE_INIT_OUT) | SBIT(OSMO_CC_STATE_INIT_IN) |
@ -938,16 +955,16 @@ static void handle_msg(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
&& ((1 << call->state) & statemachine_list[i].states)) && ((1 << call->state) & statemachine_list[i].states))
break; break;
if (i == STATEMACHINE_LEN) { if (i == STATEMACHINE_LEN) {
PDEBUG(DCC, DEBUG_INFO, "Message %s unhandled at state %s (callref %d)\n", LOGP(DCC, LOGL_INFO, "Message %s unhandled at state %s (callref %d)\n",
osmo_cc_msg_value2name(msg->type), state_names[call->state], call->callref); osmo_cc_msg_value2name(msg->type), state_names[call->state], call->callref);
osmo_cc_free_msg(msg); osmo_cc_free_msg(msg);
return; return;
} }
PDEBUG(DCC, DEBUG_INFO, "Handle message %s at state %s (callref %d)\n", LOGP(DCC, LOGL_INFO, "Handle message %s at state %s (callref %d)\n",
osmo_cc_msg_value2name(msg->type), state_names[call->state], call->callref); osmo_cc_msg_value2name(msg->type), state_names[call->state], call->callref);
if (debuglevel <= DEBUG_INFO) if (debuglevel <= LOGL_INFO)
osmo_cc_debug_ie(msg, DEBUG_INFO); osmo_cc_debug_ie(msg, LOGL_INFO);
statemachine_list[i].action(call, msg); statemachine_list[i].action(call, msg);
} }
@ -1024,7 +1041,7 @@ void osmo_cc_ll_msg(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg
osmo_cc_call_t *call; osmo_cc_call_t *call;
if (!(msg->type & 1)) { if (!(msg->type & 1)) {
PDEBUG(DCC, DEBUG_ERROR, "Received message from lower layer that is not an _IND nor _CNF, please fix!\n"); LOGP(DCC, LOGL_ERROR, "Received message from lower layer that is not an _IND nor _CNF, please fix!\n");
osmo_cc_free_msg(msg); osmo_cc_free_msg(msg);
return; return;
} }
@ -1047,7 +1064,7 @@ void osmo_cc_ul_msg(void *priv, uint32_t callref, osmo_cc_msg_t *msg)
osmo_cc_call_t *call; osmo_cc_call_t *call;
if ((msg->type & 1)) { if ((msg->type & 1)) {
PDEBUG(DCC, DEBUG_ERROR, "Received message from socket that is not an _REQ nor _RSP, please fix!\n"); LOGP(DCC, LOGL_ERROR, "Received message from socket that is not an _REQ nor _RSP, please fix!\n");
osmo_cc_free_msg(msg); osmo_cc_free_msg(msg);
return; return;
} }
@ -1108,7 +1125,7 @@ static int osmo_cc_set_name(osmo_cc_endpoint_t *ep, const char *text)
text++; text++;
} }
} else { } else {
PDEBUG(DCC, DEBUG_ERROR, "Invalid name definition '%s'\n", text); LOGP(DCC, LOGL_ERROR, "Invalid name definition '%s'\n", text);
return -EINVAL; return -EINVAL;
} }
@ -1171,12 +1188,12 @@ static int osmo_cc_set_address(osmo_cc_endpoint_t *ep, const char *text)
text++; text++;
} }
if (!strcasecmp(text, "auto")) { if (!strcasecmp(text, "auto")) {
PDEBUG(DCC, DEBUG_DEBUG, "setting automatic remote peer selection\n"); LOGP(DCC, LOGL_DEBUG, "setting automatic remote peer selection\n");
ep->remote_auto = 1; ep->remote_auto = 1;
return 0; return 0;
} }
if (!strcasecmp(text, "none")) { if (!strcasecmp(text, "none")) {
PDEBUG(DCC, DEBUG_DEBUG, "disable automatic remote peer selection\n"); LOGP(DCC, LOGL_DEBUG, "disable automatic remote peer selection\n");
ep->remote_auto = 0; ep->remote_auto = 0;
return 0; return 0;
} }
@ -1185,7 +1202,7 @@ static int osmo_cc_set_address(osmo_cc_endpoint_t *ep, const char *text)
host_p = &ep->remote_host; host_p = &ep->remote_host;
port_p = &ep->remote_port; port_p = &ep->remote_port;
} else { } else {
PDEBUG(DCC, DEBUG_ERROR, "Invalid local or remote address definition '%s'\n", text); LOGP(DCC, LOGL_ERROR, "Invalid local or remote address definition '%s'\n", text);
return -EINVAL; return -EINVAL;
} }
@ -1210,7 +1227,7 @@ static int osmo_cc_set_address(osmo_cc_endpoint_t *ep, const char *text)
enum osmo_cc_session_addrtype addrtype; enum osmo_cc_session_addrtype addrtype;
addrtype = osmo_cc_address_type(*host_p); addrtype = osmo_cc_address_type(*host_p);
if (addrtype == osmo_cc_session_addrtype_unknown) { if (addrtype == osmo_cc_session_addrtype_unknown) {
PDEBUG(DCC, DEBUG_ERROR, "Given local address '%s' is invalid.\n", *host_p); LOGP(DCC, LOGL_ERROR, "Given local address '%s' is invalid.\n", *host_p);
return -EINVAL; return -EINVAL;
} }
osmo_cc_set_local_peer(&ep->session_config, osmo_cc_session_nettype_inet, addrtype, *host_p); osmo_cc_set_local_peer(&ep->session_config, osmo_cc_session_nettype_inet, addrtype, *host_p);
@ -1244,7 +1261,7 @@ static int osmo_cc_set_rtp(osmo_cc_endpoint_t *ep, const char *text)
text += 9; text += 9;
ports = 1; ports = 1;
} else { } else {
PDEBUG(DCC, DEBUG_ERROR, "Invalid RTP definition '%s'\n", text); LOGP(DCC, LOGL_ERROR, "Invalid RTP definition '%s'\n", text);
return -EINVAL; return -EINVAL;
} }
@ -1259,7 +1276,7 @@ static int osmo_cc_set_rtp(osmo_cc_endpoint_t *ep, const char *text)
enum osmo_cc_session_addrtype addrtype; enum osmo_cc_session_addrtype addrtype;
addrtype = osmo_cc_address_type(text); addrtype = osmo_cc_address_type(text);
if (addrtype == osmo_cc_session_addrtype_unknown) { if (addrtype == osmo_cc_session_addrtype_unknown) {
PDEBUG(DCC, DEBUG_ERROR, "Given RTP address '%s' is invalid.\n", text); LOGP(DCC, LOGL_ERROR, "Given RTP address '%s' is invalid.\n", text);
return -EINVAL; return -EINVAL;
} }
osmo_cc_set_local_peer(&ep->session_config, osmo_cc_session_nettype_inet, addrtype, text); osmo_cc_set_local_peer(&ep->session_config, osmo_cc_session_nettype_inet, addrtype, text);
@ -1272,7 +1289,7 @@ static int osmo_cc_set_rtp(osmo_cc_endpoint_t *ep, const char *text)
/* from port */ /* from port */
while (*text > ' ') { while (*text > ' ') {
if (*text < '0' || *text > '9') { if (*text < '0' || *text > '9') {
PDEBUG(DCC, DEBUG_ERROR, "Given 'from' port in '%s' is invalid.\n", text); LOGP(DCC, LOGL_ERROR, "Given 'from' port in '%s' is invalid.\n", text);
return -EINVAL; return -EINVAL;
} }
from = from * 10 + *text - '0'; from = from * 10 + *text - '0';
@ -1289,7 +1306,7 @@ static int osmo_cc_set_rtp(osmo_cc_endpoint_t *ep, const char *text)
/* to port */ /* to port */
while (*text > ' ') { while (*text > ' ') {
if (*text < '0' || *text > '9') { if (*text < '0' || *text > '9') {
PDEBUG(DCC, DEBUG_ERROR, "Given 'to' port in '%s' is invalid.\n", text); LOGP(DCC, LOGL_ERROR, "Given 'to' port in '%s' is invalid.\n", text);
return -EINVAL; return -EINVAL;
} }
to = to * 10 + *text - '0'; to = to * 10 + *text - '0';
@ -1318,10 +1335,10 @@ int osmo_cc_new(osmo_cc_endpoint_t *ep, const char *version, const char *name, u
int rc; int rc;
int i; int i;
PDEBUG(DCC, DEBUG_DEBUG, "Creating new endpoint instance.\n"); LOGP(DCC, LOGL_DEBUG, "Creating new endpoint instance.\n");
if (!!strcmp(version, OSMO_CC_VERSION)) { if (!!strcmp(version, OSMO_CC_VERSION)) {
PDEBUG(DCC, DEBUG_ERROR, "Application was compiled for different Osmo-CC version.\n"); LOGP(DCC, LOGL_ERROR, "Application was compiled for different Osmo-CC version.\n");
return OSMO_CC_RC_VERSION_MISMATCH; return OSMO_CC_RC_VERSION_MISMATCH;
} }
@ -1375,7 +1392,7 @@ int osmo_cc_new(osmo_cc_endpoint_t *ep, const char *version, const char *name, u
return rc; return rc;
} }
} else { } else {
PDEBUG(DCC, DEBUG_ERROR, "Unknown osmo-cc argument \"%s\"\n", argv[i]); LOGP(DCC, LOGL_ERROR, "Unknown osmo-cc argument \"%s\"\n", argv[i]);
return -EINVAL; return -EINVAL;
} }
} }
@ -1391,7 +1408,7 @@ int osmo_cc_new(osmo_cc_endpoint_t *ep, const char *version, const char *name, u
port = ep->local_port; port = ep->local_port;
if (!host) { if (!host) {
host = "127.0.0.1"; host = "127.0.0.1";
PDEBUG(DCC, DEBUG_DEBUG, "No local peer set, using default \"%s\"\n", host); LOGP(DCC, LOGL_DEBUG, "No local peer set, using default \"%s\"\n", host);
} }
rc = osmo_cc_open_socket(&ep->os, host, port, ep, osmo_cc_ul_msg, serving_location); rc = osmo_cc_open_socket(&ep->os, host, port, ep, osmo_cc_ul_msg, serving_location);
if (rc < 0) { if (rc < 0) {
@ -1413,12 +1430,12 @@ int osmo_cc_new(osmo_cc_endpoint_t *ep, const char *version, const char *name, u
if (ep->remote_auto) { if (ep->remote_auto) {
free((char *)ep->remote_host); free((char *)ep->remote_host);
ep->remote_host = strdup(ep->local_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); LOGP(DCC, LOGL_DEBUG, "Remote peer set to auto, using local peer's host \"%s\" for remote peer.\n", ep->remote_host);
if (rc == OSMO_CC_DEFAULT_PORT) if (rc == OSMO_CC_DEFAULT_PORT)
ep->remote_port = OSMO_CC_DEFAULT_PORT + 1; ep->remote_port = OSMO_CC_DEFAULT_PORT + 1;
else else
ep->remote_port = OSMO_CC_DEFAULT_PORT; ep->remote_port = OSMO_CC_DEFAULT_PORT;
PDEBUG(DCC, DEBUG_DEBUG, " -> Using remote port %d.\n", ep->remote_port); LOGP(DCC, LOGL_DEBUG, " -> Using remote port %d.\n", ep->remote_port);
/* create address string */ /* create address string */
free((char *)ep->remote_address); free((char *)ep->remote_address);
addrtype = osmo_cc_address_type(ep->remote_host); addrtype = osmo_cc_address_type(ep->remote_host);
@ -1431,7 +1448,7 @@ int osmo_cc_new(osmo_cc_endpoint_t *ep, const char *version, const char *name, u
/* attach to remote host */ /* attach to remote host */
timer_init(&ep->attach_timer, send_attach_ind, ep); timer_init(&ep->attach_timer, send_attach_ind, ep);
if (ep->remote_host) { if (ep->remote_host) {
send_attach_ind(&ep->attach_timer); send_attach_ind(ep->attach_timer.data);
} }
} }
@ -1443,7 +1460,7 @@ void osmo_cc_delete(osmo_cc_endpoint_t *ep)
{ {
osmo_cc_endpoint_t **epp; osmo_cc_endpoint_t **epp;
PDEBUG(DCC, DEBUG_DEBUG, "Destroying endpoint instance.\n"); LOGP(DCC, LOGL_DEBUG, "Destroying endpoint instance.\n");
/* detach from list >*/ /* detach from list >*/
epp = &osmo_cc_endpoint_list; epp = &osmo_cc_endpoint_list;
@ -1519,7 +1536,7 @@ const char *osmo_cc_host_of_address(const char *address)
char *p; char *p;
if (strlen(address) >= sizeof(host)) { if (strlen(address) >= sizeof(host)) {
PDEBUG(DCC, DEBUG_ERROR, "String way too long!\n"); LOGP(DCC, LOGL_ERROR, "String way too long!\n");
return NULL; return NULL;
} }

View File

@ -25,6 +25,7 @@
#include <sys/time.h> #include <sys/time.h>
#include <inttypes.h> #include <inttypes.h>
#include "../libtimer/timer.h" #include "../libtimer/timer.h"
#include "../libselect/select.h"
#include "../libdebug/debug.h" #include "../libdebug/debug.h"
#include "endpoint.h" #include "endpoint.h"
#include "helper.h" #include "helper.h"
@ -62,24 +63,24 @@ const char *osmo_cc_helper_audio_accept(osmo_cc_session_config_t *conf, void *pr
int i, selected_codec_i, telephone_event_i; int i, selected_codec_i, telephone_event_i;
if (*session_p) { if (*session_p) {
PDEBUG(DCC, DEBUG_ERROR, "Session already set, please fix!\n"); LOGP(DCC, LOGL_ERROR, "Session already set, please fix!\n");
abort(); abort();
} }
if (*codec_p) { if (*codec_p) {
PDEBUG(DCC, DEBUG_ERROR, "Codec already set, please fix!\n"); LOGP(DCC, LOGL_ERROR, "Codec already set, please fix!\n");
abort(); abort();
} }
/* SDP IE */ /* SDP IE */
rc = osmo_cc_get_ie_sdp(msg, 0, offer_sdp, sizeof(offer_sdp)); rc = osmo_cc_get_ie_sdp(msg, 0, offer_sdp, sizeof(offer_sdp));
if (rc < 0) { if (rc < 0) {
PDEBUG(DCC, DEBUG_ERROR, "There is no SDP included in setup request.\n"); LOGP(DCC, LOGL_ERROR, "There is no SDP included in setup request.\n");
return NULL; return NULL;
} }
*session_p = osmo_cc_session_receive_offer(conf, priv, offer_sdp); *session_p = osmo_cc_session_receive_offer(conf, priv, offer_sdp);
if (!*session_p) { if (!*session_p) {
PDEBUG(DCC, DEBUG_ERROR, "Failed to parse SDP.\n"); LOGP(DCC, LOGL_ERROR, "Failed to parse SDP.\n");
return NULL; return NULL;
} }
@ -123,8 +124,9 @@ const char *osmo_cc_helper_audio_accept(osmo_cc_session_config_t *conf, void *pr
break; break;
} }
if (!selected_codec) { if (!selected_codec) {
PDEBUG(DCC, DEBUG_ERROR, "No codec found in setup message that we support.\n"); LOGP(DCC, LOGL_ERROR, "No codec found in setup message that we support.\n");
osmo_cc_free_session(*session_p); osmo_cc_free_session(*session_p);
*session_p = NULL;
return NULL; return NULL;
} }
osmo_cc_session_accept_codec(selected_codec, codecs[selected_codec_i].encoder, codecs[selected_codec_i].decoder); osmo_cc_session_accept_codec(selected_codec, codecs[selected_codec_i].encoder, codecs[selected_codec_i].decoder);
@ -138,6 +140,7 @@ const char *osmo_cc_helper_audio_accept(osmo_cc_session_config_t *conf, void *pr
accept_sdp = osmo_cc_session_send_answer(*session_p); accept_sdp = osmo_cc_session_send_answer(*session_p);
if (!accept_sdp) { if (!accept_sdp) {
osmo_cc_free_session(*session_p); osmo_cc_free_session(*session_p);
*session_p = NULL;
return NULL; return NULL;
} }
@ -151,7 +154,7 @@ int osmo_cc_helper_audio_negotiate(osmo_cc_msg_t *msg, osmo_cc_session_t **sessi
int rc; int rc;
if (!(*session_p)) { if (!(*session_p)) {
PDEBUG(DCC, DEBUG_ERROR, "Session not set, please fix!\n"); LOGP(DCC, LOGL_ERROR, "Session not set, please fix!\n");
abort(); abort();
} }
@ -182,7 +185,7 @@ int osmo_cc_helper_audio_negotiate(osmo_cc_msg_t *msg, osmo_cc_session_t **sessi
} }
} }
if (!(*codec_p)) { if (!(*codec_p)) {
PDEBUG(DCC, DEBUG_ERROR, "No codec found in setup reply message that we support.\n"); LOGP(DCC, LOGL_ERROR, "No codec found in setup reply message that we support.\n");
return -EIO; return -EIO;
} }

View File

@ -3,8 +3,8 @@ struct osmo_cc_helper_audio_codecs {
const char *payload_name; const char *payload_name;
uint32_t payload_rate; uint32_t payload_rate;
int payload_channels; int payload_channels;
void (*encoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); 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 (*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); 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);

View File

@ -35,6 +35,8 @@
#define _OSMO_CC_NAME2VALUE(array) { \ #define _OSMO_CC_NAME2VALUE(array) { \
int value; \ int value; \
for (value = 0; (size_t)value < (sizeof(array) / sizeof(array[0])); value++) { \ for (value = 0; (size_t)value < (sizeof(array) / sizeof(array[0])); value++) { \
if (!array[value]) \
continue; \
if (!strcasecmp(array[value], name)) \ if (!strcasecmp(array[value], name)) \
return value; \ return value; \
} \ } \
@ -372,7 +374,7 @@ osmo_cc_msg_t *osmo_cc_new_msg(uint8_t msg_type)
/* allocate message */ /* allocate message */
msg = calloc(1, sizeof(*msg) + 65535); msg = calloc(1, sizeof(*msg) + 65535);
if (!msg) { if (!msg) {
PDEBUG(DCC, DEBUG_ERROR, "No memory\n"); LOGP(DCC, LOGL_ERROR, "No memory\n");
abort(); abort();
} }
/* set message type and zero length */ /* set message type and zero length */
@ -451,14 +453,14 @@ void osmo_cc_debug_ie(osmo_cc_msg_t *msg, int level)
ie = (osmo_cc_ie_t *)p; ie = (osmo_cc_ie_t *)p;
/* check for minimum IE length */ /* check for minimum IE length */
if (msg_len < sizeof(*ie)) { 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)); LOGP(DCC, level, "****** Rest of message is too short for an IE: value=%s\n", debug_hex(p, msg_len));
return; return;
} }
/* get actual IE length */ /* get actual IE length */
len = ntohs(ie->length_networkorder); len = ntohs(ie->length_networkorder);
/* check if IE length does not exceed message */ /* check if IE length does not exceed message */
if (msg_len < sizeof(*ie) + len) { 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)); LOGP(DCC, level, "****** IE: type=0x%02x length=%d would exceed the rest length of message (%d bytes left)\n", ie->type, len, msg_len - (int)sizeof(*ie));
return; return;
} }
switch (ie->type) { switch (ie->type) {
@ -466,109 +468,109 @@ void osmo_cc_debug_ie(osmo_cc_msg_t *msg, int level)
rc = osmo_cc_get_ie_called(msg, ie_repeat[ie->type], &type, &plan, string, sizeof(string)); rc = osmo_cc_get_ie_called(msg, ie_repeat[ie->type], &type, &plan, string, sizeof(string));
if (rc < 0) if (rc < 0)
break; 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); LOGP(DCC, level, " %s type=%d(%s) plan=%d(%s) number='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_type_value2name(type), plan, osmo_cc_plan_value2name(plan), string);
break; break;
case OSMO_CC_IE_CALLED_SUB: case OSMO_CC_IE_CALLED_SUB:
rc = osmo_cc_get_ie_called_sub(msg, ie_repeat[ie->type], &type, string, sizeof(string)); rc = osmo_cc_get_ie_called_sub(msg, ie_repeat[ie->type], &type, string, sizeof(string));
if (rc < 0) if (rc < 0)
break; break;
PDEBUG(DCC, level, " %s type=%d(%s) number='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_type_value2name(type), string); LOGP(DCC, level, " %s type=%d(%s) number='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_type_value2name(type), string);
break; break;
case OSMO_CC_IE_CALLED_NAME: case OSMO_CC_IE_CALLED_NAME:
rc = osmo_cc_get_ie_called_name(msg, ie_repeat[ie->type], string, sizeof(string)); rc = osmo_cc_get_ie_called_name(msg, ie_repeat[ie->type], string, sizeof(string));
if (rc < 0) if (rc < 0)
break; break;
PDEBUG(DCC, level, " %s name='%s'\n", osmo_cc_ie_value2name(ie->type), string); LOGP(DCC, level, " %s name='%s'\n", osmo_cc_ie_value2name(ie->type), string);
break; break;
case OSMO_CC_IE_CALLED_INTERFACE: case OSMO_CC_IE_CALLED_INTERFACE:
rc = osmo_cc_get_ie_called_interface(msg, ie_repeat[ie->type], string, sizeof(string)); rc = osmo_cc_get_ie_called_interface(msg, ie_repeat[ie->type], string, sizeof(string));
if (rc < 0) if (rc < 0)
break; break;
PDEBUG(DCC, level, " %s name='%s'\n", osmo_cc_ie_value2name(ie->type), string); LOGP(DCC, level, " %s name='%s'\n", osmo_cc_ie_value2name(ie->type), string);
break; break;
case OSMO_CC_IE_COMPLETE: case OSMO_CC_IE_COMPLETE:
rc = osmo_cc_get_ie_complete(msg, ie_repeat[ie->type]); rc = osmo_cc_get_ie_complete(msg, ie_repeat[ie->type]);
if (rc < 0) if (rc < 0)
break; break;
PDEBUG(DCC, level, " %s\n", osmo_cc_ie_value2name(ie->type)); LOGP(DCC, level, " %s\n", osmo_cc_ie_value2name(ie->type));
break; break;
case OSMO_CC_IE_CALLING: case OSMO_CC_IE_CALLING:
rc = osmo_cc_get_ie_calling(msg, ie_repeat[ie->type], &type, &plan, &present, &screen, string, sizeof(string)); rc = osmo_cc_get_ie_calling(msg, ie_repeat[ie->type], &type, &plan, &present, &screen, string, sizeof(string));
if (rc < 0) if (rc < 0)
break; 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); LOGP(DCC, level, " %s type=%d(%s) plan=%d(%s), presentation=%d(%s), screening=%d(%s), number='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_type_value2name(type), plan, osmo_cc_plan_value2name(plan), present, osmo_cc_present_value2name(present), screen, osmo_cc_screen_value2name(screen), string);
break; break;
case OSMO_CC_IE_CALLING_SUB: case OSMO_CC_IE_CALLING_SUB:
rc = osmo_cc_get_ie_calling_sub(msg, ie_repeat[ie->type], &type, string, sizeof(string)); rc = osmo_cc_get_ie_calling_sub(msg, ie_repeat[ie->type], &type, string, sizeof(string));
if (rc < 0) if (rc < 0)
break; break;
PDEBUG(DCC, level, " %s type=%d(%s) number='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_type_value2name(type), string); LOGP(DCC, level, " %s type=%d(%s) number='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_type_value2name(type), string);
break; break;
case OSMO_CC_IE_CALLING_NAME: case OSMO_CC_IE_CALLING_NAME:
rc = osmo_cc_get_ie_calling_name(msg, ie_repeat[ie->type], string, sizeof(string)); rc = osmo_cc_get_ie_calling_name(msg, ie_repeat[ie->type], string, sizeof(string));
if (rc < 0) if (rc < 0)
break; break;
PDEBUG(DCC, level, " %s name='%s'\n", osmo_cc_ie_value2name(ie->type), string); LOGP(DCC, level, " %s name='%s'\n", osmo_cc_ie_value2name(ie->type), string);
break; break;
case OSMO_CC_IE_CALLING_INTERFACE: case OSMO_CC_IE_CALLING_INTERFACE:
rc = osmo_cc_get_ie_calling_interface(msg, ie_repeat[ie->type], string, sizeof(string)); rc = osmo_cc_get_ie_calling_interface(msg, ie_repeat[ie->type], string, sizeof(string));
if (rc < 0) if (rc < 0)
break; break;
PDEBUG(DCC, level, " %s name='%s'\n", osmo_cc_ie_value2name(ie->type), string); LOGP(DCC, level, " %s name='%s'\n", osmo_cc_ie_value2name(ie->type), string);
break; break;
case OSMO_CC_IE_CALLING_NETWORK: case OSMO_CC_IE_CALLING_NETWORK:
rc = osmo_cc_get_ie_calling_network(msg, ie_repeat[ie->type], &type, string, sizeof(string)); rc = osmo_cc_get_ie_calling_network(msg, ie_repeat[ie->type], &type, string, sizeof(string));
if (rc < 0) if (rc < 0)
break; break;
PDEBUG(DCC, level, " %s type=%d(%s) id='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_network_value2name(type), string); LOGP(DCC, level, " %s type=%d(%s) id='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_network_value2name(type), string);
break; break;
case OSMO_CC_IE_BEARER: case OSMO_CC_IE_BEARER:
rc = osmo_cc_get_ie_bearer(msg, ie_repeat[ie->type], &coding, &capability, &mode); rc = osmo_cc_get_ie_bearer(msg, ie_repeat[ie->type], &coding, &capability, &mode);
if (rc < 0) if (rc < 0)
break; 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)); LOGP(DCC, level, " %s coding=%d(%s) capability=%d(%s) mode=%d(%s)\n", osmo_cc_ie_value2name(ie->type), coding, osmo_cc_coding_value2name(coding), capability, osmo_cc_capability_value2name(capability), mode, osmo_cc_mode_value2name(mode));
break; break;
case OSMO_CC_IE_REDIR: case OSMO_CC_IE_REDIR:
rc = osmo_cc_get_ie_redir(msg, ie_repeat[ie->type], &type, &plan, &present, &screen, &reason, string, sizeof(string)); rc = osmo_cc_get_ie_redir(msg, ie_repeat[ie->type], &type, &plan, &present, &screen, &reason, string, sizeof(string));
if (rc < 0) if (rc < 0)
break; 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); LOGP(DCC, level, " %s type=%d(%s) plan=%d(%s) presentation=%d(%s) screening=%d(%s) reason=%d(%s) number='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_type_value2name(type), plan, osmo_cc_plan_value2name(plan), present, osmo_cc_present_value2name(present), screen, osmo_cc_screen_value2name(screen), reason, osmo_cc_redir_reason_value2name(reason), string);
break; break;
case OSMO_CC_IE_DTMF: 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)); rc = osmo_cc_get_ie_dtmf(msg, ie_repeat[ie->type], &duration_ms, &pause_ms, &dtmf_mode, string, sizeof(string));
if (rc < 0) if (rc < 0)
break; 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)); LOGP(DCC, level, " %s duration=%dms pause=%dms mode=%d(%s)\n", osmo_cc_ie_value2name(ie->type), duration_ms, pause_ms, dtmf_mode, osmo_cc_dtmf_mode_value2name(dtmf_mode));
break; break;
case OSMO_CC_IE_KEYPAD: case OSMO_CC_IE_KEYPAD:
rc = osmo_cc_get_ie_keypad(msg, ie_repeat[ie->type], string, sizeof(string)); rc = osmo_cc_get_ie_keypad(msg, ie_repeat[ie->type], string, sizeof(string));
if (rc < 0) if (rc < 0)
break; break;
PDEBUG(DCC, level, " %s digits='%s'\n", osmo_cc_ie_value2name(ie->type), string); LOGP(DCC, level, " %s digits='%s'\n", osmo_cc_ie_value2name(ie->type), string);
break; break;
case OSMO_CC_IE_PROGRESS: case OSMO_CC_IE_PROGRESS:
rc = osmo_cc_get_ie_progress(msg, ie_repeat[ie->type], &coding, &location, &progress); rc = osmo_cc_get_ie_progress(msg, ie_repeat[ie->type], &coding, &location, &progress);
if (rc < 0) if (rc < 0)
break; 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)); LOGP(DCC, level, " %s coding=%d(%s) location=%d(%s) progress=%d(%s)\n", osmo_cc_ie_value2name(ie->type), coding, osmo_cc_coding_value2name(coding), location, osmo_cc_location_value2name(location), progress, osmo_cc_progress_value2name(progress));
break; break;
case OSMO_CC_IE_NOTIFY: case OSMO_CC_IE_NOTIFY:
rc = osmo_cc_get_ie_notify(msg, ie_repeat[ie->type], &notify); rc = osmo_cc_get_ie_notify(msg, ie_repeat[ie->type], &notify);
if (rc < 0) if (rc < 0)
break; break;
PDEBUG(DCC, level, " %s indicator=%d(%s)\n", osmo_cc_ie_value2name(ie->type), notify, osmo_cc_notify_value2name(notify)); LOGP(DCC, level, " %s indicator=%d(%s)\n", osmo_cc_ie_value2name(ie->type), notify, osmo_cc_notify_value2name(notify));
break; break;
case OSMO_CC_IE_CAUSE: case OSMO_CC_IE_CAUSE:
rc = osmo_cc_get_ie_cause(msg, ie_repeat[ie->type], &location, &isdn_cause, &sip_cause, &socket_cause); rc = osmo_cc_get_ie_cause(msg, ie_repeat[ie->type], &location, &isdn_cause, &sip_cause, &socket_cause);
if (rc < 0) if (rc < 0)
break; 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)); LOGP(DCC, level, " %s location=%d(%s) isdn_cause=%d(%s) sip_cause=%d socket_cause=%d(%s)\n", osmo_cc_ie_value2name(ie->type), location, osmo_cc_location_value2name(location), isdn_cause, osmo_cc_isdn_cause_value2name(isdn_cause), sip_cause, socket_cause, osmo_cc_socket_cause_value2name(socket_cause));
break; break;
case OSMO_CC_IE_DISPLAY: case OSMO_CC_IE_DISPLAY:
rc = osmo_cc_get_ie_display(msg, ie_repeat[ie->type], string, sizeof(string)); rc = osmo_cc_get_ie_display(msg, ie_repeat[ie->type], string, sizeof(string));
if (rc < 0) if (rc < 0)
break; break;
PDEBUG(DCC, level, " %s info='%s'\n", osmo_cc_ie_value2name(ie->type), string); LOGP(DCC, level, " %s info='%s'\n", osmo_cc_ie_value2name(ie->type), string);
break; break;
case OSMO_CC_IE_SDP: case OSMO_CC_IE_SDP:
rc = osmo_cc_get_ie_sdp(msg, ie_repeat[ie->type], string, sizeof(string)); rc = osmo_cc_get_ie_sdp(msg, ie_repeat[ie->type], string, sizeof(string));
@ -580,22 +582,22 @@ void osmo_cc_debug_ie(osmo_cc_msg_t *msg, int level)
if (string[i] == '\n') if (string[i] == '\n')
string[i] = 'n'; string[i] = 'n';
} }
PDEBUG(DCC, level, " %s payload=%s\n", osmo_cc_ie_value2name(ie->type), string); LOGP(DCC, level, " %s payload=%s\n", osmo_cc_ie_value2name(ie->type), string);
break; break;
case OSMO_CC_IE_SOCKET_ADDRESS: case OSMO_CC_IE_SOCKET_ADDRESS:
rc = osmo_cc_get_ie_socket_address(msg, ie_repeat[ie->type], string, sizeof(string)); rc = osmo_cc_get_ie_socket_address(msg, ie_repeat[ie->type], string, sizeof(string));
if (rc < 0) if (rc < 0)
break; break;
PDEBUG(DCC, level, " %s address='%s'\n", osmo_cc_ie_value2name(ie->type), string); LOGP(DCC, level, " %s address='%s'\n", osmo_cc_ie_value2name(ie->type), string);
break; break;
case OSMO_CC_IE_PRIVATE: case OSMO_CC_IE_PRIVATE:
rc = osmo_cc_get_ie_private(msg, ie_repeat[ie->type], &unique, (uint8_t *)string, sizeof(string)); rc = osmo_cc_get_ie_private(msg, ie_repeat[ie->type], &unique, (uint8_t *)string, sizeof(string));
if (rc < 0) if (rc < 0)
break; 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)); LOGP(DCC, level, " %s unique=%u=0x%08x private=%s\n", osmo_cc_ie_value2name(ie->type), unique, unique, debug_hex((uint8_t *)string, rc));
break; break;
default: 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)); LOGP(DCC, level, " %s type=0x%02x length=%d value=%s\n", osmo_cc_ie_value2name(ie->type), ie->type, len, debug_hex(ie->data, len));
} }
ie_repeat[ie->type]++; ie_repeat[ie->type]++;
p += sizeof(*ie) + len; p += sizeof(*ie) + len;
@ -623,16 +625,16 @@ int osmo_cc_get_ie_struct(osmo_cc_msg_t *msg, uint8_t ie_type, int ie_repeat, in
ie = (osmo_cc_ie_t *)p; ie = (osmo_cc_ie_t *)p;
/* check for minimum IE length */ /* check for minimum IE length */
if (msg_len < sizeof(*ie)) { if (msg_len < sizeof(*ie)) {
PDEBUG(DCC, DEBUG_ERROR, "MSG short read\n"); LOGP(DCC, LOGL_ERROR, "MSG short read\n");
osmo_cc_debug_ie(msg, DEBUG_ERROR); osmo_cc_debug_ie(msg, LOGL_ERROR);
return -EINVAL; return -EINVAL;
} }
/* get actual IE length */ /* get actual IE length */
len = ntohs(ie->length_networkorder); len = ntohs(ie->length_networkorder);
/* check if IE length does not exceed message */ /* check if IE length does not exceed message */
if (msg_len < sizeof(*ie) + len) { if (msg_len < sizeof(*ie) + len) {
PDEBUG(DCC, DEBUG_ERROR, "MSG short read\n"); LOGP(DCC, LOGL_ERROR, "MSG short read\n");
osmo_cc_debug_ie(msg, DEBUG_ERROR); osmo_cc_debug_ie(msg, LOGL_ERROR);
return -EINVAL; return -EINVAL;
} }
/* check if IE matches the one that is searched for */ /* check if IE matches the one that is searched for */
@ -650,7 +652,7 @@ int osmo_cc_get_ie_struct(osmo_cc_msg_t *msg, uint8_t ie_type, int ie_repeat, in
} }
/* return IE and indicate how many bytes we have more than the given length*/ /* return IE and indicate how many bytes we have more than the given length*/
if (ntohs(ie->length_networkorder) < ie_len) { 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); LOGP(DCC, LOGL_ERROR, "IE 0x%02d has length of %d, but we expect it to have at least %d!\n", ie_type, ntohs(ie->length_networkorder), ie_len);
return -EINVAL; return -EINVAL;
} }
*ie_struct = ie; *ie_struct = ie;
@ -726,7 +728,7 @@ void *osmo_cc_add_ie(osmo_cc_msg_t *msg, uint8_t ie_type, int ie_len)
msg_len = ntohs(msg->length_networkorder); msg_len = ntohs(msg->length_networkorder);
new_msg_len = msg_len + sizeof(*ie) + ie_len; new_msg_len = msg_len + sizeof(*ie) + ie_len;
if (new_msg_len > 65535) { if (new_msg_len > 65535) {
PDEBUG(DCC, DEBUG_ERROR, "MSG overflow\n"); LOGP(DCC, LOGL_ERROR, "MSG overflow\n");
return NULL; return NULL;
} }
msg->length_networkorder = htons(new_msg_len); msg->length_networkorder = htons(new_msg_len);

View File

@ -30,8 +30,10 @@ enum osmo_cc_msg_type {
OSMO_CC_MSG_NOTIFY_IND = 0x85, OSMO_CC_MSG_NOTIFY_IND = 0x85,
OSMO_CC_MSG_INFO_REQ = 0x88, OSMO_CC_MSG_INFO_REQ = 0x88,
OSMO_CC_MSG_INFO_IND = 0x89, OSMO_CC_MSG_INFO_IND = 0x89,
OSMO_CC_MSG_UPDATE_REQ = 0x91, OSMO_CC_MSG_MODIFY_REQ = 0x90,
OSMO_CC_MSG_UPDATE_CNF = 0x93, 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_REQ = 0xf8,
OSMO_CC_MSG_ATTACH_IND = 0xf9, OSMO_CC_MSG_ATTACH_IND = 0xf9,
OSMO_CC_MSG_ATTACH_RSP = 0xfa, OSMO_CC_MSG_ATTACH_RSP = 0xfa,

View File

@ -28,6 +28,7 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include "../libdebug/debug.h" #include "../libdebug/debug.h"
#include "../libtimer/timer.h" #include "../libtimer/timer.h"
#include "../libselect/select.h"
#include "endpoint.h" #include "endpoint.h"
#define RTP_VERSION 2 #define RTP_VERSION 2
@ -67,11 +68,11 @@ static int rtp_receive(int sock, uint8_t **payload_p, int *payload_len_p, uint8_
if (len < 0) { if (len < 0) {
if (errno == EAGAIN) if (errno == EAGAIN)
return -EAGAIN; return -EAGAIN;
PDEBUG(DCC, DEBUG_DEBUG, "Read errno = %d (%s)\n", errno, strerror(errno)); LOGP(DCC, LOGL_DEBUG, "Read errno = %d (%s)\n", errno, strerror(errno));
return -EIO; return -EIO;
} }
if (len < 12) { if (len < 12) {
PDEBUG(DCC, DEBUG_NOTICE, "Received RTP frame too short (len = %d).\n", len); LOGP(DCC, LOGL_NOTICE, "Received RTP frame too short (len = %d).\n", len);
return -EINVAL; return -EINVAL;
} }
@ -86,20 +87,20 @@ static int rtp_receive(int sock, uint8_t **payload_p, int *payload_len_p, uint8_
*ssrc_p = ntohl(rtph->ssrc); *ssrc_p = ntohl(rtph->ssrc);
if (version != RTP_VERSION) { if (version != RTP_VERSION) {
PDEBUG(DCC, DEBUG_NOTICE, "Received RTP version %d not supported.\n", version); LOGP(DCC, LOGL_NOTICE, "Received RTP version %d not supported.\n", version);
return -EINVAL; return -EINVAL;
} }
payload = data + sizeof(*rtph) + (csrc_count << 2); payload = data + sizeof(*rtph) + (csrc_count << 2);
payload_len = len - sizeof(*rtph) - (csrc_count << 2); payload_len = len - sizeof(*rtph) - (csrc_count << 2);
if (payload_len < 0) { if (payload_len < 0) {
PDEBUG(DCC, DEBUG_NOTICE, "Received RTP frame too short (len = %d, csrc count = %d).\n", len, csrc_count); LOGP(DCC, LOGL_NOTICE, "Received RTP frame too short (len = %d, csrc count = %d).\n", len, csrc_count);
return -EINVAL; return -EINVAL;
} }
if (extension) { if (extension) {
if (payload_len < (int)sizeof(*rtpxh)) { if (payload_len < (int)sizeof(*rtpxh)) {
PDEBUG(DCC, DEBUG_NOTICE, "Received RTP frame too short for extension header.\n"); LOGP(DCC, LOGL_NOTICE, "Received RTP frame too short for extension header.\n");
return -EINVAL; return -EINVAL;
} }
rtpxh = (struct rtp_x_hdr *)payload; rtpxh = (struct rtp_x_hdr *)payload;
@ -107,19 +108,19 @@ static int rtp_receive(int sock, uint8_t **payload_p, int *payload_len_p, uint8_
payload += x_len; payload += x_len;
payload_len -= x_len; payload_len -= x_len;
if (payload_len < (int)sizeof(*rtpxh)) { if (payload_len < (int)sizeof(*rtpxh)) {
PDEBUG(DCC, DEBUG_NOTICE, "Received RTP frame too short, extension header exceeds frame length.\n"); LOGP(DCC, LOGL_NOTICE, "Received RTP frame too short, extension header exceeds frame length.\n");
return -EINVAL; return -EINVAL;
} }
} }
if (padding) { if (padding) {
if (payload_len < 1) { if (payload_len < 1) {
PDEBUG(DCC, DEBUG_NOTICE, "Received RTP frame too short for padding length.\n"); LOGP(DCC, LOGL_NOTICE, "Received RTP frame too short for padding length.\n");
return -EINVAL; return -EINVAL;
} }
payload_len -= payload[payload_len - 1]; payload_len -= payload[payload_len - 1];
if (payload_len < 0) { if (payload_len < 0) {
PDEBUG(DCC, DEBUG_NOTICE, "Received RTP frame padding is greater than payload.\n"); LOGP(DCC, LOGL_NOTICE, "Received RTP frame padding is greater than payload.\n");
return -EINVAL; return -EINVAL;
} }
} }
@ -132,6 +133,22 @@ static int rtp_receive(int sock, uint8_t **payload_p, int *payload_len_p, uint8_
return 0; return 0;
} }
static int rtcp_receive(int sock)
{
static uint8_t data[2048];
int len;
len = read(sock, data, sizeof(data));
if (len < 0) {
if (errno == EAGAIN)
return -EAGAIN;
LOGP(DCC, LOGL_DEBUG, "Read errno = %d (%s)\n", errno, strerror(errno));
return -EIO;
}
return 0;
}
static void rtp_send(int sock, uint8_t *payload, int payload_len, uint8_t marker, uint8_t pt, uint16_t sequence, uint32_t timestamp, uint32_t ssrc) 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; struct rtp_hdr *rtph;
@ -147,16 +164,19 @@ static void rtp_send(int sock, uint8_t *payload, int payload_len, uint8_t marker
rtph->ssrc = htonl(ssrc); rtph->ssrc = htonl(ssrc);
len += payload_len; len += payload_len;
if (len > (int)sizeof(data)) { if (len > (int)sizeof(data)) {
PDEBUG(DCC, DEBUG_NOTICE, "Buffer overflow, please fix!.\n"); LOGP(DCC, LOGL_NOTICE, "Buffer overflow, please fix!.\n");
abort(); abort();
} }
memcpy(data + sizeof(*rtph), payload, payload_len); memcpy(data + sizeof(*rtph), payload, payload_len);
rc = write(sock, data, len); rc = write(sock, data, len);
if (rc < 0) if (rc < 0)
PDEBUG(DCC, DEBUG_DEBUG, "Write errno = %d (%s)\n", errno, strerror(errno)); LOGP(DCC, LOGL_DEBUG, "Write errno = %d (%s)\n", errno, strerror(errno));
} }
static int rtp_listen_cb(struct osmo_fd *ofd, unsigned int when);
static int rtcp_listen_cb(struct osmo_fd *ofd, unsigned int when);
/* open and bind RTP /* open and bind RTP
* set local port to what we bound * set local port to what we bound
*/ */
@ -186,7 +206,7 @@ int osmo_cc_rtp_open(osmo_cc_session_media_t *media)
rc = inet_pton(AF_INET, media->connection_data_local.address, &sa4->sin_addr); rc = inet_pton(AF_INET, media->connection_data_local.address, &sa4->sin_addr);
if (rc < 1) { if (rc < 1) {
pton_error: pton_error:
PDEBUG(DCC, DEBUG_NOTICE, "Cannot bind to address '%s'.\n", media->connection_data_local.address); LOGP(DCC, LOGL_NOTICE, "Cannot bind to address '%s'.\n", media->connection_data_local.address);
return -EINVAL; return -EINVAL;
} }
sport = &sa4->sin_port; sport = &sa4->sin_port;
@ -204,7 +224,7 @@ pton_error:
slen = sizeof(*sa6); slen = sizeof(*sa6);
break; break;
case osmo_cc_session_addrtype_unknown: case osmo_cc_session_addrtype_unknown:
PDEBUG(DCC, DEBUG_NOTICE, "Unsupported address type '%s'.\n", media->connection_data_local.addrtype_name); LOGP(DCC, LOGL_NOTICE, "Unsupported address type '%s'.\n", media->connection_data_local.addrtype_name);
return -EINVAL; return -EINVAL;
} }
@ -217,46 +237,54 @@ pton_error:
rc = socket(domain, SOCK_DGRAM, IPPROTO_UDP); rc = socket(domain, SOCK_DGRAM, IPPROTO_UDP);
if (rc < 0) { if (rc < 0) {
socket_error: socket_error:
PDEBUG(DCC, DEBUG_ERROR, "Cannot create socket (domain=%d, errno=%d(%s))\n", domain, errno, strerror(errno)); LOGP(DCC, LOGL_ERROR, "Cannot create socket (domain=%d, errno=%d(%s))\n", domain, errno, strerror(errno));
osmo_cc_rtp_close(media); osmo_cc_rtp_close(media);
return -EIO; return -EIO;
} }
media->rtp_socket = rc; media->rtp_ofd.fd = rc;
media->rtp_ofd.cb = rtp_listen_cb;
media->rtp_ofd.data = media;
media->rtp_ofd.when = OSMO_FD_READ;
osmo_fd_register(&media->rtp_ofd);
rc = socket(domain, SOCK_DGRAM, IPPROTO_UDP); rc = socket(domain, SOCK_DGRAM, IPPROTO_UDP);
if (rc < 0) if (rc < 0)
goto socket_error; goto socket_error;
media->rtcp_socket = rc; media->rtcp_ofd.fd = rc;
media->rtcp_ofd.cb = rtcp_listen_cb;
media->rtcp_ofd.data = media;
media->rtcp_ofd.when = OSMO_FD_READ;
osmo_fd_register(&media->rtcp_ofd);
/* bind sockets */ /* bind sockets */
*sport = htons(conf->rtp_port_next); *sport = htons(conf->rtp_port_next);
rc = bind(media->rtp_socket, (struct sockaddr *)&sa, slen); rc = bind(media->rtp_ofd.fd, (struct sockaddr *)&sa, slen);
if (rc < 0) { if (rc < 0) {
bind_error: bind_error:
osmo_cc_rtp_close(media); 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; 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) { if (conf->rtp_port_next == start_port) {
PDEBUG(DCC, DEBUG_ERROR, "Cannot bind socket (errno=%d(%s))\n", errno, strerror(errno)); LOGP(DCC, LOGL_ERROR, "Cannot bind socket (errno=%d(%s))\n", errno, strerror(errno));
return -EIO; return -EIO;
} }
continue; continue;
} }
*sport = htons(conf->rtp_port_next + 1); *sport = htons(conf->rtp_port_next + 1);
rc = bind(media->rtcp_socket, (struct sockaddr *)&sa, slen); rc = bind(media->rtcp_ofd.fd, (struct sockaddr *)&sa, slen);
if (rc < 0) if (rc < 0)
goto bind_error; goto bind_error;
media->description.port_local = conf->rtp_port_next; 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; 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 */ /* set nonblocking io, to prevent write to block */
flags = fcntl(media->rtp_socket, F_GETFL); flags = fcntl(media->rtp_ofd.fd, F_GETFL);
flags |= O_NONBLOCK; flags |= O_NONBLOCK;
fcntl(media->rtp_socket, F_SETFL, flags); fcntl(media->rtp_ofd.fd, F_SETFL, flags);
flags = fcntl(media->rtcp_socket, F_GETFL); flags = fcntl(media->rtcp_ofd.fd, F_GETFL);
flags |= O_NONBLOCK; flags |= O_NONBLOCK;
fcntl(media->rtcp_socket, F_SETFL, flags); fcntl(media->rtcp_ofd.fd, F_SETFL, flags);
break; break;
} }
PDEBUG(DCC, DEBUG_DEBUG, "Opening media port %d\n", media->description.port_local); LOGP(DCC, LOGL_DEBUG, "Opening media port %d\n", media->description.port_local);
return 0; return 0;
} }
@ -273,7 +301,7 @@ int osmo_cc_rtp_connect(osmo_cc_session_media_t *media)
uint16_t *sport; uint16_t *sport;
int rc; int rc;
PDEBUG(DCC, DEBUG_DEBUG, "Connecting media port %d->%d\n", media->description.port_local, media->description.port_remote); LOGP(DCC, LOGL_DEBUG, "Connecting media port %d->%d\n", media->description.port_local, media->description.port_remote);
switch (media->connection_data_remote.addrtype) { switch (media->connection_data_remote.addrtype) {
case osmo_cc_session_addrtype_ipv4: case osmo_cc_session_addrtype_ipv4:
@ -283,7 +311,7 @@ int osmo_cc_rtp_connect(osmo_cc_session_media_t *media)
rc = inet_pton(AF_INET, media->connection_data_remote.address, &sa4->sin_addr); rc = inet_pton(AF_INET, media->connection_data_remote.address, &sa4->sin_addr);
if (rc < 1) { if (rc < 1) {
pton_error: pton_error:
PDEBUG(DCC, DEBUG_NOTICE, "Cannot connect to address '%s'.\n", media->connection_data_remote.address); LOGP(DCC, LOGL_NOTICE, "Cannot connect to address '%s'.\n", media->connection_data_remote.address);
return -EINVAL; return -EINVAL;
} }
sport = &sa4->sin_port; sport = &sa4->sin_port;
@ -300,20 +328,20 @@ pton_error:
slen = sizeof(*sa6); slen = sizeof(*sa6);
break; break;
case osmo_cc_session_addrtype_unknown: case osmo_cc_session_addrtype_unknown:
PDEBUG(DCC, DEBUG_NOTICE, "Unsupported address type '%s'.\n", media->connection_data_local.addrtype_name); LOGP(DCC, LOGL_NOTICE, "Unsupported address type '%s'.\n", media->connection_data_local.addrtype_name);
return -EINVAL; return -EINVAL;
} }
*sport = htons(media->description.port_remote); *sport = htons(media->description.port_remote);
rc = connect(media->rtp_socket, (struct sockaddr *)&sa, slen); rc = connect(media->rtp_ofd.fd, (struct sockaddr *)&sa, slen);
if (rc < 0) { if (rc < 0) {
connect_error: connect_error:
PDEBUG(DCC, DEBUG_NOTICE, "Cannot connect to address '%s'.\n", media->connection_data_remote.address); LOGP(DCC, LOGL_NOTICE, "Cannot connect to address '%s'.\n", media->connection_data_remote.address);
osmo_cc_rtp_close(media); osmo_cc_rtp_close(media);
return -EIO; return -EIO;
} }
*sport = htons(media->description.port_remote + 1); *sport = htons(media->description.port_remote + 1);
rc = connect(media->rtcp_socket, (struct sockaddr *)&sa, slen); rc = connect(media->rtcp_ofd.fd, (struct sockaddr *)&sa, slen);
if (rc < 0) if (rc < 0)
goto connect_error; goto connect_error;
@ -321,22 +349,22 @@ connect_error:
} }
/* send rtp data with given codec */ /* 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 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; uint8_t *payload = NULL;
int payload_len = 0; int payload_len = 0;
if (!codec || !codec->media->rtp_socket) if (!codec || !codec->media->rtp_ofd.fd)
return; return;
if (codec->encoder) if (codec->encoder)
codec->encoder(data, len, &payload, &payload_len); codec->encoder(data, len, &payload, &payload_len, priv);
else { else {
payload = data; payload = data;
payload_len = len; 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); rtp_send(codec->media->rtp_ofd.fd, payload, payload_len, marker, codec->payload_type_remote, codec->media->tx_sequence, codec->media->tx_timestamp, codec->media->tx_ssrc);
codec->media->tx_sequence += inc_sequence; codec->media->tx_sequence += inc_sequence;
codec->media->tx_timestamp += inc_timestamp; codec->media->tx_timestamp += inc_timestamp;
@ -344,9 +372,9 @@ void osmo_cc_rtp_send(osmo_cc_session_codec_t *codec, uint8_t *data, int len, ui
free(payload); free(payload);
} }
/* receive rtp data for given media, return < 0, if there is nothing this time */ static int rtp_listen_cb(struct osmo_fd *ofd, unsigned int when)
int osmo_cc_rtp_receive(osmo_cc_session_media_t *media)
{ {
osmo_cc_session_media_t *media = ofd->data;
int rc; int rc;
uint8_t *payload = NULL; uint8_t *payload = NULL;
int payload_len = 0; int payload_len = 0;
@ -356,49 +384,63 @@ int osmo_cc_rtp_receive(osmo_cc_session_media_t *media)
uint8_t *data; uint8_t *data;
int len; int len;
if (!media || media->rtp_socket <= 0) if (when & OSMO_FD_READ) {
return -EIO; rc = rtp_receive(media->rtp_ofd.fd, &payload, &payload_len, &marker, &payload_type, &media->rx_sequence, &media->rx_timestamp, &media->rx_ssrc);
if (rc < 0)
return rc;
rc = rtp_receive(media->rtp_socket, &payload, &payload_len, &marker, &payload_type, &media->rx_sequence, &media->rx_timestamp, &media->rx_ssrc); /* search for codec */
if (rc < 0) for (codec = media->codec_list; codec; codec = codec->next) {
return rc; if (codec->payload_type_local == payload_type)
break;
}
if (!codec) {
LOGP(DCC, LOGL_NOTICE, "Received RTP frame for unknown codec (payload_type = %d).\n", payload_type);
return 0;
}
/* search for codec */ if (codec->decoder)
for (codec = media->codec_list; codec; codec = codec->next) { codec->decoder(payload, payload_len, &data, &len, media->session->priv);
else {
if (codec->payload_type_local == payload_type) data = payload;
break; len = payload_len;
} }
if (!codec) {
PDEBUG(DCC, DEBUG_NOTICE, "Received RTP frame for unknown codec (payload_type = %d).\n", payload_type); if (codec->media->receive)
return 0; codec->media->receiver(codec, marker, media->rx_sequence, media->rx_timestamp, media->rx_ssrc, data, len);
if (codec->decoder)
free(data);
} }
if (codec->decoder) return 0;
codec->decoder(payload, payload_len, &data, &len); }
else {
data = payload; static int rtcp_listen_cb(struct osmo_fd *ofd, unsigned int when)
len = payload_len; {
osmo_cc_session_media_t *media = ofd->data;
int rc;
if (when & OSMO_FD_READ) {
rc = rtcp_receive(media->rtp_ofd.fd);
if (rc < 0)
return rc;
} }
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; return 0;
} }
void osmo_cc_rtp_close(osmo_cc_session_media_t *media) void osmo_cc_rtp_close(osmo_cc_session_media_t *media)
{ {
if (media->rtp_socket) { if (media->rtp_ofd.fd) {
close(media->rtp_socket); osmo_fd_unregister(&media->rtp_ofd);
media->rtp_socket = 0; close(media->rtp_ofd.fd);
media->rtp_ofd.fd = 0;
} }
if (media->rtcp_socket) { if (media->rtcp_ofd.fd) {
close(media->rtcp_socket); osmo_fd_unregister(&media->rtcp_ofd);
media->rtcp_socket = 0; close(media->rtcp_ofd.fd);
media->rtcp_ofd.fd = 0;
} }
} }

View File

@ -2,7 +2,6 @@
void osmo_cc_set_rtp_ports(osmo_cc_session_config_t *conf, uint16_t from, uint16_t to); 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_open(osmo_cc_session_media_t *media);
int osmo_cc_rtp_connect(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 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 osmo_cc_rtp_close(osmo_cc_session_media_t *media); void osmo_cc_rtp_close(osmo_cc_session_media_t *media);

View File

@ -24,6 +24,7 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <unistd.h> #include <unistd.h>
#include "../libtimer/timer.h" #include "../libtimer/timer.h"
#include "../libselect/select.h"
#include "../libdebug/debug.h" #include "../libdebug/debug.h"
#include "endpoint.h" #include "endpoint.h"
#include "message.h" #include "message.h"
@ -152,7 +153,7 @@ int osmo_cc_add_screen(osmo_cc_endpoint_t *ep, const char *text)
text += 17; text += 17;
list_p = &ep->screen_called_out; list_p = &ep->screen_called_out;
} else { } 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); LOGP(DCC, LOGL_ERROR, "Invalid screening definition \"%s\". It must start with 'screen-calling-in' or 'screen-called-in' or 'screen-calling-out' or 'screen-called-out'\n", text);
return -EINVAL; return -EINVAL;
} }
@ -171,7 +172,7 @@ next_from:
token = osmo_cc_strtok_quotes(&text); token = osmo_cc_strtok_quotes(&text);
if (!token) { if (!token) {
free(list); 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); LOGP(DCC, LOGL_ERROR, "Missing 'from' string in screening definition \"%s\". If the string shall be empty, use double quotes. (\'\' or \"\")\n", text);
return -EINVAL; return -EINVAL;
} }
if (!strcasecmp(token, "unknown")) { if (!strcasecmp(token, "unknown")) {
@ -208,8 +209,8 @@ next_from:
if (no_present) { if (no_present) {
no_present_error: no_present_error:
free(list); free(list);
PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text); LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text);
PDEBUG(DCC, DEBUG_ERROR, "Keyword '%s' not allowed in screen entry for called number\n", token); LOGP(DCC, LOGL_ERROR, "Keyword '%s' not allowed in screen entry for called number\n", token);
return -EINVAL; return -EINVAL;
} }
list->has_from_present = 1; list->has_from_present = 1;
@ -231,8 +232,8 @@ no_present_error:
if (token[i] == '*') { if (token[i] == '*') {
if (star_used) { if (star_used) {
free(list); free(list);
PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text); LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text);
PDEBUG(DCC, DEBUG_ERROR, "The '*' may be used only once.\n"); LOGP(DCC, LOGL_ERROR, "The '*' may be used only once.\n");
return -EINVAL; return -EINVAL;
} }
list->from[j] = SCREEN_STAR; list->from[j] = SCREEN_STAR;
@ -250,8 +251,8 @@ next_to:
token = osmo_cc_strtok_quotes(&text); token = osmo_cc_strtok_quotes(&text);
if (!token) { if (!token) {
free(list); free(list);
PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text); LOGP(DCC, LOGL_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"); LOGP(DCC, LOGL_ERROR, "Missing screening result. If the string shall be empty, use double quotes. (\'\' or \"\")\n");
return -EINVAL; return -EINVAL;
} }
if (!strcasecmp(token, "unknown")) { if (!strcasecmp(token, "unknown")) {
@ -303,8 +304,8 @@ next_to:
if (token[i] == '*') { if (token[i] == '*') {
if (star_used) { if (star_used) {
free(list); free(list);
PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text); LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text);
PDEBUG(DCC, DEBUG_ERROR, "The '*' may be used only once.\n"); LOGP(DCC, LOGL_ERROR, "The '*' may be used only once.\n");
return -EINVAL; return -EINVAL;
} }
list->to[j] = SCREEN_STAR; list->to[j] = SCREEN_STAR;
@ -313,14 +314,14 @@ next_to:
if (token[i] == '@') { if (token[i] == '@') {
if (!calling_in) { if (!calling_in) {
free(list); free(list);
PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text); LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text);
PDEBUG(DCC, DEBUG_ERROR, "The '@' may be used only for incoming calls from interface.\n"); LOGP(DCC, LOGL_ERROR, "The '@' may be used only for incoming calls from interface.\n");
return -EINVAL; return -EINVAL;
} }
if (at_used) { if (at_used) {
free(list); free(list);
PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text); LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text);
PDEBUG(DCC, DEBUG_ERROR, "The '@' may be used only once.\n"); LOGP(DCC, LOGL_ERROR, "The '@' may be used only once.\n");
return -EINVAL; return -EINVAL;
} }
list->to[j] = SCREEN_AT; list->to[j] = SCREEN_AT;
@ -337,8 +338,8 @@ next_to:
token = osmo_cc_strtok_quotes(&text); token = osmo_cc_strtok_quotes(&text);
if (token) { if (token) {
free(list); free(list);
PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text); LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text);
PDEBUG(DCC, DEBUG_ERROR, "Got garbage behind screening result.\n"); LOGP(DCC, LOGL_ERROR, "Got garbage behind screening result.\n");
return -EINVAL; return -EINVAL;
} }
@ -391,76 +392,76 @@ static int osmo_cc_screen(const char *what, osmo_cc_screen_list_t *list, uint8_t
const char *suffix; const char *suffix;
int i, j, rule; int i, j, rule;
PDEBUG(DCC, DEBUG_INFO, "Screening %s '%s':\n", what, id_from); LOGP(DCC, LOGL_INFO, "Screening %s '%s':\n", what, id_from);
switch (*type) { switch (*type) {
case OSMO_CC_TYPE_UNKNOWN: case OSMO_CC_TYPE_UNKNOWN:
PDEBUG(DCC, DEBUG_INFO, " -> type = unknown\n"); LOGP(DCC, LOGL_INFO, " -> type = unknown\n");
break; break;
case OSMO_CC_TYPE_INTERNATIONAL: case OSMO_CC_TYPE_INTERNATIONAL:
PDEBUG(DCC, DEBUG_INFO, " -> type = international\n"); LOGP(DCC, LOGL_INFO, " -> type = international\n");
break; break;
case OSMO_CC_TYPE_NATIONAL: case OSMO_CC_TYPE_NATIONAL:
PDEBUG(DCC, DEBUG_INFO, " -> type = national\n"); LOGP(DCC, LOGL_INFO, " -> type = national\n");
break; break;
case OSMO_CC_TYPE_NETWORK: case OSMO_CC_TYPE_NETWORK:
PDEBUG(DCC, DEBUG_INFO, " -> type = network\n"); LOGP(DCC, LOGL_INFO, " -> type = network\n");
break; break;
case OSMO_CC_TYPE_SUBSCRIBER: case OSMO_CC_TYPE_SUBSCRIBER:
PDEBUG(DCC, DEBUG_INFO, " -> type = subscriber\n"); LOGP(DCC, LOGL_INFO, " -> type = subscriber\n");
break; break;
case OSMO_CC_TYPE_ABBREVIATED: case OSMO_CC_TYPE_ABBREVIATED:
PDEBUG(DCC, DEBUG_INFO, " -> type = abbreviated\n"); LOGP(DCC, LOGL_INFO, " -> type = abbreviated\n");
break; break;
} }
if (present) switch (*present) { if (present) switch (*present) {
case OSMO_CC_PRESENT_ALLOWED: case OSMO_CC_PRESENT_ALLOWED:
PDEBUG(DCC, DEBUG_INFO, " -> present = allowed\n"); LOGP(DCC, LOGL_INFO, " -> present = allowed\n");
break; break;
case OSMO_CC_PRESENT_RESTRICTED: case OSMO_CC_PRESENT_RESTRICTED:
PDEBUG(DCC, DEBUG_INFO, " -> present = restricted\n"); LOGP(DCC, LOGL_INFO, " -> present = restricted\n");
break; break;
} }
rule = 0; rule = 0;
while (list) { while (list) {
rule++; rule++;
PDEBUG(DCC, DEBUG_INFO, "Comparing with rule #%d: '%s':\n", rule, print_rule_string(list->from)); LOGP(DCC, LOGL_INFO, "Comparing with rule #%d: '%s':\n", rule, print_rule_string(list->from));
if (list->has_from_type) switch (list->from_type) { if (list->has_from_type) switch (list->from_type) {
case OSMO_CC_TYPE_UNKNOWN: case OSMO_CC_TYPE_UNKNOWN:
PDEBUG(DCC, DEBUG_INFO, " -> type = unknown\n"); LOGP(DCC, LOGL_INFO, " -> type = unknown\n");
break; break;
case OSMO_CC_TYPE_INTERNATIONAL: case OSMO_CC_TYPE_INTERNATIONAL:
PDEBUG(DCC, DEBUG_INFO, " -> type = international\n"); LOGP(DCC, LOGL_INFO, " -> type = international\n");
break; break;
case OSMO_CC_TYPE_NATIONAL: case OSMO_CC_TYPE_NATIONAL:
PDEBUG(DCC, DEBUG_INFO, " -> type = national\n"); LOGP(DCC, LOGL_INFO, " -> type = national\n");
break; break;
case OSMO_CC_TYPE_NETWORK: case OSMO_CC_TYPE_NETWORK:
PDEBUG(DCC, DEBUG_INFO, " -> type = network\n"); LOGP(DCC, LOGL_INFO, " -> type = network\n");
break; break;
case OSMO_CC_TYPE_SUBSCRIBER: case OSMO_CC_TYPE_SUBSCRIBER:
PDEBUG(DCC, DEBUG_INFO, " -> type = subscriber\n"); LOGP(DCC, LOGL_INFO, " -> type = subscriber\n");
break; break;
case OSMO_CC_TYPE_ABBREVIATED: case OSMO_CC_TYPE_ABBREVIATED:
PDEBUG(DCC, DEBUG_INFO, " -> type = abbreviated\n"); LOGP(DCC, LOGL_INFO, " -> type = abbreviated\n");
break; break;
} }
if (list->has_from_present) switch (list->from_present) { if (list->has_from_present) switch (list->from_present) {
case OSMO_CC_PRESENT_ALLOWED: case OSMO_CC_PRESENT_ALLOWED:
PDEBUG(DCC, DEBUG_INFO, " -> present = allowed\n"); LOGP(DCC, LOGL_INFO, " -> present = allowed\n");
break; break;
case OSMO_CC_PRESENT_RESTRICTED: case OSMO_CC_PRESENT_RESTRICTED:
PDEBUG(DCC, DEBUG_INFO, " -> present = restricted\n"); LOGP(DCC, LOGL_INFO, " -> present = restricted\n");
break; break;
} }
suffix = NULL; suffix = NULL;
/* attributes do not match */ /* attributes do not match */
if (list->has_from_type && list->from_type != *type) { if (list->has_from_type && list->from_type != *type) {
PDEBUG(DCC, DEBUG_INFO, "Rule does not match, because 'type' is different.\n"); LOGP(DCC, LOGL_INFO, "Rule does not match, because 'type' is different.\n");
continue; continue;
} }
if (present && list->has_from_present && list->from_present != *present) { if (present && list->has_from_present && list->from_present != *present) {
PDEBUG(DCC, DEBUG_INFO, "Rule does not match, because 'present' is different.\n"); LOGP(DCC, LOGL_INFO, "Rule does not match, because 'present' is different.\n");
continue; continue;
} }
for (i = 0; list->from[i] && id_from[i]; i++) { for (i = 0; list->from[i] && id_from[i]; i++) {
@ -484,7 +485,7 @@ static int osmo_cc_screen(const char *what, osmo_cc_screen_list_t *list, uint8_t
/* if all digits have matched */ /* if all digits have matched */
if (list->from[i] == '\0' && id_from[i] == '\0') if (list->from[i] == '\0' && id_from[i] == '\0')
break; break;
PDEBUG(DCC, DEBUG_INFO, "Rule does not match, because %s is different.\n", what); LOGP(DCC, LOGL_INFO, "Rule does not match, because %s is different.\n", what);
list = list->next; list = list->next;
} }
@ -521,37 +522,37 @@ static int osmo_cc_screen(const char *what, osmo_cc_screen_list_t *list, uint8_t
} }
id_to[j] = '\0'; id_to[j] = '\0';
PDEBUG(DCC, DEBUG_INFO, "Rule matches, changing %s to '%s'.\n", what, print_rule_string(id_to)); LOGP(DCC, LOGL_INFO, "Rule matches, changing %s to '%s'.\n", what, print_rule_string(id_to));
if (list->has_to_type) switch (list->to_type) { if (list->has_to_type) switch (list->to_type) {
case OSMO_CC_TYPE_UNKNOWN: case OSMO_CC_TYPE_UNKNOWN:
PDEBUG(DCC, DEBUG_INFO, " -> type = unknown\n"); LOGP(DCC, LOGL_INFO, " -> type = unknown\n");
break; break;
case OSMO_CC_TYPE_INTERNATIONAL: case OSMO_CC_TYPE_INTERNATIONAL:
PDEBUG(DCC, DEBUG_INFO, " -> type = international\n"); LOGP(DCC, LOGL_INFO, " -> type = international\n");
break; break;
case OSMO_CC_TYPE_NATIONAL: case OSMO_CC_TYPE_NATIONAL:
PDEBUG(DCC, DEBUG_INFO, " -> type = national\n"); LOGP(DCC, LOGL_INFO, " -> type = national\n");
break; break;
case OSMO_CC_TYPE_NETWORK: case OSMO_CC_TYPE_NETWORK:
PDEBUG(DCC, DEBUG_INFO, " -> type = network\n"); LOGP(DCC, LOGL_INFO, " -> type = network\n");
break; break;
case OSMO_CC_TYPE_SUBSCRIBER: case OSMO_CC_TYPE_SUBSCRIBER:
PDEBUG(DCC, DEBUG_INFO, " -> type = subscriber\n"); LOGP(DCC, LOGL_INFO, " -> type = subscriber\n");
break; break;
case OSMO_CC_TYPE_ABBREVIATED: case OSMO_CC_TYPE_ABBREVIATED:
PDEBUG(DCC, DEBUG_INFO, " -> type = abbreviated\n"); LOGP(DCC, LOGL_INFO, " -> type = abbreviated\n");
break; break;
} }
if (list->has_to_present) switch (list->to_present) { if (list->has_to_present) switch (list->to_present) {
case OSMO_CC_PRESENT_ALLOWED: case OSMO_CC_PRESENT_ALLOWED:
PDEBUG(DCC, DEBUG_INFO, " -> present = allowed\n"); LOGP(DCC, LOGL_INFO, " -> present = allowed\n");
break; break;
case OSMO_CC_PRESENT_RESTRICTED: case OSMO_CC_PRESENT_RESTRICTED:
PDEBUG(DCC, DEBUG_INFO, " -> present = restricted\n"); LOGP(DCC, LOGL_INFO, " -> present = restricted\n");
break; break;
} }
if (routing_p && *routing_p) if (routing_p && *routing_p)
PDEBUG(DCC, DEBUG_INFO, " -> remote = %s\n", *routing_p); LOGP(DCC, LOGL_INFO, " -> remote = %s\n", *routing_p);
return 0; return 0;
} }

View File

@ -25,6 +25,7 @@
#include <errno.h> #include <errno.h>
#include "../libdebug/debug.h" #include "../libdebug/debug.h"
#include "../libtimer/timer.h" #include "../libtimer/timer.h"
#include "../libselect/select.h"
#include "endpoint.h" #include "endpoint.h"
#include "sdp.h" #include "sdp.h"
@ -135,7 +136,7 @@ char *osmo_cc_session_gensdp(osmo_cc_session_t *session)
/* check for overflow and return */ /* check for overflow and return */
if (strlen(sdp) == sizeof(sdp) - 1) { 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)); LOGP(DCC, LOGL_ERROR, "Fatal error: Allocated SDP buffer with %d bytes is too small, please fix!\n", (int)sizeof(sdp));
return NULL; return NULL;
} }
return sdp; return sdp;
@ -285,21 +286,21 @@ struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf,
continue; continue;
if (line[1] != '=') { if (line[1] != '=') {
PDEBUG(DCC, DEBUG_NOTICE, "SDP line %d = '%s' is garbage, expecting '=' as second character.\n", line_no, line); LOGP(DCC, LOGL_NOTICE, "SDP line %d = '%s' is garbage, expecting '=' as second character.\n", line_no, line);
continue; continue;
} }
switch(line[0]) { switch(line[0]) {
case 'v': case 'v':
PDEBUG(DCC, DEBUG_DEBUG, " -> Version: %s\n", next_word); LOGP(DCC, LOGL_DEBUG, " -> Version: %s\n", next_word);
if (atoi(next_word) != 0) { if (atoi(next_word) != 0) {
PDEBUG(DCC, DEBUG_NOTICE, "SDP line %d = '%s' describes unsupported version.\n", line_no, line); LOGP(DCC, LOGL_NOTICE, "SDP line %d = '%s' describes unsupported version.\n", line_no, line);
osmo_cc_free_session(session); osmo_cc_free_session(session);
return NULL; return NULL;
} }
break; break;
case 'o': case 'o':
PDEBUG(DCC, DEBUG_DEBUG, " -> Originator: %s\n", next_word); LOGP(DCC, LOGL_DEBUG, " -> Originator: %s\n", next_word);
/* Originator */ /* Originator */
word = wordsep(&next_word); word = wordsep(&next_word);
if (!word) if (!word)
@ -334,12 +335,12 @@ struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf,
break; break;
case 's': case 's':
/* Session Name */ /* Session Name */
PDEBUG(DCC, DEBUG_DEBUG, " -> Session Name: %s\n", next_word); LOGP(DCC, LOGL_DEBUG, " -> Session Name: %s\n", next_word);
free((char *)session->name); // if already set free((char *)session->name); // if already set
session->name = strdup(next_word); session->name = strdup(next_word);
break; break;
case 'c': /* Connection Data */ case 'c': /* Connection Data */
PDEBUG(DCC, DEBUG_DEBUG, " -> Connection Data: %s\n", next_word); LOGP(DCC, LOGL_DEBUG, " -> Connection Data: %s\n", next_word);
if (media) if (media)
cd = &media->connection_data_remote; cd = &media->connection_data_remote;
else else
@ -350,7 +351,7 @@ struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf,
if (!strcmp(word, "IN")) if (!strcmp(word, "IN"))
cd->nettype = osmo_cc_session_nettype_inet; cd->nettype = osmo_cc_session_nettype_inet;
else { else {
PDEBUG(DCC, DEBUG_NOTICE, "Unsupported network type '%s' in SDP line %d = '%s'\n", word, line_no, line); LOGP(DCC, LOGL_NOTICE, "Unsupported network type '%s' in SDP line %d = '%s'\n", word, line_no, line);
break; break;
} }
/* address type */ /* address type */
@ -358,13 +359,13 @@ struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf,
break; break;
if (!strcmp(word, "IP4")) { if (!strcmp(word, "IP4")) {
cd->addrtype = osmo_cc_session_addrtype_ipv4; cd->addrtype = osmo_cc_session_addrtype_ipv4;
PDEBUG(DCC, DEBUG_DEBUG, " -> Address Type = IPv4\n"); LOGP(DCC, LOGL_DEBUG, " -> Address Type = IPv4\n");
} else } else
if (!strcmp(word, "IP6")) { if (!strcmp(word, "IP6")) {
cd->addrtype = osmo_cc_session_addrtype_ipv6; cd->addrtype = osmo_cc_session_addrtype_ipv6;
PDEBUG(DCC, DEBUG_DEBUG, " -> Address Type = IPv6\n"); LOGP(DCC, LOGL_DEBUG, " -> Address Type = IPv6\n");
} else { } else {
PDEBUG(DCC, DEBUG_NOTICE, "Unsupported address type '%s' in SDP line %d = '%s'\n", word, line_no, line); LOGP(DCC, LOGL_NOTICE, "Unsupported address type '%s' in SDP line %d = '%s'\n", word, line_no, line);
break; break;
} }
/* connection address */ /* connection address */
@ -374,10 +375,10 @@ struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf,
*p++ = '\0'; *p++ = '\0';
free((char *)cd->address); // in case of multiple lines of 'c' free((char *)cd->address); // in case of multiple lines of 'c'
cd->address = strdup(word); cd->address = strdup(word);
PDEBUG(DCC, DEBUG_DEBUG, " -> Address = %s\n", word); LOGP(DCC, LOGL_DEBUG, " -> Address = %s\n", word);
break; break;
case 'm': /* Media Description */ case 'm': /* Media Description */
PDEBUG(DCC, DEBUG_DEBUG, " -> Media Description: %s\n", next_word); LOGP(DCC, LOGL_DEBUG, " -> Media Description: %s\n", next_word);
/* add media description */ /* add media description */
media = osmo_cc_add_media(session, 0, 0, NULL, 0, 0, 0, csend, creceive, NULL, 0); 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 */ /* copy common connection data from common connection, if exists */
@ -394,7 +395,7 @@ struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf,
else { else {
media->description.type = osmo_cc_session_media_type_unknown; media->description.type = osmo_cc_session_media_type_unknown;
media->description.type_name = strdup(word); media->description.type_name = strdup(word);
PDEBUG(DCC, DEBUG_DEBUG, "Unsupported media type in SDP line %d = '%s'\n", line_no, line); LOGP(DCC, LOGL_DEBUG, "Unsupported media type in SDP line %d = '%s'\n", line_no, line);
} }
/* port */ /* port */
if (!(word = wordsep(&next_word))) if (!(word = wordsep(&next_word)))
@ -408,7 +409,7 @@ struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf,
else { else {
media->description.proto = osmo_cc_session_media_proto_unknown; media->description.proto = osmo_cc_session_media_proto_unknown;
media->description.proto_name = strdup(word); media->description.proto_name = strdup(word);
PDEBUG(DCC, DEBUG_NOTICE, "Unsupported protocol type in SDP line %d = '%s'\n", line_no, line); LOGP(DCC, LOGL_NOTICE, "Unsupported protocol type in SDP line %d = '%s'\n", line_no, line);
break; break;
} }
/* create codec description for each codec and link */ /* create codec description for each codec and link */
@ -418,17 +419,17 @@ struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf,
/* fmt */ /* fmt */
codec->payload_type_remote = atoi(word); codec->payload_type_remote = atoi(word);
complete_codec_by_fmt(codec->payload_type_remote, &codec->payload_name, &codec->payload_rate, &codec->payload_channels); 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); LOGP(DCC, LOGL_DEBUG, " -> payload type = %d\n", codec->payload_type_remote);
if (codec->payload_name) if (codec->payload_name)
PDEBUG(DCC, DEBUG_DEBUG, " -> payload name = %s\n", codec->payload_name); LOGP(DCC, LOGL_DEBUG, " -> payload name = %s\n", codec->payload_name);
if (codec->payload_rate) if (codec->payload_rate)
PDEBUG(DCC, DEBUG_DEBUG, " -> payload rate = %d\n", codec->payload_rate); LOGP(DCC, LOGL_DEBUG, " -> payload rate = %d\n", codec->payload_rate);
if (codec->payload_channels) if (codec->payload_channels)
PDEBUG(DCC, DEBUG_DEBUG, " -> payload channels = %d\n", codec->payload_channels); LOGP(DCC, LOGL_DEBUG, " -> payload channels = %d\n", codec->payload_channels);
} }
break; break;
case 'a': case 'a':
PDEBUG(DCC, DEBUG_DEBUG, " -> Attribute: %s\n", next_word); LOGP(DCC, LOGL_DEBUG, " -> Attribute: %s\n", next_word);
word = wordsep(&next_word); word = wordsep(&next_word);
if (!strcmp(word, "sendrecv")) { if (!strcmp(word, "sendrecv")) {
if (media) { if (media) {
@ -471,7 +472,7 @@ struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf,
break; break;
} else } else
if (!media) { if (!media) {
PDEBUG(DCC, DEBUG_NOTICE, "Attribute without previously defined media in SDP line %d = '%s'\n", line_no, line); LOGP(DCC, LOGL_NOTICE, "Attribute without previously defined media in SDP line %d = '%s'\n", line_no, line);
break; break;
} }
if (!strncmp(word, "rtpmap:", 7)) { if (!strncmp(word, "rtpmap:", 7)) {
@ -481,23 +482,23 @@ struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf,
break; break;
} }
if (!codec) { if (!codec) {
PDEBUG(DCC, DEBUG_NOTICE, "Attribute without previously defined codec in SDP line %d = '%s'\n", line_no, line); LOGP(DCC, LOGL_NOTICE, "Attribute without previously defined codec in SDP line %d = '%s'\n", line_no, line);
break; break;
} }
PDEBUG(DCC, DEBUG_DEBUG, " -> (rtpmap) payload type = %d\n", codec->payload_type_remote); LOGP(DCC, LOGL_DEBUG, " -> (rtpmap) payload type = %d\n", codec->payload_type_remote);
if (!(word = wordsep(&next_word))) if (!(word = wordsep(&next_word)))
goto rtpmap_done; goto rtpmap_done;
if ((p = strchr(word, '/'))) if ((p = strchr(word, '/')))
*p++ = '\0'; *p++ = '\0';
free((char *)codec->payload_name); // in case it is already set above free((char *)codec->payload_name); // in case it is already set above
codec->payload_name = strdup(word); codec->payload_name = strdup(word);
PDEBUG(DCC, DEBUG_DEBUG, " -> (rtpmap) payload name = %s\n", codec->payload_name); LOGP(DCC, LOGL_DEBUG, " -> (rtpmap) payload name = %s\n", codec->payload_name);
if (!(word = p)) if (!(word = p))
goto rtpmap_done; goto rtpmap_done;
if ((p = strchr(word, '/'))) if ((p = strchr(word, '/')))
*p++ = '\0'; *p++ = '\0';
codec->payload_rate = atoi(word); codec->payload_rate = atoi(word);
PDEBUG(DCC, DEBUG_DEBUG, " -> (rtpmap) payload rate = %d\n", codec->payload_rate); LOGP(DCC, LOGL_DEBUG, " -> (rtpmap) payload rate = %d\n", codec->payload_rate);
if (!(word = p)) { if (!(word = p)) {
/* if no channel is given and no default was specified, we must set 1 channel */ /* if no channel is given and no default was specified, we must set 1 channel */
if (!codec->payload_channels) if (!codec->payload_channels)
@ -505,10 +506,10 @@ struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf,
goto rtpmap_done; goto rtpmap_done;
} }
codec->payload_channels = atoi(word); codec->payload_channels = atoi(word);
PDEBUG(DCC, DEBUG_DEBUG, " -> (rtpmap) payload channels = %d\n", codec->payload_channels); LOGP(DCC, LOGL_DEBUG, " -> (rtpmap) payload channels = %d\n", codec->payload_channels);
rtpmap_done: rtpmap_done:
if (!codec->payload_name || !codec->payload_rate || !codec->payload_channels) { 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); LOGP(DCC, LOGL_NOTICE, "Broken 'rtpmap' definition in SDP line %d = '%s' Skipping codec!\n", line_no, line);
osmo_cc_free_codec(codec); osmo_cc_free_codec(codec);
} }
} }
@ -518,7 +519,7 @@ struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf,
/* if something is incomplete, abort here */ /* if something is incomplete, abort here */
if (osmo_cc_session_check(session, 1)) { if (osmo_cc_session_check(session, 1)) {
PDEBUG(DCC, DEBUG_NOTICE, "Parsing SDP failed.\n"); LOGP(DCC, LOGL_NOTICE, "Parsing SDP failed.\n");
osmo_cc_free_session(session); osmo_cc_free_session(session);
return NULL; return NULL;
} }
@ -536,7 +537,7 @@ void osmo_cc_debug_sdp(const char *_sdp)
for (i = 0; *sdp > 0 && *sdp >= 32 && i < (int)sizeof(text) - 1; i++) for (i = 0; *sdp > 0 && *sdp >= 32 && i < (int)sizeof(text) - 1; i++)
text[i] = *sdp++; text[i] = *sdp++;
text[i] = '\0'; text[i] = '\0';
PDEBUG(DCC, DEBUG_DEBUG, " | %s\n", text); LOGP(DCC, LOGL_DEBUG, " | %s\n", text);
while (*sdp > 0 && *sdp < 32) while (*sdp > 0 && *sdp < 32)
sdp++; sdp++;
} }

View File

@ -25,6 +25,7 @@
#include <sys/time.h> #include <sys/time.h>
#include <inttypes.h> #include <inttypes.h>
#include "../libtimer/timer.h" #include "../libtimer/timer.h"
#include "../libselect/select.h"
#include "../libdebug/debug.h" #include "../libdebug/debug.h"
#include "../liboptions/options.h" #include "../liboptions/options.h"
#include "endpoint.h" #include "endpoint.h"
@ -42,11 +43,11 @@ osmo_cc_session_t *osmo_cc_new_session(osmo_cc_session_config_t *conf, void *pri
{ {
osmo_cc_session_t *session; osmo_cc_session_t *session;
if (debug) PDEBUG(DCC, DEBUG_DEBUG, "Creating session structure.\n"); if (debug) LOGP(DCC, LOGL_DEBUG, "Creating session structure.\n");
session = calloc(1, sizeof(*session)); session = calloc(1, sizeof(*session));
if (!session) { if (!session) {
PDEBUG(DCC, DEBUG_ERROR, "No mem!\n"); LOGP(DCC, LOGL_ERROR, "No mem!\n");
abort(); abort();
} }
session->config = conf; session->config = conf;
@ -55,7 +56,7 @@ osmo_cc_session_t *osmo_cc_new_session(osmo_cc_session_config_t *conf, void *pri
int i; int i;
for (i = 0; username[i]; i++) { for (i = 0; username[i]; i++) {
if ((uint8_t)username[i] < 33) { if ((uint8_t)username[i] < 33) {
PDEBUG(DCC, DEBUG_ERROR, "Fatal error: SDP's originator (username) uses invalid characters, please fix!\n"); LOGP(DCC, LOGL_ERROR, "Fatal error: SDP's originator (username) uses invalid characters, please fix!\n");
abort(); abort();
} }
} }
@ -63,7 +64,7 @@ osmo_cc_session_t *osmo_cc_new_session(osmo_cc_session_config_t *conf, void *pri
} }
if (!username) if (!username)
session->origin_local.username = strdup("-"); session->origin_local.username = strdup("-");
if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> user name = %s\n", session->origin_local.username); if (debug) LOGP(DCC, LOGL_DEBUG, " -> user name = %s\n", session->origin_local.username);
if (sess_id) if (sess_id)
session->origin_local.sess_id = strdup(sess_id); session->origin_local.sess_id = strdup(sess_id);
if (sess_version) if (sess_version)
@ -79,35 +80,35 @@ osmo_cc_session_t *osmo_cc_new_session(osmo_cc_session_config_t *conf, void *pri
if (!sess_version) if (!sess_version)
session->origin_local.sess_version = strdup(ntp_timestamp); 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) LOGP(DCC, LOGL_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 (debug) LOGP(DCC, LOGL_DEBUG, " -> session version = %s\n", session->origin_local.sess_version);
if (nettype) if (nettype)
session->origin_local.nettype = strdup(osmo_cc_session_nettype2string(nettype)); session->origin_local.nettype = strdup(osmo_cc_session_nettype2string(nettype));
else else
session->origin_local.nettype = strdup(osmo_cc_session_nettype2string(conf->default_nettype)); 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 (debug) LOGP(DCC, LOGL_DEBUG, " -> network type = %s\n", session->origin_local.nettype);
if (addrtype) if (addrtype)
session->origin_local.addrtype = strdup(osmo_cc_session_addrtype2string(addrtype)); session->origin_local.addrtype = strdup(osmo_cc_session_addrtype2string(addrtype));
else else
session->origin_local.addrtype = strdup(osmo_cc_session_addrtype2string(conf->default_addrtype)); 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 (debug) LOGP(DCC, LOGL_DEBUG, " -> address type = %s\n", session->origin_local.addrtype);
if (unicast_address) if (unicast_address)
session->origin_local.unicast_address = strdup(unicast_address); session->origin_local.unicast_address = strdup(unicast_address);
else else
session->origin_local.unicast_address = strdup(conf->default_unicast_address); 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 (debug) LOGP(DCC, LOGL_DEBUG, " -> unicast address = %s\n", session->origin_local.unicast_address);
if (session_name) if (session_name)
session->name = strdup(session_name); session->name = strdup(session_name);
if (!session_name) if (!session_name)
session->name = strdup("-"); session->name = strdup("-");
if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> session name = %s\n", session->name); if (debug) LOGP(DCC, LOGL_DEBUG, " -> session name = %s\n", session->name);
return session; return session;
} }
void osmo_cc_free_session(osmo_cc_session_t *session) void osmo_cc_free_session(osmo_cc_session_t *session)
{ {
PDEBUG(DCC, DEBUG_DEBUG, "Free session structure.\n"); LOGP(DCC, LOGL_DEBUG, "Free session structure.\n");
free((char *)session->origin_local.username); free((char *)session->origin_local.username);
free((char *)session->origin_local.sess_id); free((char *)session->origin_local.sess_id);
@ -134,7 +135,7 @@ osmo_cc_session_media_t *osmo_cc_add_media(osmo_cc_session_t *session, enum osmo
media = calloc(1, sizeof(*media)); media = calloc(1, sizeof(*media));
if (!media) { if (!media) {
PDEBUG(DCC, DEBUG_ERROR, "No mem!\n"); LOGP(DCC, LOGL_ERROR, "No mem!\n");
abort(); abort();
} }
media->session = session; media->session = session;
@ -163,14 +164,14 @@ osmo_cc_session_media_t *osmo_cc_add_media(osmo_cc_session_t *session, enum osmo
mediap = &((*mediap)->next); mediap = &((*mediap)->next);
*mediap = media; *mediap = media;
if (debug) PDEBUG(DCC, DEBUG_DEBUG, "Adding session media.\n"); if (debug) LOGP(DCC, LOGL_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) LOGP(DCC, LOGL_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) LOGP(DCC, LOGL_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) LOGP(DCC, LOGL_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) LOGP(DCC, LOGL_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) LOGP(DCC, LOGL_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) LOGP(DCC, LOGL_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); if (debug) LOGP(DCC, LOGL_DEBUG, "Opening and binding media port %d\n", media->description.port_local);
return media; return media;
} }
@ -179,7 +180,7 @@ void osmo_cc_free_media(osmo_cc_session_media_t *media)
{ {
osmo_cc_session_media_t **mediap; osmo_cc_session_media_t **mediap;
PDEBUG(DCC, DEBUG_DEBUG, "Free session media.\n"); LOGP(DCC, LOGL_DEBUG, "Free session media.\n");
osmo_cc_rtp_close(media); osmo_cc_rtp_close(media);
free((char *)media->connection_data_local.nettype_name); free((char *)media->connection_data_local.nettype_name);
@ -197,14 +198,14 @@ void osmo_cc_free_media(osmo_cc_session_media_t *media)
free(media); free(media);
} }
osmo_cc_session_codec_t *osmo_cc_add_codec(osmo_cc_session_media_t *media, const char *payload_name, uint32_t payload_rate, int payload_channels, void (*encoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len), void (*decoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len), int debug) osmo_cc_session_codec_t *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; osmo_cc_session_codec_t *codec, **codecp;
int rc; int rc;
codec = calloc(1, sizeof(*codec)); codec = calloc(1, sizeof(*codec));
if (!codec) { if (!codec) {
PDEBUG(DCC, DEBUG_ERROR, "No mem!\n"); LOGP(DCC, LOGL_ERROR, "No mem!\n");
abort(); abort();
} }
codec->media = media; codec->media = media;
@ -231,11 +232,11 @@ osmo_cc_session_codec_t *osmo_cc_add_codec(osmo_cc_session_media_t *media, const
codecp = &((*codecp)->next); codecp = &((*codecp)->next);
*codecp = codec; *codecp = codec;
if (debug) PDEBUG(DCC, DEBUG_DEBUG, "Adding session codec.\n"); if (debug) LOGP(DCC, LOGL_DEBUG, "Adding session codec.\n");
if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> payload type = %d\n", codec->payload_type_local); if (debug) LOGP(DCC, LOGL_DEBUG, " -> payload type = %d\n", codec->payload_type_local);
if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> payload name = %s\n", codec->payload_name); if (debug) LOGP(DCC, LOGL_DEBUG, " -> payload name = %s\n", codec->payload_name);
if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> payload rate = %d\n", codec->payload_rate); if (debug) LOGP(DCC, LOGL_DEBUG, " -> payload rate = %d\n", codec->payload_rate);
if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> payload channels = %d\n", codec->payload_channels); if (debug) LOGP(DCC, LOGL_DEBUG, " -> payload channels = %d\n", codec->payload_channels);
return codec; return codec;
} }
@ -244,7 +245,7 @@ void osmo_cc_free_codec(osmo_cc_session_codec_t *codec)
{ {
osmo_cc_session_codec_t **codecp; osmo_cc_session_codec_t **codecp;
PDEBUG(DCC, DEBUG_DEBUG, "Free session codec.\n"); LOGP(DCC, LOGL_DEBUG, "Free session codec.\n");
free((char *)codec->payload_name); free((char *)codec->payload_name);
codecp = &codec->media->codec_list; codecp = &codec->media->codec_list;
@ -273,15 +274,15 @@ int osmo_cc_session_check(osmo_cc_session_t *session, int remote)
|| !orig->nettype || !orig->nettype
|| !orig->addrtype || !orig->addrtype
|| !orig->unicast_address) { || !orig->unicast_address) {
PDEBUG(DCC, DEBUG_NOTICE, "Missing data in session origin\n"); LOGP(DCC, LOGL_NOTICE, "Missing data in session origin\n");
return -EINVAL; return -EINVAL;
} }
if (!session->name) { if (!session->name) {
PDEBUG(DCC, DEBUG_NOTICE, "Missing data in session origin\n"); LOGP(DCC, LOGL_NOTICE, "Missing data in session origin\n");
return -EINVAL; return -EINVAL;
} }
if (!session->media_list) { if (!session->media_list) {
PDEBUG(DCC, DEBUG_NOTICE, "Missing media session\n"); LOGP(DCC, LOGL_NOTICE, "Missing media session\n");
return -EINVAL; return -EINVAL;
} }
i = 0; i = 0;
@ -292,39 +293,39 @@ int osmo_cc_session_check(osmo_cc_session_t *session, int remote)
else else
cd = &media->connection_data_local; cd = &media->connection_data_local;
if (!cd->nettype && !cd->nettype_name) { if (!cd->nettype && !cd->nettype_name) {
PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d is missing connection network type\n", i); LOGP(DCC, LOGL_NOTICE, "Session with media #%d is missing connection network type\n", i);
return -EINVAL; return -EINVAL;
} }
if (!cd->addrtype && !cd->addrtype_name) { if (!cd->addrtype && !cd->addrtype_name) {
PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d is missing connection address type\n", i); LOGP(DCC, LOGL_NOTICE, "Session with media #%d is missing connection address type\n", i);
return -EINVAL; return -EINVAL;
} }
if (!cd->address) { if (!cd->address) {
PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d is missing connection address\n", i); LOGP(DCC, LOGL_NOTICE, "Session with media #%d is missing connection address\n", i);
return -EINVAL; return -EINVAL;
} }
md = &media->description; md = &media->description;
if (!md->type && !md->type_name) { if (!md->type && !md->type_name) {
PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d is missing media type\n", i); LOGP(DCC, LOGL_NOTICE, "Session with media #%d is missing media type\n", i);
return -EINVAL; return -EINVAL;
} }
if (!md->proto && !md->proto_name) { if (!md->proto && !md->proto_name) {
PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d is missing protocol\n", i); LOGP(DCC, LOGL_NOTICE, "Session with media #%d is missing protocol\n", i);
return -EINVAL; return -EINVAL;
} }
j = 0; j = 0;
osmo_cc_session_for_each_codec(media->codec_list, codec) { osmo_cc_session_for_each_codec(media->codec_list, codec) {
j++; j++;
if (!codec->payload_name) { if (!codec->payload_name) {
PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d, codec #%d is missing name\n", i, j); LOGP(DCC, LOGL_NOTICE, "Session with media #%d, codec #%d is missing name\n", i, j);
return -EINVAL; return -EINVAL;
} }
if (!codec->payload_rate) { if (!codec->payload_rate) {
PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d, codec #%d is missing rate\n", i, j); LOGP(DCC, LOGL_NOTICE, "Session with media #%d, codec #%d is missing rate\n", i, j);
return -EINVAL; return -EINVAL;
} }
if (!codec->payload_channels) { if (!codec->payload_channels) {
PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d, codec #%d is missing channel count\n", i, j); LOGP(DCC, LOGL_NOTICE, "Session with media #%d, codec #%d is missing channel count\n", i, j);
return -EINVAL; return -EINVAL;
} }
} }
@ -339,11 +340,11 @@ const char *osmo_cc_session_send_offer(osmo_cc_session_t *session)
const char *sdp; const char *sdp;
int rc; int rc;
PDEBUG(DCC, DEBUG_DEBUG, "Generating session offer and opening RTP stream.\n"); LOGP(DCC, LOGL_DEBUG, "Generating session offer and opening RTP stream.\n");
rc = osmo_cc_session_check(session, 0); rc = osmo_cc_session_check(session, 0);
if (rc < 0) { if (rc < 0) {
PDEBUG(DCC, DEBUG_ERROR, "Please fix!\n"); LOGP(DCC, LOGL_ERROR, "Please fix!\n");
abort(); abort();
} }
@ -358,7 +359,7 @@ osmo_cc_session_t *osmo_cc_session_receive_offer(osmo_cc_session_config_t *conf,
osmo_cc_session_t *session; osmo_cc_session_t *session;
int rc; int rc;
PDEBUG(DCC, DEBUG_DEBUG, "Parsing session offer.\n"); LOGP(DCC, LOGL_DEBUG, "Parsing session offer.\n");
osmo_cc_debug_sdp(sdp); osmo_cc_debug_sdp(sdp);
session = osmo_cc_session_parsesdp(conf, priv, sdp); session = osmo_cc_session_parsesdp(conf, priv, sdp);
@ -396,14 +397,14 @@ void osmo_cc_session_accept_media(osmo_cc_session_media_t *media, enum osmo_cc_s
media->receive = receive; media->receive = receive;
media->receiver = receiver; media->receiver = receiver;
PDEBUG(DCC, DEBUG_DEBUG, "Accepting session media.\n"); LOGP(DCC, LOGL_DEBUG, "Accepting session media.\n");
PDEBUG(DCC, DEBUG_DEBUG, " -> network type = %s\n", osmo_cc_session_nettype2string(media->connection_data_local.nettype)); LOGP(DCC, LOGL_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)); LOGP(DCC, LOGL_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); LOGP(DCC, LOGL_DEBUG, " -> address = %s\n", media->connection_data_local.address);
} }
void osmo_cc_session_accept_codec(osmo_cc_session_codec_t *codec, void (*encoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len), void (*decoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_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))
{ {
codec->accepted = 1; codec->accepted = 1;
codec->encoder = encoder; codec->encoder = encoder;
@ -411,11 +412,11 @@ void osmo_cc_session_accept_codec(osmo_cc_session_codec_t *codec, void (*encoder
/* when we accept a codec, we just use the same payload type as the remote */ /* when we accept a codec, we just use the same payload type as the remote */
codec->payload_type_local = codec->payload_type_remote; codec->payload_type_local = codec->payload_type_remote;
PDEBUG(DCC, DEBUG_DEBUG, "Accepting session codec.\n"); LOGP(DCC, LOGL_DEBUG, "Accepting session codec.\n");
PDEBUG(DCC, DEBUG_DEBUG, " -> payload type = %d\n", codec->payload_type_local); LOGP(DCC, LOGL_DEBUG, " -> payload type = %d\n", codec->payload_type_local);
PDEBUG(DCC, DEBUG_DEBUG, " -> payload name = %s\n", codec->payload_name); LOGP(DCC, LOGL_DEBUG, " -> payload name = %s\n", codec->payload_name);
PDEBUG(DCC, DEBUG_DEBUG, " -> payload rate = %d\n", codec->payload_rate); LOGP(DCC, LOGL_DEBUG, " -> payload rate = %d\n", codec->payload_rate);
PDEBUG(DCC, DEBUG_DEBUG, " -> payload channels = %d\n", codec->payload_channels); LOGP(DCC, LOGL_DEBUG, " -> payload channels = %d\n", codec->payload_channels);
} }
/* remove codecs/media that have not been accepted and generate SDP */ /* remove codecs/media that have not been accepted and generate SDP */
@ -426,7 +427,7 @@ const char *osmo_cc_session_send_answer(osmo_cc_session_t *session)
const char *sdp; const char *sdp;
int rc; int rc;
PDEBUG(DCC, DEBUG_DEBUG, "Generating session answer.\n"); LOGP(DCC, LOGL_DEBUG, "Generating session answer.\n");
/* loop all media */ /* loop all media */
osmo_cc_session_for_each_media(session->media_list, media) { osmo_cc_session_for_each_media(session->media_list, media) {
@ -449,7 +450,7 @@ const char *osmo_cc_session_send_answer(osmo_cc_session_t *session)
rc = osmo_cc_session_check(session, 0); rc = osmo_cc_session_check(session, 0);
if (rc < 0) { if (rc < 0) {
PDEBUG(DCC, DEBUG_ERROR, "Please fix!\n"); LOGP(DCC, LOGL_ERROR, "Please fix!\n");
abort(); abort();
} }
@ -469,7 +470,7 @@ static int osmo_cc_session_negotiate(osmo_cc_session_t *session_local, struct os
osmo_cc_session_codec_t *codec_local, *codec_remote, **codec_local_p; osmo_cc_session_codec_t *codec_local, *codec_remote, **codec_local_p;
int rc; int rc;
PDEBUG(DCC, DEBUG_DEBUG, "Negotiating session.\n"); LOGP(DCC, LOGL_DEBUG, "Negotiating session.\n");
/* copy remote session information */ /* copy remote session information */
session_local->origin_remote.username = strdup(session_remote->origin_remote.username); session_local->origin_remote.username = strdup(session_remote->origin_remote.username);
@ -516,11 +517,11 @@ static int osmo_cc_session_negotiate(osmo_cc_session_t *session_local, struct os
} }
} }
if (media_local) { if (media_local) {
PDEBUG(DCC, DEBUG_NOTICE, "Negotiation failed, because remote endpoint returns less media streams than we offered.\n"); LOGP(DCC, LOGL_NOTICE, "Negotiation failed, because remote endpoint returns less media streams than we offered.\n");
return -EINVAL; return -EINVAL;
} }
if (media_remote) { if (media_remote) {
PDEBUG(DCC, DEBUG_NOTICE, "Negotiation failed, because remote endpoint returns more media streams than we offered.\n"); LOGP(DCC, LOGL_NOTICE, "Negotiation failed, because remote endpoint returns more media streams than we offered.\n");
return -EINVAL; return -EINVAL;
} }
@ -549,7 +550,7 @@ int osmo_cc_session_receive_answer(osmo_cc_session_t *session, const char *sdp)
osmo_cc_session_t *session_remote; osmo_cc_session_t *session_remote;
int rc; int rc;
PDEBUG(DCC, DEBUG_DEBUG, "Parsing session answer.\n"); LOGP(DCC, LOGL_DEBUG, "Parsing session answer.\n");
osmo_cc_debug_sdp(sdp); osmo_cc_debug_sdp(sdp);
session_remote = osmo_cc_session_parsesdp(session->config, NULL, sdp); session_remote = osmo_cc_session_parsesdp(session->config, NULL, sdp);
@ -622,19 +623,3 @@ int osmo_cc_session_if_codec(osmo_cc_session_codec_t *codec, const char *name, u
&& codec->payload_channels == channels); && codec->payload_channels == channels);
} }
int osmo_cc_session_handle(osmo_cc_session_t *session)
{
osmo_cc_session_media_t *media;
int w = 0, rc;
osmo_cc_session_for_each_media(session->media_list, media) {
do {
rc = osmo_cc_rtp_receive(media);
if (rc >= 0)
w = 1;
} while (rc >= 0);
}
return w;
}

View File

@ -80,8 +80,8 @@ typedef struct osmo_cc_session_media {
struct osmo_cc_session_codec *codec_list; struct osmo_cc_session_codec *codec_list;
int send, receive; 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); 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; struct osmo_fd rtp_ofd;
int rtcp_socket; struct osmo_fd rtcp_ofd;
uint32_t tx_ssrc, rx_ssrc; uint32_t tx_ssrc, rx_ssrc;
uint16_t tx_sequence, rx_sequence; uint16_t tx_sequence, rx_sequence;
uint32_t tx_timestamp, rx_timestamp; uint32_t tx_timestamp, rx_timestamp;
@ -96,8 +96,8 @@ typedef struct osmo_cc_session_codec {
const char *payload_name; const char *payload_name;
uint32_t payload_rate; uint32_t payload_rate;
int payload_channels; int payload_channels;
void (*encoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len); 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 (*decoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len, void *priv);
int accepted; int accepted;
} osmo_cc_session_codec_t; } osmo_cc_session_codec_t;
@ -112,13 +112,13 @@ osmo_cc_session_t *osmo_cc_new_session(osmo_cc_session_config_t *conf, void *pri
void osmo_cc_free_session(osmo_cc_session_t *session); 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); 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); void osmo_cc_free_media(osmo_cc_session_media_t *media);
osmo_cc_session_codec_t *osmo_cc_add_codec(osmo_cc_session_media_t *media, const char *playload_name, uint32_t playload_rate, int playload_channels, void (*encoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len), void (*decoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len), int debug); 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); void osmo_cc_free_codec(osmo_cc_session_codec_t *codec);
int osmo_cc_session_check(struct osmo_cc_session *session, int remote); int osmo_cc_session_check(struct osmo_cc_session *session, int remote);
const char *osmo_cc_session_send_offer(osmo_cc_session_t *session); 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); 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_media(osmo_cc_session_media_t *media, enum osmo_cc_session_nettype nettype, enum osmo_cc_session_addrtype addrtype, const char *address, int send, int receive, void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len));
void osmo_cc_session_accept_codec(osmo_cc_session_codec_t *codec, void (*encoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len), void (*decoder)(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len)); 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); 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); 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_nettype2string(enum osmo_cc_session_nettype nettype);
@ -126,5 +126,4 @@ const char *osmo_cc_session_addrtype2string(enum osmo_cc_session_addrtype addrty
const char *osmo_cc_session_media_type2string(enum osmo_cc_session_media_type media_type); 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); 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_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);

View File

@ -28,6 +28,7 @@
#include <netdb.h> #include <netdb.h>
#include "../libdebug/debug.h" #include "../libdebug/debug.h"
#include "../libtimer/timer.h" #include "../libtimer/timer.h"
#include "../libselect/select.h"
#include "message.h" #include "message.h"
#include "cause.h" #include "cause.h"
#include "socket.h" #include "socket.h"
@ -54,7 +55,7 @@ static int _getaddrinfo(const char *host, uint16_t port, struct addrinfo **resul
rc = getaddrinfo(host, portstr, &hints, result); rc = getaddrinfo(host, portstr, &hints, result);
if (rc < 0) { if (rc < 0) {
PDEBUG(DCC, DEBUG_ERROR, "Failed to create socket for host '%s', port '%d': %s.\n", host, port, gai_strerror(rc)); LOGP(DCC, LOGL_ERROR, "Failed to create socket for host '%s', port '%d': %s.\n", host, port, gai_strerror(rc));
return rc; return rc;
} }
return rc; return rc;
@ -80,9 +81,9 @@ static void rej_msg(osmo_cc_socket_t *os, uint32_t callref, uint8_t socket_cause
os->recv_msg_cb(os->priv, callref, msg); os->recv_msg_cb(os->priv, callref, msg);
} }
void tx_keepalive_timeout(struct timer *timer) static void tx_keepalive_timeout(void *data)
{ {
osmo_cc_conn_t *conn = (osmo_cc_conn_t *)timer->priv; osmo_cc_conn_t *conn = data;
osmo_cc_msg_t *msg; osmo_cc_msg_t *msg;
/* send keepalive message */ /* send keepalive message */
@ -93,20 +94,22 @@ void tx_keepalive_timeout(struct timer *timer)
static void close_conn(osmo_cc_conn_t *conn, uint8_t socket_cause); static void close_conn(osmo_cc_conn_t *conn, uint8_t socket_cause);
void rx_keepalive_timeout(struct timer *timer) static void rx_keepalive_timeout(void *data)
{ {
osmo_cc_conn_t *conn = (osmo_cc_conn_t *)timer->priv; osmo_cc_conn_t *conn = data;
PDEBUG(DCC, DEBUG_ERROR, "OsmoCC-Socket failed due to timeout.\n"); LOGP(DCC, LOGL_ERROR, "OsmoCC-Socket failed due to timeout.\n");
close_conn(conn, OSMO_CC_SOCKET_CAUSE_TIMEOUT); close_conn(conn, OSMO_CC_SOCKET_CAUSE_TIMEOUT);
} }
static int socket_listen_cb(struct osmo_fd *ofd, unsigned int when);
/* create socket process and bind socket */ /* 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 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; int try = 0, auto_port = 0;
struct addrinfo *result, *rp; struct addrinfo *result, *rp;
int rc, sock, flags; int rc, sock;
memset(os, 0, sizeof(*os)); memset(os, 0, sizeof(*os));
@ -118,7 +121,7 @@ try_again:
auto_port = 1; auto_port = 1;
} }
PDEBUG(DCC, DEBUG_DEBUG, "Create socket for host %s port %d.\n", host, port); LOGP(DCC, LOGL_DEBUG, "Create socket for host %s port %d.\n", host, port);
rc = _getaddrinfo(host, port, &result); rc = _getaddrinfo(host, port, &result);
if (rc < 0) if (rc < 0)
@ -137,26 +140,27 @@ try_again:
freeaddrinfo(result); freeaddrinfo(result);
if (rp == NULL) { if (rp == NULL) {
if (auto_port && port < OSMO_CC_DEFAULT_PORT_MAX) { 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); LOGP(DCC, LOGL_DEBUG, "Failed to bind host %s port %d, trying again.\n", host, port);
goto try_again; goto try_again;
} }
PDEBUG(DCC, DEBUG_ERROR, "Failed to bind given host %s port %d.\n", host, port); LOGP(DCC, LOGL_ERROR, "Failed to bind given host %s port %d.\n", host, port);
return -EIO; return -EIO;
} }
/* listen to socket */ /* listen to socket */
rc = listen(sock, 10); rc = listen(sock, 10);
if (rc < 0) { if (rc < 0) {
PDEBUG(DCC, DEBUG_ERROR, "Failed to listen on socket.\n"); LOGP(DCC, LOGL_ERROR, "Failed to listen on socket.\n");
close(sock);
return rc; return rc;
} }
/* set nonblocking io */ /* register */
flags = fcntl(sock, F_GETFL); os->ofd.fd = sock;
flags |= O_NONBLOCK; os->ofd.cb = socket_listen_cb;
fcntl(sock, F_SETFL, flags); os->ofd.data = os;
os->ofd.when = OSMO_FD_READ;
os->socket = sock; osmo_fd_register(&os->ofd);
os->recv_msg_cb = recv_msg_cb; os->recv_msg_cb = recv_msg_cb;
os->priv = priv; os->priv = priv;
os->location = location; os->location = location;
@ -164,6 +168,8 @@ try_again:
return port; return port;
} }
static int socket_conn_cb(struct osmo_fd *ofd, unsigned int when);
/* create a connection */ /* create a connection */
static osmo_cc_conn_t *open_conn(osmo_cc_socket_t *os, int sock, uint32_t callref, int read_setup) static osmo_cc_conn_t *open_conn(osmo_cc_socket_t *os, int sock, uint32_t callref, int read_setup)
{ {
@ -172,11 +178,15 @@ static osmo_cc_conn_t *open_conn(osmo_cc_socket_t *os, int sock, uint32_t callre
/* create connection */ /* create connection */
conn = calloc(1, sizeof(*conn)); conn = calloc(1, sizeof(*conn));
if (!conn) { if (!conn) {
PDEBUG(DCC, DEBUG_ERROR, "No mem!\n"); LOGP(DCC, LOGL_ERROR, "No mem!\n");
abort(); abort();
} }
conn->os = os; conn->os = os;
conn->socket = sock; conn->ofd.fd = sock;
conn->ofd.cb = socket_conn_cb;
conn->ofd.data = conn;
conn->ofd.when = OSMO_FD_READ;
osmo_fd_register(&conn->ofd);
conn->read_version = 1; conn->read_version = 1;
conn->write_version = 1; conn->write_version = 1;
conn->read_setup = read_setup; conn->read_setup = read_setup;
@ -190,7 +200,7 @@ static osmo_cc_conn_t *open_conn(osmo_cc_socket_t *os, int sock, uint32_t callre
timer_start(&conn->tx_keepalive_timer, OSMO_CC_SOCKET_TX_KEEPALIVE); timer_start(&conn->tx_keepalive_timer, OSMO_CC_SOCKET_TX_KEEPALIVE);
timer_start(&conn->rx_keepalive_timer, OSMO_CC_SOCKET_RX_KEEPALIVE); timer_start(&conn->rx_keepalive_timer, OSMO_CC_SOCKET_RX_KEEPALIVE);
PDEBUG(DCC, DEBUG_DEBUG, "New socket connection (callref %d).\n", conn->callref); LOGP(DCC, LOGL_DEBUG, "New socket connection (callref %d).\n", conn->callref);
/* attach to list */ /* attach to list */
connp = &os->conn_list; connp = &os->conn_list;
@ -218,11 +228,13 @@ static void close_conn(osmo_cc_conn_t *conn, uint8_t socket_cause)
rej_msg(conn->os, conn->callref, socket_cause, 0, 0); rej_msg(conn->os, conn->callref, socket_cause, 0, 0);
} }
PDEBUG(DCC, DEBUG_DEBUG, "Destroy socket connection (callref %d).\n", conn->callref); LOGP(DCC, LOGL_DEBUG, "Destroy socket connection (callref %d).\n", conn->callref);
/* close socket */ /* close socket */
if (conn->socket) if (conn->ofd.fd) {
close(conn->socket); osmo_fd_unregister(&conn->ofd);
close(conn->ofd.fd);
}
/* free partly received message */ /* free partly received message */
if (conn->read_msg) if (conn->read_msg)
osmo_cc_free_msg(conn->read_msg); osmo_cc_free_msg(conn->read_msg);
@ -244,15 +256,16 @@ void osmo_cc_close_socket(osmo_cc_socket_t *os)
{ {
osmo_cc_msg_list_t *ml; osmo_cc_msg_list_t *ml;
PDEBUG(DCC, DEBUG_DEBUG, "Destroy socket.\n"); LOGP(DCC, LOGL_DEBUG, "Destroy socket.\n");
/* free all connections */ /* free all connections */
while (os->conn_list) while (os->conn_list)
close_conn(os->conn_list, 0); close_conn(os->conn_list, 0);
/* close socket */ /* close socket */
if (os->socket > 0) { if (os->ofd.fd > 0) {
close(os->socket); osmo_fd_unregister(&os->ofd);
os->socket = 0; close(os->ofd.fd);
os->ofd.fd = 0;
} }
/* free send queue */ /* free send queue */
while ((ml = os->write_list)) { while ((ml = os->write_list)) {
@ -293,7 +306,7 @@ static int receive_conn(osmo_cc_conn_t *conn)
/* get version from remote */ /* get version from remote */
if (conn->read_version) { if (conn->read_version) {
rc = recv(conn->socket, conn->read_version_string + conn->read_version_pos, strlen(version_string) - conn->read_version_pos, 0); rc = recv(conn->ofd.fd, conn->read_version_string + conn->read_version_pos, strlen(version_string) - conn->read_version_pos, 0);
if (rc < 0 && errno == EAGAIN) if (rc < 0 && errno == EAGAIN)
return work; return work;
work = 1; work = 1;
@ -304,12 +317,12 @@ static int receive_conn(osmo_cc_conn_t *conn)
if (conn->read_version_pos == strlen(version_string)) { if (conn->read_version_pos == strlen(version_string)) {
conn->read_version = 0; conn->read_version = 0;
if (!!memcmp(conn->read_version_string, version_string, strlen(version_string) - 1)) { 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"); LOGP(DCC, LOGL_NOTICE, "Remote does not seem to be an Osmo-CC socket, rejecting!\n");
socket_cause = OSMO_CC_SOCKET_CAUSE_FAILED; socket_cause = OSMO_CC_SOCKET_CAUSE_FAILED;
goto close; goto close;
} }
if (conn->read_version_string[strlen(version_string) - 1] != version_string[strlen(version_string) - 1]) { 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); LOGP(DCC, LOGL_NOTICE, "Remote Osmo-CC socket has wrong version (local=%s, remote=%s), rejecting!\n", version_string, conn->read_version_string);
socket_cause = OSMO_CC_SOCKET_CAUSE_VERSION_MISMATCH; socket_cause = OSMO_CC_SOCKET_CAUSE_VERSION_MISMATCH;
goto close; goto close;
} }
@ -320,7 +333,7 @@ static int receive_conn(osmo_cc_conn_t *conn)
try_next_message: try_next_message:
/* read message header from remote */ /* read message header from remote */
if (!conn->read_msg) { if (!conn->read_msg) {
rc = recv(conn->socket, ((uint8_t *)&conn->read_hdr) + conn->read_pos, sizeof(conn->read_hdr) - conn->read_pos, 0); rc = recv(conn->ofd.fd, ((uint8_t *)&conn->read_hdr) + conn->read_pos, sizeof(conn->read_hdr) - conn->read_pos, 0);
if (rc < 0 && errno == EAGAIN) if (rc < 0 && errno == EAGAIN)
return work; return work;
work = 1; work = 1;
@ -344,7 +357,7 @@ try_next_message:
len = ntohs(msg->length_networkorder); len = ntohs(msg->length_networkorder);
if (len == 0) if (len == 0)
goto empty_message; goto empty_message;
rc = recv(conn->socket, msg->data + conn->read_pos, len - conn->read_pos, 0); rc = recv(conn->ofd.fd, msg->data + conn->read_pos, len - conn->read_pos, 0);
if (rc < 0 && errno == EAGAIN) if (rc < 0 && errno == EAGAIN)
return work; return work;
work = 1; work = 1;
@ -369,7 +382,7 @@ empty_message:
else else
conn->os->recv_msg_cb(conn->os->priv, conn->callref, msg); 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) { 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"); LOGP(DCC, LOGL_DEBUG, "closing socket because we received a release or reject message.\n");
close_conn(conn, 0); close_conn(conn, 0);
return 1; /* conn removed */ return 1; /* conn removed */
} }
@ -378,7 +391,7 @@ empty_message:
return work; return work;
close: close:
PDEBUG(DCC, DEBUG_ERROR, "OsmoCC-Socket failed, socket cause %d.\n", socket_cause); LOGP(DCC, LOGL_ERROR, "OsmoCC-Socket failed, socket cause %d.\n", socket_cause);
close_conn(conn, socket_cause); close_conn(conn, socket_cause);
return work; /* conn removed */ return work; /* conn removed */
} }
@ -397,7 +410,7 @@ static int transmit_conn(osmo_cc_conn_t *conn)
/* send socket version to remote */ /* send socket version to remote */
if (conn->write_version) { if (conn->write_version) {
rc = write(conn->socket, version_string, strlen(version_string)); rc = write(conn->ofd.fd, version_string, strlen(version_string));
if (rc < 0 && errno == EAGAIN) if (rc < 0 && errno == EAGAIN)
return work; return work;
work = 1; work = 1;
@ -405,7 +418,7 @@ static int transmit_conn(osmo_cc_conn_t *conn)
goto close; goto close;
} }
if (rc != strlen(version_string)) { if (rc != strlen(version_string)) {
PDEBUG(DCC, DEBUG_ERROR, "short write, please fix handling!\n"); LOGP(DCC, LOGL_ERROR, "short write, please fix handling!\n");
abort(); abort();
} }
conn->write_version = 0; conn->write_version = 0;
@ -416,7 +429,7 @@ static int transmit_conn(osmo_cc_conn_t *conn)
timer_stop(&conn->tx_keepalive_timer); timer_stop(&conn->tx_keepalive_timer);
msg = conn->write_list->msg; msg = conn->write_list->msg;
len = sizeof(*msg) + ntohs(msg->length_networkorder); len = sizeof(*msg) + ntohs(msg->length_networkorder);
rc = write(conn->socket, msg, len); rc = write(conn->ofd.fd, msg, len);
if (rc < 0 && errno == EAGAIN) if (rc < 0 && errno == EAGAIN)
return work; return work;
work = 1; work = 1;
@ -424,12 +437,12 @@ static int transmit_conn(osmo_cc_conn_t *conn)
goto close; goto close;
} }
if (rc != len) { if (rc != len) {
PDEBUG(DCC, DEBUG_ERROR, "short write, please fix handling!\n"); LOGP(DCC, LOGL_ERROR, "short write, please fix handling!\n");
abort(); abort();
} }
/* close socket after sending release/reject message */ /* close socket after sending release/reject message */
if (msg->type == OSMO_CC_MSG_REL_REQ || msg->type == OSMO_CC_MSG_REJ_REQ) { 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"); LOGP(DCC, LOGL_DEBUG, "closing socket because we sent a release or reject message.\n");
close_conn(conn, 0); close_conn(conn, 0);
return work; /* conn removed */ return work; /* conn removed */
} }
@ -450,7 +463,7 @@ static int transmit_conn(osmo_cc_conn_t *conn)
return work; return work;
close: close:
PDEBUG(DCC, DEBUG_NOTICE, "OsmoCC-Socket failed.\n"); LOGP(DCC, LOGL_NOTICE, "OsmoCC-Socket failed.\n");
close_conn(conn, socket_cause); close_conn(conn, socket_cause);
return work; /* conn removed */ return work; /* conn removed */
} }
@ -460,8 +473,6 @@ close:
*/ */
int osmo_cc_handle_socket(osmo_cc_socket_t *os) int osmo_cc_handle_socket(osmo_cc_socket_t *os)
{ {
struct sockaddr_storage sa;
socklen_t slen = sizeof(sa);
int sock; int sock;
osmo_cc_conn_t *conn; osmo_cc_conn_t *conn;
osmo_cc_msg_list_t *ml, **mlp; osmo_cc_msg_list_t *ml, **mlp;
@ -487,6 +498,7 @@ int osmo_cc_handle_socket(osmo_cc_socket_t *os)
while (*mlp) while (*mlp)
mlp = &((*mlp)->next); mlp = &((*mlp)->next);
*mlp = ml; *mlp = ml;
conn->ofd.when |= OSMO_FD_WRITE;
/* done with message */ /* done with message */
continue; continue;
} }
@ -504,7 +516,7 @@ int osmo_cc_handle_socket(osmo_cc_socket_t *os)
/* reject, if this is not a setup message */ /* reject, if this is not a setup message */
if (ml->msg->type != OSMO_CC_MSG_SETUP_REQ if (ml->msg->type != OSMO_CC_MSG_SETUP_REQ
&& ml->msg->type != OSMO_CC_MSG_ATTACH_REQ) { && ml->msg->type != OSMO_CC_MSG_ATTACH_REQ) {
PDEBUG(DCC, DEBUG_ERROR, "Message with unknown callref.\n"); LOGP(DCC, LOGL_ERROR, "Message with unknown callref.\n");
rej_msg(os, ml->callref, 0, OSMO_CC_ISDN_CAUSE_INVAL_CALLREF, 0); rej_msg(os, ml->callref, 0, OSMO_CC_ISDN_CAUSE_INVAL_CALLREF, 0);
/* drop message */ /* drop message */
osmo_cc_free_msg(ml->msg); osmo_cc_free_msg(ml->msg);
@ -526,7 +538,7 @@ int osmo_cc_handle_socket(osmo_cc_socket_t *os)
sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sock < 0) if (sock < 0)
continue; continue;
/* set nonblocking io */ /* set nonblocking io, to prevent connect() and subsequent reads from blocking */
flags = fcntl(sock, F_GETFL); flags = fcntl(sock, F_GETFL);
flags |= O_NONBLOCK; flags |= O_NONBLOCK;
fcntl(sock, F_SETFL, flags); fcntl(sock, F_SETFL, flags);
@ -538,7 +550,7 @@ int osmo_cc_handle_socket(osmo_cc_socket_t *os)
} }
freeaddrinfo(result); freeaddrinfo(result);
if (rp == NULL) { if (rp == NULL) {
PDEBUG(DCC, DEBUG_ERROR, "Failed to connect to given host %s port %d.\n", ml->host, ml->port); LOGP(DCC, LOGL_ERROR, "Failed to connect to given host %s port %d.\n", ml->host, ml->port);
rej_msg(os, ml->callref, OSMO_CC_SOCKET_CAUSE_FAILED, 0, 0); rej_msg(os, ml->callref, OSMO_CC_SOCKET_CAUSE_FAILED, 0, 0);
/* drop message */ /* drop message */
osmo_cc_free_msg(ml->msg); osmo_cc_free_msg(ml->msg);
@ -550,34 +562,58 @@ int osmo_cc_handle_socket(osmo_cc_socket_t *os)
conn = open_conn(os, sock, ml->callref, 0); conn = open_conn(os, sock, ml->callref, 0);
/* attach to list */ /* attach to list */
conn->write_list = ml; conn->write_list = ml;
conn->ofd.when |= OSMO_FD_WRITE;
/* done with (setup) message */ /* 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; return work;
} }
static int socket_listen_cb(struct osmo_fd *ofd, unsigned int when)
{
osmo_cc_socket_t *os = ofd->data;
struct sockaddr_storage sa;
socklen_t slen = sizeof(sa);
int sock;
int flags;
if (when & OSMO_FD_READ) {
/* handle new socket connection */
if ((sock = accept(os->ofd.fd, (struct sockaddr *)&sa, &slen)) > 0) {
/* set nonblocking io, to prevent subsequent reads from blocking */
flags = fcntl(sock, F_GETFL);
flags |= O_NONBLOCK;
fcntl(sock, F_SETFL, flags);
/* create connection */
open_conn(os, sock, 0, 1);
}
}
return 0;
}
static int socket_conn_cb(struct osmo_fd *ofd, unsigned int when)
{
osmo_cc_conn_t *conn = ofd->data;
int work;
if (when & OSMO_FD_READ) {
/* check for rx */
work = receive_conn(conn);
/* if "change" is set, connection list might have changed, so we restart processing the list */
if (work)
return 0;
}
if (when & OSMO_FD_WRITE) {
/* check for tx */
work = transmit_conn(conn);
/* if "change" is set, connection list might have changed, so we restart processing the list */
if (work)
return 0;
else
conn->ofd.when &= ~OSMO_FD_WRITE;
}
return 0;
}

View File

@ -12,7 +12,7 @@ struct osmo_cc_socket;
typedef struct osmo_cc_conn { typedef struct osmo_cc_conn {
struct osmo_cc_conn *next; struct osmo_cc_conn *next;
struct osmo_cc_socket *os; struct osmo_cc_socket *os;
int socket; struct osmo_fd ofd;
uint32_t callref; uint32_t callref;
int read_setup; int read_setup;
int read_version; int read_version;
@ -28,7 +28,7 @@ typedef struct osmo_cc_conn {
} osmo_cc_conn_t; } osmo_cc_conn_t;
typedef struct osmo_cc_socket { typedef struct osmo_cc_socket {
int socket; struct osmo_fd ofd;
osmo_cc_conn_t *conn_list; osmo_cc_conn_t *conn_list;
osmo_cc_msg_list_t *write_list; osmo_cc_msg_list_t *write_list;
void (*recv_msg_cb)(void *priv, uint32_t callref, osmo_cc_msg_t *msg); void (*recv_msg_cb)(void *priv, uint32_t callref, osmo_cc_msg_t *msg);

View File

@ -34,8 +34,11 @@ int init_samplerate(samplerate_t *state, double low_samplerate, double high_samp
abort(); abort();
} }
iir_lowpass_init(&state->up.lp, filter_cutoff, high_samplerate, 2); state->filter_cutoff = filter_cutoff;
iir_lowpass_init(&state->down.lp, filter_cutoff, high_samplerate, 2); if (state->filter_cutoff) {
iir_lowpass_init(&state->up.lp, filter_cutoff, high_samplerate, 2);
iir_lowpass_init(&state->down.lp, filter_cutoff, high_samplerate, 2);
}
return 0; return 0;
} }
@ -49,7 +52,8 @@ int samplerate_downsample(samplerate_t *state, sample_t *samples, int input_num)
sample_t last_sample; sample_t last_sample;
/* filter down */ /* filter down */
iir_process(&state->down.lp, samples, input_num); if (state->filter_cutoff)
iir_process(&state->down.lp, samples, input_num);
/* get last sample for interpolation */ /* get last sample for interpolation */
last_sample = state->down.last_sample; last_sample = state->down.last_sample;
@ -185,7 +189,8 @@ void samplerate_upsample(samplerate_t *state, sample_t *input, int input_num, sa
state->up.in_index = in_index; state->up.in_index = in_index;
/* filter up */ /* filter up */
iir_process(&state->up.lp, samples, output_num); if (state->filter_cutoff)
iir_process(&state->up.lp, samples, output_num);
if (input == output) { if (input == output) {
/* copy samples */ /* copy samples */

View File

@ -2,6 +2,7 @@
typedef struct samplerate { typedef struct samplerate {
double factor; double factor;
double filter_cutoff;
struct { struct {
iir_filter_t lp; iir_filter_t lp;
sample_t last_sample; sample_t last_sample;

View File

@ -26,6 +26,8 @@
#include <errno.h> #include <errno.h>
#include "timer.h" #include "timer.h"
//#define DEBUG
static struct timer *timer_head = NULL; static struct timer *timer_head = NULL;
static struct timer **timer_tail_p = &timer_head; static struct timer **timer_tail_p = &timer_head;
@ -38,7 +40,7 @@ double get_time(void)
return (double)tv.tv_sec + (double)tv.tv_nsec / 1000000000.0; return (double)tv.tv_sec + (double)tv.tv_nsec / 1000000000.0;
} }
void timer_init(struct timer *timer, void (*fn)(struct timer *timer), void *priv) void timer_init(struct timer *timer, void (*fn)(void *data), void *priv)
{ {
if (timer->linked) { if (timer->linked) {
fprintf(stderr, "Timer is already initialized, aborting!\n"); fprintf(stderr, "Timer is already initialized, aborting!\n");
@ -46,12 +48,15 @@ void timer_init(struct timer *timer, void (*fn)(struct timer *timer), void *priv
} }
timer->timeout = 0; timer->timeout = 0;
timer->fn = fn; timer->cb = fn;
timer->priv = priv; timer->data = priv;
timer->next = NULL; timer->next = NULL;
*timer_tail_p = timer; *timer_tail_p = timer;
timer_tail_p = &timer->next; timer_tail_p = &timer->next;
timer->linked = 1; timer->linked = 1;
#ifdef DEBUG
fprintf(stderr, "%s: timer=%p linked.\n", __func__, timer);
#endif
} }
void timer_exit(struct timer *timer) void timer_exit(struct timer *timer)
@ -64,6 +69,9 @@ void timer_exit(struct timer *timer)
timer_tail_p = &((*timer_tail_p)->next); timer_tail_p = &((*timer_tail_p)->next);
} }
timer->linked = 0; timer->linked = 0;
#ifdef DEBUG
fprintf(stderr, "%s: timer=%p unlinked.\n", __func__, timer);
#endif
} }
void timer_start(struct timer *timer, double duration) void timer_start(struct timer *timer, double duration)
@ -75,6 +83,9 @@ void timer_start(struct timer *timer, double duration)
timer->duration = duration; timer->duration = duration;
timer->timeout = get_time() + duration; timer->timeout = get_time() + duration;
#ifdef DEBUG
fprintf(stderr, "%s: timer=%p started %.3f seconds.\n", __func__, timer, duration);
#endif
} }
void timer_stop(struct timer *timer) void timer_stop(struct timer *timer)
@ -85,6 +96,9 @@ void timer_stop(struct timer *timer)
} }
timer->timeout = 0; timer->timeout = 0;
#ifdef DEBUG
fprintf(stderr, "%s: timer=%p stopped.\n", __func__, timer);
#endif
} }
int timer_running(struct timer *timer) int timer_running(struct timer *timer)
@ -97,23 +111,55 @@ int timer_running(struct timer *timer)
return (timer->timeout != 0); return (timer->timeout != 0);
} }
void process_timer(void) double process_timer(void)
{ {
struct timer *timer; struct timer *timer;
double now; double now, timeout = -1.0;
now = get_time(); now = get_time();
again: again:
timer = timer_head; timer = timer_head;
while (timer) { while (timer) {
if (timer->linked && timer->timeout > 0 && now >= timer->timeout) { if (timer->linked && timer->timeout > 0) {
timer->timeout = 0; /* timeout, handle it, set timeout to 0 */
timer->fn(timer); if (now >= timer->timeout) {
goto again; timer->timeout = 0;
#ifdef DEBUG
fprintf(stderr, "%s: timer=%p fired.\n", __func__, timer);
#endif
if (!timer->cb)
abort();
timer->cb(timer->data);
timeout = 0.0;
goto again;
}
/* in the future, set timeout to future */
if (timeout < 0.0 || (timer->timeout - now) < timeout)
timeout = timer->timeout - now;
} }
timer = timer->next; timer = timer->next;
} }
return timeout;
}
void osmo_timer_schedule(struct osmo_timer_list *ti, time_t sec, suseconds_t usec)
{
if (!ti->linked)
timer_init(ti, ti->cb, ti->data);
timer_start(ti, (double)sec + (double)usec / 1000000.0);
}
void osmo_timer_del(struct osmo_timer_list *ti)
{
timer_exit(ti);
}
int osmo_timer_pending(struct osmo_timer_list *ti)
{
if (!ti->linked)
return 0;
return (ti->timeout != 0);
} }

View File

@ -4,15 +4,20 @@ struct timer {
int linked; /* set is timer is initialized and linked */ int linked; /* set is timer is initialized and linked */
double duration; double duration;
double timeout; double timeout;
void (*fn)(struct timer *timer); void (*cb)(void *data);
void *priv; void *data;
}; };
double get_time(void); double get_time(void);
void timer_init(struct timer *timer, void (*fn)(struct timer *timer), void *priv); void timer_init(struct timer *timer, void (*fn)(void *data), void *priv);
void timer_exit(struct timer *timer); void timer_exit(struct timer *timer);
void timer_start(struct timer *timer, double duration); void timer_start(struct timer *timer, double duration);
void timer_stop(struct timer *timer); void timer_stop(struct timer *timer);
int timer_running(struct timer *timer); int timer_running(struct timer *timer);
void process_timer(void); double process_timer(void);
#define osmo_timer_list timer
void osmo_timer_schedule(struct osmo_timer_list *ti, time_t sec, long usec);
void osmo_timer_del(struct osmo_timer_list *ti);
int osmo_timer_pending(struct osmo_timer_list *ti);

View File

@ -351,7 +351,7 @@ void alsa_work(telephone_t *telephone_ep)
if (call->cc_callref && call->codec) { if (call->cc_callref && call->codec) {
int16_t data[160]; int16_t data[160];
samples_to_int16_speech(data, call->tx_buffer, 160); samples_to_int16_speech(data, call->tx_buffer, 160);
osmo_cc_rtp_send(call->codec, (uint8_t *)data, 160 * 2, 0, 1, 160); osmo_cc_rtp_send(call->codec, (uint8_t *)data, 160 * 2, 0, 1, 160, call);
} }
} }
} }
@ -370,7 +370,7 @@ void rtp_work(telephone_t *telephone_ep)
call = telephone_ep->call_list; call = telephone_ep->call_list;
while (call) { while (call) {
if (call->cc_session) if (call->cc_session)
osmo_cc_session_handle(call->cc_session); osmo_cc_session_handle(call->cc_session, call);
call = call->next; call = call->next;
} }
} }