Updated libs
This commit is contained in:
parent
6a812616a4
commit
4027c98c53
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
@ -666,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);
|
||||||
|
@ -687,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);
|
||||||
|
@ -725,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);
|
||||||
|
@ -741,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);
|
||||||
|
@ -770,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 */
|
||||||
|
@ -797,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 */
|
||||||
|
@ -954,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1040,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;
|
||||||
}
|
}
|
||||||
|
@ -1063,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;
|
||||||
}
|
}
|
||||||
|
@ -1124,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1187,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;
|
||||||
}
|
}
|
||||||
|
@ -1201,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1226,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);
|
||||||
|
@ -1260,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1275,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);
|
||||||
|
@ -1288,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';
|
||||||
|
@ -1305,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';
|
||||||
|
@ -1334,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1391,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1407,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) {
|
||||||
|
@ -1429,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);
|
||||||
|
@ -1447,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1459,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;
|
||||||
|
@ -1535,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,7 +124,7 @@ 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;
|
*session_p = NULL;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -153,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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -374,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 */
|
||||||
|
@ -453,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) {
|
||||||
|
@ -468,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], ¬ify);
|
rc = osmo_cc_get_ie_notify(msg, ie_repeat[ie->type], ¬ify);
|
||||||
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));
|
||||||
|
@ -582,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;
|
||||||
|
@ -625,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 */
|
||||||
|
@ -652,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;
|
||||||
|
@ -728,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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
@ -326,7 +354,7 @@ void osmo_cc_rtp_send(osmo_cc_session_codec_t *codec, uint8_t *data, int len, ui
|
||||||
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)
|
||||||
|
@ -336,7 +364,7 @@ void osmo_cc_rtp_send(osmo_cc_session_codec_t *codec, uint8_t *data, int len, ui
|
||||||
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, void *priv)
|
|
||||||
{
|
{
|
||||||
|
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, void *priv)
|
||||||
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, priv);
|
}
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,5 @@ void osmo_cc_set_rtp_ports(osmo_cc_session_config_t *conf, uint16_t from, uint16
|
||||||
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 *priv);
|
void osmo_cc_rtp_send(osmo_cc_session_codec_t *codec, uint8_t *data, int len, uint8_t marker, int inc_sequence, int inc_timestamp, void *priv);
|
||||||
int osmo_cc_rtp_receive(osmo_cc_session_media_t *media, void *priv);
|
|
||||||
void osmo_cc_rtp_close(osmo_cc_session_media_t *media);
|
void osmo_cc_rtp_close(osmo_cc_session_media_t *media);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
@ -204,7 +205,7 @@ osmo_cc_session_codec_t *osmo_cc_add_codec(osmo_cc_session_media_t *media, const
|
||||||
|
|
||||||
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,10 +397,10 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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, void *codec_priv)
|
|
||||||
{
|
|
||||||
osmo_cc_session_media_t *media;
|
|
||||||
int w = 0, rc;
|
|
||||||
|
|
||||||
osmo_cc_session_for_each_media(session->media_list, media) {
|
|
||||||
do {
|
|
||||||
rc = osmo_cc_rtp_receive(media, codec_priv);
|
|
||||||
if (rc >= 0)
|
|
||||||
w = 1;
|
|
||||||
} while (rc >= 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return w;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -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, void *codec_priv);
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -26,55 +26,58 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <time.h>
|
#include "../libtimer/timer.h"
|
||||||
|
#include "../libselect/select.h"
|
||||||
#include "../libdebug/debug.h"
|
#include "../libdebug/debug.h"
|
||||||
#include "ph_socket.h"
|
#include "ph_socket.h"
|
||||||
|
|
||||||
#define CHAN s->name
|
static int ph_socket_listen_cb(struct osmo_fd *ofd, unsigned int __attribute__((unused)) what);
|
||||||
|
static int ph_socket_connect_cb(struct osmo_fd *ofd, unsigned int __attribute__((unused)) what);
|
||||||
|
static void ph_socket_timeout_cb(void *data);
|
||||||
|
|
||||||
int ph_socket_init(ph_socket_t *s, void (*ph_socket_rx_msg)(ph_socket_t *s, int channel, uint8_t prim, uint8_t *data, int length), void *priv, const char *socket_name, int server)
|
static void open_connection(ph_socket_t *s)
|
||||||
{
|
{
|
||||||
|
uint8_t enable = PH_CTRL_UNBLOCK;
|
||||||
int rc, flags;
|
int rc, flags;
|
||||||
|
|
||||||
memset(s, 0, sizeof(*s));
|
if (s->connect_ofd.fd > 0)
|
||||||
s->name = socket_name;
|
return;
|
||||||
s->ph_socket_rx_msg = ph_socket_rx_msg;
|
|
||||||
s->priv = priv;
|
|
||||||
s->tx_list_tail = &s->tx_list;
|
|
||||||
|
|
||||||
memset(&s->sock_address, 0, sizeof(s->sock_address));
|
LOGP(DPH, LOGL_DEBUG, "Trying to connect to PH-socket server.\n");
|
||||||
s->sock_address.sun_family = AF_UNIX;
|
rc = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||||
strcpy(s->sock_address.sun_path+1, socket_name);
|
if (rc < 0) {
|
||||||
|
LOGP(DPH, LOGL_ERROR, "Failed to create UNIX socket.\n");
|
||||||
if (server) {
|
osmo_timer_schedule(&s->retry_timer, SOCKET_RETRY_TIMER, 0);
|
||||||
rc = socket(PF_UNIX, SOCK_STREAM, 0);
|
return;
|
||||||
if (rc < 0) {
|
|
||||||
PDEBUG_CHAN(DPH, DEBUG_ERROR, "Failed to create UNIX socket.\n");
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
s->listen = rc;
|
|
||||||
|
|
||||||
rc = bind(s->listen, (struct sockaddr *)(&s->sock_address), sizeof(s->sock_address));
|
|
||||||
if (rc < 0) {
|
|
||||||
PDEBUG_CHAN(DPH, DEBUG_ERROR, "Failed to bind UNIX socket with path '%s' (errno = %d (%s)).\n", s->name, errno, strerror(errno));
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = listen(s->listen, 1);
|
|
||||||
if (rc < 0) {
|
|
||||||
PDEBUG_CHAN(DPH, DEBUG_ERROR, "Failed to listen to UNIX socket with path '%s' (errno = %d (%s)).\n", s->name, errno, strerror(errno));
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set nonblocking io */
|
|
||||||
flags = fcntl(s->listen, F_GETFL);
|
|
||||||
flags |= O_NONBLOCK;
|
|
||||||
fcntl(s->listen, F_SETFL, flags);
|
|
||||||
}
|
}
|
||||||
|
s->connect_ofd.fd = rc;
|
||||||
PDEBUG_CHAN(DPH, DEBUG_INFO, "Created PH-socket at '%s'.\n", s->name);
|
s->connect_ofd.data = s;
|
||||||
|
s->connect_ofd.when = BSC_FD_READ;
|
||||||
return 0;
|
s->connect_ofd.cb = ph_socket_connect_cb;
|
||||||
|
osmo_fd_register(&s->connect_ofd);
|
||||||
|
/* set nonblocking io, because we do multiple reads when handling read event */
|
||||||
|
flags = fcntl(s->connect_ofd.fd, F_GETFL);
|
||||||
|
flags |= O_NONBLOCK;
|
||||||
|
fcntl(s->connect_ofd.fd, F_SETFL, flags);
|
||||||
|
/* connect */
|
||||||
|
rc = connect(s->connect_ofd.fd, (struct sockaddr *)&s->sock_address, sizeof(s->sock_address));
|
||||||
|
if (rc < 0 && errno != EAGAIN) {
|
||||||
|
if (!s->connect_failed)
|
||||||
|
LOGP(DPH, LOGL_NOTICE, "Failed to connect UNIX socket, retrying...\n");
|
||||||
|
close(s->connect_ofd.fd);
|
||||||
|
s->connect_failed = 1;
|
||||||
|
osmo_fd_unregister(&s->connect_ofd);
|
||||||
|
s->connect_ofd.fd = 0;
|
||||||
|
osmo_timer_schedule(&s->retry_timer, SOCKET_RETRY_TIMER, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
s->connect_failed = 0;
|
||||||
|
LOGP(DPH, LOGL_INFO, "Connection to PH-socket server.\n");
|
||||||
|
/* reset rx buffer */
|
||||||
|
s->rx_header_index = 0;
|
||||||
|
s->rx_data_index = 0;
|
||||||
|
/* indicate established socket connection */
|
||||||
|
s->ph_socket_rx_msg(s, 0, PH_PRIM_CTRL_IND, &enable, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void close_connection(ph_socket_t *s)
|
static void close_connection(ph_socket_t *s)
|
||||||
|
@ -82,16 +85,17 @@ static void close_connection(ph_socket_t *s)
|
||||||
struct socket_msg_list *ml;
|
struct socket_msg_list *ml;
|
||||||
uint8_t disable = PH_CTRL_BLOCK;
|
uint8_t disable = PH_CTRL_BLOCK;
|
||||||
|
|
||||||
if (s->connect <= 0)
|
if (s->connect_ofd.fd <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PDEBUG_CHAN(DPH, DEBUG_INFO, "Connection from PH-socket closed.\n");
|
LOGP(DPH, LOGL_INFO, "Connection from PH-socket closed.\n");
|
||||||
|
|
||||||
/* indicate loss of socket connection */
|
/* indicate loss of socket connection */
|
||||||
s->ph_socket_rx_msg(s, 0, (s->listen > 0) ? PH_PRIM_CTRL_REQ : PH_PRIM_CTRL_IND, &disable, 1);
|
s->ph_socket_rx_msg(s, 0, (s->listen_ofd.fd > 0) ? PH_PRIM_CTRL_REQ : PH_PRIM_CTRL_IND, &disable, 1);
|
||||||
|
|
||||||
close(s->connect);
|
osmo_fd_unregister(&s->connect_ofd);
|
||||||
s->connect = 0;
|
close(s->connect_ofd.fd);
|
||||||
|
s->connect_ofd.fd = 0;
|
||||||
|
|
||||||
while ((ml = s->tx_list)) {
|
while ((ml = s->tx_list)) {
|
||||||
s->tx_list = ml->next;
|
s->tx_list = ml->next;
|
||||||
|
@ -103,147 +107,176 @@ static void close_connection(ph_socket_t *s)
|
||||||
s->rx_msg = NULL;
|
s->rx_msg = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set timer, so that retry is delayed */
|
if (s->listen_ofd.fd <= 0) {
|
||||||
static struct timespec tv;
|
/* set timer, so that retry is delayed */
|
||||||
clock_gettime(CLOCK_REALTIME, &tv);
|
osmo_timer_schedule(&s->retry_timer, SOCKET_RETRY_TIMER, 0);
|
||||||
double now = (double)tv.tv_sec + (double)tv.tv_nsec / 1000000000.0;
|
}
|
||||||
s->connect_timer = now + SOCKET_RETRY_TIMER;
|
}
|
||||||
|
|
||||||
|
int ph_socket_init(ph_socket_t *s, void (*ph_socket_rx_msg)(ph_socket_t *s, int channel, uint8_t prim, uint8_t *data,
|
||||||
|
int length), void *priv, const char *socket_name, int server)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
memset(s, 0, sizeof(*s));
|
||||||
|
s->name = socket_name;
|
||||||
|
s->ph_socket_rx_msg = ph_socket_rx_msg;
|
||||||
|
s->priv = priv;
|
||||||
|
s->tx_list_tail = &s->tx_list;
|
||||||
|
|
||||||
|
memset(&s->sock_address, 0, sizeof(s->sock_address));
|
||||||
|
s->sock_address.sun_family = AF_UNIX;
|
||||||
|
strcpy(s->sock_address.sun_path+1, socket_name);
|
||||||
|
|
||||||
|
s->retry_timer.data = s;
|
||||||
|
s->retry_timer.cb = ph_socket_timeout_cb;
|
||||||
|
|
||||||
|
if (server) {
|
||||||
|
rc = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (rc < 0) {
|
||||||
|
LOGP(DPH, LOGL_ERROR, "Failed to create UNIX socket.\n");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
s->listen_ofd.fd = rc;
|
||||||
|
s->listen_ofd.data = s;
|
||||||
|
s->listen_ofd.when = BSC_FD_READ;
|
||||||
|
s->listen_ofd.cb = ph_socket_listen_cb;
|
||||||
|
osmo_fd_register(&s->listen_ofd);
|
||||||
|
|
||||||
|
rc = bind(s->listen_ofd.fd, (struct sockaddr *)(&s->sock_address), sizeof(s->sock_address));
|
||||||
|
if (rc < 0) {
|
||||||
|
LOGP(DPH, LOGL_ERROR, "Failed to bind UNIX socket with path '%s' (errno = %d (%s)).\n",
|
||||||
|
s->name, errno, strerror(errno));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = listen(s->listen_ofd.fd, 1);
|
||||||
|
if (rc < 0) {
|
||||||
|
LOGP(DPH, LOGL_ERROR, "Failed to listen to UNIX socket with path '%s' (errno = %d (%s)).\n",
|
||||||
|
s->name, errno, strerror(errno));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
open_connection(s);
|
||||||
|
|
||||||
|
LOGP(DPH, LOGL_INFO, "Created PH-socket at '%s'.\n", s->name);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ph_socket_exit(ph_socket_t *s)
|
void ph_socket_exit(ph_socket_t *s)
|
||||||
{
|
{
|
||||||
PDEBUG_CHAN(DPH, DEBUG_INFO, "Destroyed PH-socket.\n");
|
LOGP(DPH, LOGL_INFO, "Destroyed PH-socket.\n");
|
||||||
|
|
||||||
close_connection(s);
|
close_connection(s);
|
||||||
if (s->listen > 0) {
|
if (s->listen_ofd.fd > 0) {
|
||||||
close(s->listen);
|
osmo_fd_unregister(&s->listen_ofd);
|
||||||
s->listen = 0;
|
close(s->listen_ofd.fd);
|
||||||
|
s->listen_ofd.fd = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (osmo_timer_pending(&s->retry_timer))
|
||||||
|
osmo_timer_del(&s->retry_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ph_socket_work(ph_socket_t *s)
|
static int ph_socket_listen_cb(struct osmo_fd *ofd, unsigned int __attribute__((unused)) what)
|
||||||
{
|
{
|
||||||
|
ph_socket_t *s = ofd->data;
|
||||||
|
struct sockaddr_un sock_address;
|
||||||
uint8_t enable = PH_CTRL_UNBLOCK;
|
uint8_t enable = PH_CTRL_UNBLOCK;
|
||||||
int rc, flags;
|
int rc, flags;
|
||||||
int work = 0;
|
|
||||||
|
|
||||||
if (s->listen > 0) {
|
socklen_t sock_len = sizeof(sock_address);
|
||||||
struct sockaddr_un sock_address;
|
/* see if there is an incoming connection */
|
||||||
socklen_t sock_len = sizeof(sock_address);
|
rc = accept(s->listen_ofd.fd, (struct sockaddr *)&sock_address, &sock_len);
|
||||||
/* see if there is an incoming connection */
|
if (rc > 0) {
|
||||||
rc = accept(s->listen, (struct sockaddr *)&sock_address, &sock_len);
|
if (s->connect_ofd.fd > 0) {
|
||||||
if (rc > 0) {
|
LOGP(DPH, LOGL_ERROR, "Rejecting incoming connection, because we already have a client "
|
||||||
if (s->connect > 0) {
|
"connected!\n");
|
||||||
PDEBUG_CHAN(DPH, DEBUG_ERROR, "Rejecting incoming connection, because we already have a client connected!\n");
|
close(rc);
|
||||||
close(rc);
|
} else {
|
||||||
} else {
|
LOGP(DPH, LOGL_INFO, "Connection from PH-socket client.\n");
|
||||||
PDEBUG_CHAN(DPH, DEBUG_INFO, "Connection from PH-socket client.\n");
|
s->connect_ofd.fd = rc;
|
||||||
s->connect = rc;
|
s->connect_ofd.data = s;
|
||||||
/* set nonblocking io */
|
s->connect_ofd.when = BSC_FD_READ;
|
||||||
flags = fcntl(s->connect, F_GETFL);
|
s->connect_ofd.cb = ph_socket_connect_cb;
|
||||||
flags |= O_NONBLOCK;
|
osmo_fd_register(&s->connect_ofd);
|
||||||
fcntl(s->connect, F_SETFL, flags);
|
/* set nonblocking io, because we do multiple reads when handling read event */
|
||||||
/* reset rx buffer */
|
flags = fcntl(s->connect_ofd.fd, F_GETFL);
|
||||||
s->rx_header_index = 0;
|
flags |= O_NONBLOCK;
|
||||||
s->rx_data_index = 0;
|
fcntl(s->connect_ofd.fd, F_SETFL, flags);
|
||||||
/* indicate established socket connection */
|
/* reset rx buffer */
|
||||||
s->ph_socket_rx_msg(s, 0, PH_PRIM_CTRL_REQ, &enable, 1);
|
s->rx_header_index = 0;
|
||||||
}
|
s->rx_data_index = 0;
|
||||||
work = 1;
|
/* indicate established socket connection */
|
||||||
}
|
s->ph_socket_rx_msg(s, 0, PH_PRIM_CTRL_REQ, &enable, 1);
|
||||||
} else {
|
|
||||||
/* open connection, if closed */
|
|
||||||
if (s->connect <= 0) {
|
|
||||||
static struct timespec tv;
|
|
||||||
clock_gettime(CLOCK_REALTIME, &tv);
|
|
||||||
double now = (double)tv.tv_sec + (double)tv.tv_nsec / 1000000000.0;
|
|
||||||
if (s->connect_timer < now) {
|
|
||||||
PDEBUG_CHAN(DPH, DEBUG_DEBUG, "Trying to connect to PH-socket server.\n");
|
|
||||||
rc = socket(PF_UNIX, SOCK_STREAM, 0);
|
|
||||||
if (rc < 0) {
|
|
||||||
PDEBUG_CHAN(DPH, DEBUG_ERROR, "Failed to create UNIX socket.\n");
|
|
||||||
s->connect_timer = now + SOCKET_RETRY_TIMER;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
s->connect = rc;
|
|
||||||
/* connect */
|
|
||||||
rc = connect(s->connect, (struct sockaddr *)&s->sock_address, sizeof(s->sock_address));
|
|
||||||
if (rc < 0 && errno != EAGAIN) {
|
|
||||||
if (!s->connect_failed)
|
|
||||||
PDEBUG_CHAN(DPH, DEBUG_NOTICE, "Failed to connect UNIX socket, retrying...\n");
|
|
||||||
close(s->connect);
|
|
||||||
s->connect_failed = 1;
|
|
||||||
s->connect = 0;
|
|
||||||
s->connect_timer = now + SOCKET_RETRY_TIMER;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
s->connect_failed = 0;
|
|
||||||
PDEBUG_CHAN(DPH, DEBUG_INFO, "Connection to PH-socket server.\n");
|
|
||||||
/* set nonblocking io */
|
|
||||||
flags = fcntl(s->connect, F_GETFL);
|
|
||||||
flags |= O_NONBLOCK;
|
|
||||||
fcntl(s->connect, F_SETFL, flags);
|
|
||||||
/* reset rx buffer */
|
|
||||||
s->rx_header_index = 0;
|
|
||||||
s->rx_data_index = 0;
|
|
||||||
/* indicate established socket connection */
|
|
||||||
s->ph_socket_rx_msg(s, 0, PH_PRIM_CTRL_IND, &enable, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle connection, if any */
|
return 0;
|
||||||
if (s->connect > 0) {
|
}
|
||||||
|
|
||||||
|
static int ph_socket_connect_cb(struct osmo_fd *ofd, unsigned __attribute__((unused)) int what)
|
||||||
|
{
|
||||||
|
ph_socket_t *s = ofd->data;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (what & BSC_FD_READ) {
|
||||||
|
rx_again:
|
||||||
if (!s->rx_msg)
|
if (!s->rx_msg)
|
||||||
s->rx_msg = calloc(1, sizeof(*s->rx_msg));
|
s->rx_msg = calloc(1, sizeof(*s->rx_msg));
|
||||||
rx_again:
|
|
||||||
if (s->rx_header_index < (int)sizeof(s->rx_msg->msg.header)) {
|
if (s->rx_header_index < (int)sizeof(s->rx_msg->msg.header)) {
|
||||||
/* read header until complete */
|
/* read header until complete */
|
||||||
rc = recv(s->connect, ((uint8_t *)&s->rx_msg->msg.header) + s->rx_header_index, sizeof(s->rx_msg->msg.header) - s->rx_header_index, 0);
|
rc = recv(s->connect_ofd.fd, ((uint8_t *)&s->rx_msg->msg.header) + s->rx_header_index,
|
||||||
|
sizeof(s->rx_msg->msg.header) - s->rx_header_index, 0);
|
||||||
if (rc > 0) {
|
if (rc > 0) {
|
||||||
s->rx_header_index += rc;
|
s->rx_header_index += rc;
|
||||||
work = 1;
|
|
||||||
goto rx_again;
|
goto rx_again;
|
||||||
} else if (rc == 0 || errno != EAGAIN) {
|
} else if (rc == 0 || errno != EAGAIN) {
|
||||||
close_connection(s);
|
close_connection(s);
|
||||||
work = 1;
|
return 0;
|
||||||
}
|
}
|
||||||
} else if (s->rx_data_index < s->rx_msg->msg.header.length) {
|
} else if (s->rx_data_index < s->rx_msg->msg.header.length) {
|
||||||
/* read data until complete */
|
/* read data until complete */
|
||||||
rc = recv(s->connect, s->rx_msg->msg.data + s->rx_data_index, s->rx_msg->msg.header.length - s->rx_data_index, 0);
|
rc = recv(s->connect_ofd.fd, s->rx_msg->msg.data + s->rx_data_index,
|
||||||
|
s->rx_msg->msg.header.length - s->rx_data_index, 0);
|
||||||
if (rc > 0) {
|
if (rc > 0) {
|
||||||
s->rx_data_index += rc;
|
s->rx_data_index += rc;
|
||||||
work = 1;
|
|
||||||
goto rx_again;
|
goto rx_again;
|
||||||
} else if (rc == 0 || errno != EAGAIN) {
|
} else if (rc == 0 || errno != EAGAIN) {
|
||||||
close_connection(s);
|
close_connection(s);
|
||||||
work = 1;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* process and free message */
|
/* process and free message */
|
||||||
if (s->rx_msg->msg.header.prim != PH_PRIM_DATA_REQ
|
if (s->rx_msg->msg.header.prim != PH_PRIM_DATA_REQ
|
||||||
&& s->rx_msg->msg.header.prim != PH_PRIM_DATA_IND
|
&& s->rx_msg->msg.header.prim != PH_PRIM_DATA_IND
|
||||||
&& s->rx_msg->msg.header.prim != PH_PRIM_DATA_CNF) {
|
&& s->rx_msg->msg.header.prim != PH_PRIM_DATA_CNF) {
|
||||||
PDEBUG_CHAN(DPH, DEBUG_DEBUG, "message 0x%02x channel %d from socket\n", s->rx_msg->msg.header.prim, s->rx_msg->msg.header.channel);
|
LOGP(DPH, LOGL_DEBUG, "message 0x%02x channel %d from socket\n",
|
||||||
|
s->rx_msg->msg.header.prim, s->rx_msg->msg.header.channel);
|
||||||
if (s->rx_msg->msg.header.length)
|
if (s->rx_msg->msg.header.length)
|
||||||
PDEBUG_CHAN(DPH, DEBUG_DEBUG, " -> data:%s\n", debug_hex(s->rx_msg->msg.data, s->rx_msg->msg.header.length));
|
LOGP(DPH, LOGL_DEBUG, " -> data:%s\n", osmo_hexdump(s->rx_msg->msg.data,
|
||||||
|
s->rx_msg->msg.header.length));
|
||||||
}
|
}
|
||||||
s->ph_socket_rx_msg(s, s->rx_msg->msg.header.channel, s->rx_msg->msg.header.prim, s->rx_msg->msg.data, s->rx_msg->msg.header.length);
|
s->ph_socket_rx_msg(s, s->rx_msg->msg.header.channel, s->rx_msg->msg.header.prim,
|
||||||
|
s->rx_msg->msg.data, s->rx_msg->msg.header.length);
|
||||||
free(s->rx_msg);
|
free(s->rx_msg);
|
||||||
s->rx_msg = NULL;
|
s->rx_msg = NULL;
|
||||||
/* reset rx buffer */
|
/* reset rx buffer */
|
||||||
s->rx_header_index = 0;
|
s->rx_header_index = 0;
|
||||||
s->rx_data_index = 0;
|
s->rx_data_index = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tx_again:
|
if (what & BSC_FD_WRITE) {
|
||||||
if (s->tx_list) {
|
if (s->tx_list) {
|
||||||
/* some frame in tx list, so try sending it */
|
/* some frame in tx list, so try sending it */
|
||||||
rc = send(s->connect, ((uint8_t *)&s->tx_list->msg.header), sizeof(s->tx_list->msg.header) + s->tx_list->msg.header.length, 0);
|
rc = send(s->connect_ofd.fd, ((uint8_t *)&s->tx_list->msg.header),
|
||||||
|
sizeof(s->tx_list->msg.header) + s->tx_list->msg.header.length, 0);
|
||||||
if (rc > 0) {
|
if (rc > 0) {
|
||||||
struct socket_msg_list *ml;
|
struct socket_msg_list *ml;
|
||||||
if (rc != (int)sizeof(s->tx_list->msg.header) + s->tx_list->msg.header.length) {
|
if (rc != (int)sizeof(s->tx_list->msg.header) + s->tx_list->msg.header.length) {
|
||||||
PDEBUG_CHAN(DPH, DEBUG_ERROR, "Short write, please fix handling!\n");
|
LOGP(DPH, LOGL_ERROR, "Short write, please fix handling!\n");
|
||||||
}
|
}
|
||||||
/* remove list entry */
|
/* remove list entry */
|
||||||
ml = s->tx_list;
|
ml = s->tx_list;
|
||||||
|
@ -251,16 +284,22 @@ tx_again:
|
||||||
if (s->tx_list == NULL)
|
if (s->tx_list == NULL)
|
||||||
s->tx_list_tail = &s->tx_list;
|
s->tx_list_tail = &s->tx_list;
|
||||||
free(ml);
|
free(ml);
|
||||||
work = 1;
|
|
||||||
goto tx_again;
|
|
||||||
} else if (rc == 0 || errno != EAGAIN) {
|
} else if (rc == 0 || errno != EAGAIN) {
|
||||||
close_connection(s);
|
close_connection(s);
|
||||||
work = 1;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
|
s->connect_ofd.when &= ~BSC_FD_WRITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return work;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ph_socket_timeout_cb(void *data)
|
||||||
|
{
|
||||||
|
ph_socket_t *s = data;
|
||||||
|
|
||||||
|
open_connection(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ph_socket_tx_msg(ph_socket_t *s, int channel, uint8_t prim, uint8_t *data, int length)
|
void ph_socket_tx_msg(ph_socket_t *s, int channel, uint8_t prim, uint8_t *data, int length)
|
||||||
|
@ -270,18 +309,18 @@ void ph_socket_tx_msg(ph_socket_t *s, int channel, uint8_t prim, uint8_t *data,
|
||||||
if (prim != PH_PRIM_DATA_REQ
|
if (prim != PH_PRIM_DATA_REQ
|
||||||
&& prim != PH_PRIM_DATA_IND
|
&& prim != PH_PRIM_DATA_IND
|
||||||
&& prim != PH_PRIM_DATA_CNF) {
|
&& prim != PH_PRIM_DATA_CNF) {
|
||||||
PDEBUG_CHAN(DPH, DEBUG_DEBUG, "message 0x%02x channel %d to socket\n", prim, channel);
|
LOGP(DPH, LOGL_DEBUG, "message 0x%02x channel %d to socket\n", prim, channel);
|
||||||
if (length)
|
if (length)
|
||||||
PDEBUG_CHAN(DPH, DEBUG_DEBUG, " -> data:%s\n", debug_hex(data, length));
|
LOGP(DPH, LOGL_DEBUG, " -> data:%s\n", osmo_hexdump(data, length));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (length > (int)sizeof(tx_msg->msg.data)) {
|
if (length > (int)sizeof(tx_msg->msg.data)) {
|
||||||
PDEBUG_CHAN(DPH, DEBUG_NOTICE, "Frame from HDLC process too large for socket, dropping!\n");
|
LOGP(DPH, LOGL_NOTICE, "Frame from HDLC process too large for socket, dropping!\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->connect <= 0) {
|
if (s->connect_ofd.fd <= 0) {
|
||||||
PDEBUG_CHAN(DPH, DEBUG_NOTICE, "Dropping message for socket, socket is closed!\n");
|
LOGP(DPH, LOGL_NOTICE, "Dropping message for socket, socket is closed!\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,5 +334,6 @@ void ph_socket_tx_msg(ph_socket_t *s, int channel, uint8_t prim, uint8_t *data,
|
||||||
/* move message to list */
|
/* move message to list */
|
||||||
*s->tx_list_tail = tx_msg;
|
*s->tx_list_tail = tx_msg;
|
||||||
s->tx_list_tail = &tx_msg->next;
|
s->tx_list_tail = &tx_msg->next;
|
||||||
|
s->connect_ofd.when |= BSC_FD_WRITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,17 +85,17 @@ struct socket_msg_list {
|
||||||
struct socket_msg msg;
|
struct socket_msg msg;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SOCKET_RETRY_TIMER 2.0
|
#define SOCKET_RETRY_TIMER 2
|
||||||
|
|
||||||
typedef struct ph_socket {
|
typedef struct ph_socket {
|
||||||
const char *name;
|
const char *name;
|
||||||
void (*ph_socket_rx_msg)(struct ph_socket *s, int channel, uint8_t prim, uint8_t *data, int length);
|
void (*ph_socket_rx_msg)(struct ph_socket *s, int channel, uint8_t prim, uint8_t *data, int length);
|
||||||
void *priv;
|
void *priv;
|
||||||
struct sockaddr_un sock_address;
|
struct sockaddr_un sock_address;
|
||||||
int listen; /* socket to listen to incoming connections */
|
struct osmo_fd listen_ofd; /* socket to listen to incoming connections */
|
||||||
int connect; /* socket of incoming connection */
|
struct osmo_fd connect_ofd; /* socket of incoming connection */
|
||||||
int connect_failed; /* used to print a failure only once */
|
int connect_failed; /* used to print a failure only once */
|
||||||
double connect_timer; /* time when to connect again */
|
struct osmo_timer_list retry_timer; /* timer to connect again */
|
||||||
struct socket_msg_list *tx_list, **tx_list_tail;
|
struct socket_msg_list *tx_list, **tx_list_tail;
|
||||||
struct socket_msg_list *rx_msg;
|
struct socket_msg_list *rx_msg;
|
||||||
int rx_header_index;
|
int rx_header_index;
|
||||||
|
@ -105,6 +105,3 @@ typedef struct ph_socket {
|
||||||
int ph_socket_init(ph_socket_t *s, void (*ph_socket_rx_msg)(ph_socket_t *s, int channel, uint8_t prim, uint8_t *data, int length), void *priv, const char *socket_name, int server);
|
int ph_socket_init(ph_socket_t *s, void (*ph_socket_rx_msg)(ph_socket_t *s, int channel, uint8_t prim, uint8_t *data, int length), void *priv, const char *socket_name, int server);
|
||||||
void ph_socket_exit(ph_socket_t *s);
|
void ph_socket_exit(ph_socket_t *s);
|
||||||
void ph_socket_tx_msg(ph_socket_t *s, int channel, uint8_t prim, uint8_t *data, int length);
|
void ph_socket_tx_msg(ph_socket_t *s, int channel, uint8_t prim, uint8_t *data, int length);
|
||||||
int ph_socket_work(ph_socket_t *s);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
AM_CPPFLAGS = -Wall -Wextra -g $(all_includes)
|
||||||
|
|
||||||
|
noinst_LIBRARIES = libselect.a
|
||||||
|
|
||||||
|
libselect_a_SOURCES = \
|
||||||
|
select.c
|
|
@ -0,0 +1,168 @@
|
||||||
|
/* Timer handling
|
||||||
|
*
|
||||||
|
* (C) 2023 by Andreas Eversberg <jolly@eversberg.eu>
|
||||||
|
* All Rights Reserved
|
||||||
|
*
|
||||||
|
* Inspired by libosmocore
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include "select.h"
|
||||||
|
|
||||||
|
//#define DEBUG
|
||||||
|
|
||||||
|
#define MAX_OFD 1024
|
||||||
|
|
||||||
|
struct osmo_fd *ofd_list = NULL;
|
||||||
|
int ofd_changed = 0;
|
||||||
|
|
||||||
|
int osmo_fd_register(struct osmo_fd *ofd)
|
||||||
|
{
|
||||||
|
struct osmo_fd **ofdp;
|
||||||
|
|
||||||
|
/* attach to list, if not already */
|
||||||
|
ofdp = &ofd_list;
|
||||||
|
while (*ofdp) {
|
||||||
|
if (*ofdp == ofd)
|
||||||
|
break;
|
||||||
|
ofdp = &((*ofdp)->next);
|
||||||
|
}
|
||||||
|
if (!*ofdp) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "%s: ofd=%p fd=%d registers.\n", __func__, ofd, ofd->fd);
|
||||||
|
#endif
|
||||||
|
ofd->next = NULL;
|
||||||
|
*ofdp = ofd;
|
||||||
|
ofd_changed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void osmo_fd_unregister(struct osmo_fd *ofd)
|
||||||
|
{
|
||||||
|
struct osmo_fd **ofdp;
|
||||||
|
|
||||||
|
/* detach from list, if not already */
|
||||||
|
ofdp = &ofd_list;
|
||||||
|
while (*ofdp) {
|
||||||
|
if (*ofdp == ofd)
|
||||||
|
break;
|
||||||
|
ofdp = &((*ofdp)->next);
|
||||||
|
}
|
||||||
|
if (*ofdp) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "%s: ofd=%p fd=%d unregisters.\n", __func__, ofd, ofd->fd);
|
||||||
|
#endif
|
||||||
|
*ofdp = ofd->next;
|
||||||
|
ofd->next = NULL;
|
||||||
|
ofd_changed = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int osmo_fd_select(double timeout)
|
||||||
|
{
|
||||||
|
fd_set readset;
|
||||||
|
fd_set writeset;
|
||||||
|
fd_set exceptset;
|
||||||
|
struct osmo_fd *ofd;
|
||||||
|
struct timeval tv;
|
||||||
|
int max_fd;
|
||||||
|
unsigned int what;
|
||||||
|
int work = 0;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* init event sets */
|
||||||
|
FD_ZERO(&readset);
|
||||||
|
FD_ZERO(&writeset);
|
||||||
|
FD_ZERO(&exceptset);
|
||||||
|
|
||||||
|
/* populate event set with all file descriptios */
|
||||||
|
ofd = ofd_list;
|
||||||
|
max_fd = 0;
|
||||||
|
while (ofd) {
|
||||||
|
if (ofd->fd > max_fd)
|
||||||
|
max_fd = ofd->fd;
|
||||||
|
if (ofd->when & OSMO_FD_READ)
|
||||||
|
FD_SET(ofd->fd, &readset);
|
||||||
|
if (ofd->when & OSMO_FD_WRITE)
|
||||||
|
FD_SET(ofd->fd, &writeset);
|
||||||
|
if (ofd->when & OSMO_FD_EXCEPT)
|
||||||
|
FD_SET(ofd->fd, &exceptset);
|
||||||
|
ofd = ofd->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeout >= 0) {
|
||||||
|
/* prepare timeout */
|
||||||
|
tv.tv_sec = floor(timeout);
|
||||||
|
tv.tv_usec = (timeout - tv.tv_sec) * 1000000.0;
|
||||||
|
/* wait for event or timeout */
|
||||||
|
rc = select(max_fd + 1, &readset, &writeset, &exceptset, &tv);
|
||||||
|
} else {
|
||||||
|
/* wait for event */
|
||||||
|
rc = select(max_fd + 1, &readset, &writeset, &exceptset, NULL);
|
||||||
|
}
|
||||||
|
if (rc < 0) {
|
||||||
|
if (errno != EINTR)
|
||||||
|
fprintf(stderr, "%s: select() failed: '%d' with errno %d (%s) Please fix!\n", __func__, rc, errno, strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
again:
|
||||||
|
/* check the result and call handler */
|
||||||
|
ofd_changed = 0;
|
||||||
|
ofd = ofd_list;
|
||||||
|
while (ofd) {
|
||||||
|
what = 0;
|
||||||
|
if (FD_ISSET(ofd->fd, &readset)) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "%s: ofd=%p fd=%d get READ event.\n", __func__, ofd, ofd->fd);
|
||||||
|
#endif
|
||||||
|
what |= OSMO_FD_READ;
|
||||||
|
FD_CLR(ofd->fd, &readset);
|
||||||
|
}
|
||||||
|
if (FD_ISSET(ofd->fd, &writeset)) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "%s: ofd=%p fd=%d get WRITE event.\n", __func__, ofd, ofd->fd);
|
||||||
|
#endif
|
||||||
|
what |= OSMO_FD_WRITE;
|
||||||
|
FD_CLR(ofd->fd, &writeset);
|
||||||
|
}
|
||||||
|
if (FD_ISSET(ofd->fd, &exceptset)) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "%s: ofd=%p fd=%d get EXCEPTION event.\n", __func__, ofd, ofd->fd);
|
||||||
|
#endif
|
||||||
|
what |= OSMO_FD_EXCEPT;
|
||||||
|
FD_CLR(ofd->fd, &exceptset);
|
||||||
|
}
|
||||||
|
if (what) {
|
||||||
|
work = 1;
|
||||||
|
ofd->cb(ofd, what);
|
||||||
|
/* list has changed */
|
||||||
|
if (ofd_changed)
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
ofd = ofd->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return work;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
#define OSMO_FD_READ 0x0001
|
||||||
|
#define OSMO_FD_WRITE 0x0002
|
||||||
|
#define OSMO_FD_EXCEPT 0x0004
|
||||||
|
#define BSC_FD_READ 0x0001
|
||||||
|
#define BSC_FD_WRITE 0x0002
|
||||||
|
#define BSC_FD_EXCEPT 0x0004
|
||||||
|
|
||||||
|
struct osmo_fd {
|
||||||
|
struct osmo_fd *next;
|
||||||
|
int fd;
|
||||||
|
unsigned int when;
|
||||||
|
int (*cb)(struct osmo_fd *fd, unsigned int what);
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
int osmo_fd_register(struct osmo_fd *ofd);
|
||||||
|
void osmo_fd_unregister(struct osmo_fd *ofd);
|
||||||
|
int osmo_fd_select(double timeout);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue