diff --git a/src/libdebug/debug.h b/src/libdebug/debug.h index 5942651..1d0c461 100644 --- a/src/libdebug/debug.h +++ b/src/libdebug/debug.h @@ -84,3 +84,10 @@ extern int debug_limit_scroll; const char *debug_hex(const uint8_t *data, int len); +#define LOGP PDEBUG +#define LOGL_DEBUG DEBUG_DEBUG +#define LOGL_INFO DEBUG_INFO +#define LOGL_NOTICE DEBUG_NOTICE +#define LOGL_ERROR DEBUG_ERROR +#define osmo_hexdump debug_hex + diff --git a/src/libosmocc/endpoint.c b/src/libosmocc/endpoint.c index 48290d5..e78b3ed 100644 --- a/src/libosmocc/endpoint.c +++ b/src/libosmocc/endpoint.c @@ -24,6 +24,7 @@ #include #include #include "../libtimer/timer.h" +#include "../libselect/select.h" #include "../libdebug/debug.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)); 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(); } - 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->callref = callref; @@ -58,7 +59,7 @@ static void call_delete(osmo_cc_call_t *call) { osmo_cc_call_t **cp; - PDEBUG(DCC, DEBUG_DEBUG, "Destroying call with callref %u.\n", call->callref); + LOGP(DCC, LOGL_DEBUG, "Destroying call with callref %u.\n", call->callref); /* detach from call process 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) { - 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; } @@ -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); 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; } portstring = osmo_cc_port_of_address(address); if (!portstring) { - PDEBUG(DCC, DEBUG_ERROR, "Port number in given address '%s' is not specified or invalid.\n", address); + LOGP(DCC, LOGL_ERROR, "Port number in given address '%s' is not specified or invalid.\n", address); return -EINVAL; } *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) { rc = split_address(address, &host, &port); if (rc < 0) { - PDEBUG(DCC, DEBUG_ERROR, "Given remote peer's address '%s' in setup message is invalid, rejecting call.\n", address); + LOGP(DCC, LOGL_ERROR, "Given remote peer's address '%s' in setup message is invalid, rejecting call.\n", address); reject: /* reject, due to error */ osmo_cc_free_msg(msg); @@ -228,21 +229,21 @@ reject: call_delete(call); 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 */ if (msg->type == OSMO_CC_MSG_ATTACH_IND) { host = call->ep->remote_host; port = call->ep->remote_port; - PDEBUG(DCC, DEBUG_DEBUG, "Using host IP '%s' and port '%d' from remote address for attach message.\n", host, port); + LOGP(DCC, LOGL_DEBUG, "Using host IP '%s' and port '%d' from remote address for attach message.\n", host, port); } /* if there is no remote peer in the setup message, use remote peer */ if (!address && msg->type == OSMO_CC_MSG_SETUP_IND && call->ep->remote_host) { host = call->ep->remote_host; port = call->ep->remote_port; - 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 */ @@ -256,16 +257,16 @@ reject: /* check for incoming attachment */ att = osmo_cc_get_attached_interface(call->ep, interface); if (!att && !interface[0]) { - PDEBUG(DCC, DEBUG_ERROR, "No remote peer attached, rejecting call.\n"); + LOGP(DCC, LOGL_ERROR, "No remote peer attached, rejecting call.\n"); goto reject; } if (!att) { - PDEBUG(DCC, DEBUG_ERROR, "No remote peer attached for given interface '%s', rejecting call.\n", interface); + LOGP(DCC, LOGL_ERROR, "No remote peer attached for given interface '%s', rejecting call.\n", interface); goto reject; } host = att->attached_host; port = att->attached_port; - 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 */ @@ -278,13 +279,13 @@ reject: } /* 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_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 */ 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) { - 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 */ 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 || call->state == OSMO_CC_STATE_ATTACH_OUT) { timer_start(&call->ep->attach_timer, OSMO_CC_ATTACH_TIMER); - PDEBUG(DCC, DEBUG_INFO, "Attachment to remote peer \"%s\" failed, retrying.\n", call->ep->remote_address); + LOGP(DCC, LOGL_INFO, "Attachment to remote peer \"%s\" failed, retrying.\n", call->ep->remote_address); } if (call->attached_name) - PDEBUG(DCC, DEBUG_INFO, "Peer with remote interface \"%s\" detached from us.\n", call->attached_name); + LOGP(DCC, LOGL_INFO, "Peer with remote interface \"%s\" detached from us.\n", call->attached_name); /* change state */ new_call_state(call, OSMO_CC_STATE_IDLE); @@ -355,12 +356,12 @@ void attach_req(osmo_cc_call_t *call, osmo_cc_msg_t *msg) if (rc < 0) address[0] = '\0'; if (!address[0]) { - PDEBUG(DCC, DEBUG_ERROR, "Attachment request from remote peer has no remote address set, rejecting.\n"); + LOGP(DCC, LOGL_ERROR, "Attachment request from remote peer has no remote address set, rejecting.\n"); rel: /* change to REL_REQ */ msg->type = OSMO_CC_MSG_REL_IND; - 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 */ forward_to_ul(call, msg); @@ -372,7 +373,7 @@ rel: } rc = split_address(address, &host, &port); if (rc < 0) { - PDEBUG(DCC, DEBUG_ERROR, "Given remote peer's address '%s' in attach message is invalid, rejecting call.\n", address); + LOGP(DCC, LOGL_ERROR, "Given remote peer's address '%s' in attach message is invalid, rejecting call.\n", address); goto rel; } free((char *)call->attached_host); @@ -387,11 +388,11 @@ rel: 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 */ 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 */ 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 */ 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 */ 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) { /* change to REL_REQ */ msg->type = OSMO_CC_MSG_REL_IND; - PDEBUG(DCC, DEBUG_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type)); + LOGP(DCC, LOGL_INFO, "Changing message to %s.\n", osmo_cc_msg_value2name(msg->type)); /* to upper layer */ 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 */ 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 */ 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 */ 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 */ 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 */ 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; /* 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 */ 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; /* 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)) break; 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_free_msg(msg); 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); - if (debuglevel <= DEBUG_INFO) - osmo_cc_debug_ie(msg, DEBUG_INFO); + if (debuglevel <= LOGL_INFO) + osmo_cc_debug_ie(msg, LOGL_INFO); 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; 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); 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; 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); return; } @@ -1124,7 +1125,7 @@ static int osmo_cc_set_name(osmo_cc_endpoint_t *ep, const char *text) text++; } } else { - PDEBUG(DCC, DEBUG_ERROR, "Invalid name definition '%s'\n", text); + LOGP(DCC, LOGL_ERROR, "Invalid name definition '%s'\n", text); return -EINVAL; } @@ -1187,12 +1188,12 @@ static int osmo_cc_set_address(osmo_cc_endpoint_t *ep, const char *text) text++; } 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; return 0; } 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; 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; port_p = &ep->remote_port; } 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; } @@ -1226,7 +1227,7 @@ static int osmo_cc_set_address(osmo_cc_endpoint_t *ep, const char *text) enum osmo_cc_session_addrtype addrtype; addrtype = osmo_cc_address_type(*host_p); if (addrtype == osmo_cc_session_addrtype_unknown) { - PDEBUG(DCC, DEBUG_ERROR, "Given local address '%s' is invalid.\n", *host_p); + LOGP(DCC, LOGL_ERROR, "Given local address '%s' is invalid.\n", *host_p); return -EINVAL; } osmo_cc_set_local_peer(&ep->session_config, osmo_cc_session_nettype_inet, addrtype, *host_p); @@ -1260,7 +1261,7 @@ static int osmo_cc_set_rtp(osmo_cc_endpoint_t *ep, const char *text) text += 9; ports = 1; } else { - PDEBUG(DCC, DEBUG_ERROR, "Invalid RTP definition '%s'\n", text); + LOGP(DCC, LOGL_ERROR, "Invalid RTP definition '%s'\n", text); 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; addrtype = osmo_cc_address_type(text); if (addrtype == osmo_cc_session_addrtype_unknown) { - PDEBUG(DCC, DEBUG_ERROR, "Given RTP address '%s' is invalid.\n", text); + LOGP(DCC, LOGL_ERROR, "Given RTP address '%s' is invalid.\n", text); return -EINVAL; } osmo_cc_set_local_peer(&ep->session_config, osmo_cc_session_nettype_inet, addrtype, text); @@ -1288,7 +1289,7 @@ static int osmo_cc_set_rtp(osmo_cc_endpoint_t *ep, const char *text) /* from port */ while (*text > ' ') { 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; } 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 */ while (*text > ' ') { 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; } 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 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)) { - 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; } @@ -1391,7 +1392,7 @@ int osmo_cc_new(osmo_cc_endpoint_t *ep, const char *version, const char *name, u return rc; } } 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; } } @@ -1407,7 +1408,7 @@ int osmo_cc_new(osmo_cc_endpoint_t *ep, const char *version, const char *name, u port = ep->local_port; if (!host) { 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); 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) { free((char *)ep->remote_host); ep->remote_host = strdup(ep->local_host); - PDEBUG(DCC, DEBUG_DEBUG, "Remote peer set to auto, using local peer's host \"%s\" for remote peer.\n", ep->remote_host); + LOGP(DCC, LOGL_DEBUG, "Remote peer set to auto, using local peer's host \"%s\" for remote peer.\n", ep->remote_host); if (rc == OSMO_CC_DEFAULT_PORT) ep->remote_port = OSMO_CC_DEFAULT_PORT + 1; else ep->remote_port = OSMO_CC_DEFAULT_PORT; - 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 */ free((char *)ep->remote_address); 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 */ timer_init(&ep->attach_timer, send_attach_ind, ep); 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; - PDEBUG(DCC, DEBUG_DEBUG, "Destroying endpoint instance.\n"); + LOGP(DCC, LOGL_DEBUG, "Destroying endpoint instance.\n"); /* detach from list >*/ epp = &osmo_cc_endpoint_list; @@ -1535,7 +1536,7 @@ const char *osmo_cc_host_of_address(const char *address) char *p; 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; } diff --git a/src/libosmocc/helper.c b/src/libosmocc/helper.c index 7700174..f94d33c 100644 --- a/src/libosmocc/helper.c +++ b/src/libosmocc/helper.c @@ -25,6 +25,7 @@ #include #include #include "../libtimer/timer.h" +#include "../libselect/select.h" #include "../libdebug/debug.h" #include "endpoint.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; if (*session_p) { - PDEBUG(DCC, DEBUG_ERROR, "Session already set, please fix!\n"); + LOGP(DCC, LOGL_ERROR, "Session already set, please fix!\n"); abort(); } if (*codec_p) { - PDEBUG(DCC, DEBUG_ERROR, "Codec already set, please fix!\n"); + LOGP(DCC, LOGL_ERROR, "Codec already set, please fix!\n"); abort(); } /* SDP IE */ rc = osmo_cc_get_ie_sdp(msg, 0, offer_sdp, sizeof(offer_sdp)); if (rc < 0) { - 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; } *session_p = osmo_cc_session_receive_offer(conf, priv, offer_sdp); if (!*session_p) { - PDEBUG(DCC, DEBUG_ERROR, "Failed to parse SDP.\n"); + LOGP(DCC, LOGL_ERROR, "Failed to parse SDP.\n"); return NULL; } @@ -123,7 +124,7 @@ const char *osmo_cc_helper_audio_accept(osmo_cc_session_config_t *conf, void *pr break; } 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); *session_p = 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; if (!(*session_p)) { - PDEBUG(DCC, DEBUG_ERROR, "Session not set, please fix!\n"); + LOGP(DCC, LOGL_ERROR, "Session not set, please fix!\n"); abort(); } @@ -184,7 +185,7 @@ int osmo_cc_helper_audio_negotiate(osmo_cc_msg_t *msg, osmo_cc_session_t **sessi } } 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; } diff --git a/src/libosmocc/message.c b/src/libosmocc/message.c index 6dc7a7f..1197f63 100644 --- a/src/libosmocc/message.c +++ b/src/libosmocc/message.c @@ -374,7 +374,7 @@ osmo_cc_msg_t *osmo_cc_new_msg(uint8_t msg_type) /* allocate message */ msg = calloc(1, sizeof(*msg) + 65535); if (!msg) { - PDEBUG(DCC, DEBUG_ERROR, "No memory\n"); + LOGP(DCC, LOGL_ERROR, "No memory\n"); abort(); } /* 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; /* check for minimum IE length */ if (msg_len < sizeof(*ie)) { - PDEBUG(DCC, level, "****** Rest of message is too short for an IE: value=%s\n", debug_hex(p, msg_len)); + LOGP(DCC, level, "****** Rest of message is too short for an IE: value=%s\n", debug_hex(p, msg_len)); return; } /* get actual IE length */ len = ntohs(ie->length_networkorder); /* check if IE length does not exceed message */ if (msg_len < sizeof(*ie) + len) { - 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; } 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)); if (rc < 0) break; - PDEBUG(DCC, level, " %s type=%d(%s) plan=%d(%s) number='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_type_value2name(type), plan, osmo_cc_plan_value2name(plan), string); + LOGP(DCC, level, " %s type=%d(%s) plan=%d(%s) number='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_type_value2name(type), plan, osmo_cc_plan_value2name(plan), string); break; case OSMO_CC_IE_CALLED_SUB: rc = osmo_cc_get_ie_called_sub(msg, ie_repeat[ie->type], &type, string, sizeof(string)); if (rc < 0) break; - 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; case OSMO_CC_IE_CALLED_NAME: rc = osmo_cc_get_ie_called_name(msg, ie_repeat[ie->type], string, sizeof(string)); if (rc < 0) break; - PDEBUG(DCC, level, " %s name='%s'\n", osmo_cc_ie_value2name(ie->type), string); + LOGP(DCC, level, " %s name='%s'\n", osmo_cc_ie_value2name(ie->type), string); break; case OSMO_CC_IE_CALLED_INTERFACE: rc = osmo_cc_get_ie_called_interface(msg, ie_repeat[ie->type], string, sizeof(string)); if (rc < 0) break; - 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; case OSMO_CC_IE_COMPLETE: rc = osmo_cc_get_ie_complete(msg, ie_repeat[ie->type]); if (rc < 0) break; - PDEBUG(DCC, level, " %s\n", osmo_cc_ie_value2name(ie->type)); + LOGP(DCC, level, " %s\n", osmo_cc_ie_value2name(ie->type)); break; case OSMO_CC_IE_CALLING: rc = osmo_cc_get_ie_calling(msg, ie_repeat[ie->type], &type, &plan, &present, &screen, string, sizeof(string)); if (rc < 0) break; - 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; case OSMO_CC_IE_CALLING_SUB: rc = osmo_cc_get_ie_calling_sub(msg, ie_repeat[ie->type], &type, string, sizeof(string)); if (rc < 0) break; - PDEBUG(DCC, level, " %s type=%d(%s) number='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_type_value2name(type), string); + LOGP(DCC, level, " %s type=%d(%s) number='%s'\n", osmo_cc_ie_value2name(ie->type), type, osmo_cc_type_value2name(type), string); break; case OSMO_CC_IE_CALLING_NAME: rc = osmo_cc_get_ie_calling_name(msg, ie_repeat[ie->type], string, sizeof(string)); if (rc < 0) break; - 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; case OSMO_CC_IE_CALLING_INTERFACE: rc = osmo_cc_get_ie_calling_interface(msg, ie_repeat[ie->type], string, sizeof(string)); if (rc < 0) break; - PDEBUG(DCC, level, " %s name='%s'\n", osmo_cc_ie_value2name(ie->type), string); + LOGP(DCC, level, " %s name='%s'\n", osmo_cc_ie_value2name(ie->type), string); break; case OSMO_CC_IE_CALLING_NETWORK: rc = osmo_cc_get_ie_calling_network(msg, ie_repeat[ie->type], &type, string, sizeof(string)); if (rc < 0) break; - 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; case OSMO_CC_IE_BEARER: rc = osmo_cc_get_ie_bearer(msg, ie_repeat[ie->type], &coding, &capability, &mode); if (rc < 0) break; - PDEBUG(DCC, level, " %s coding=%d(%s) capability=%d(%s) mode=%d(%s)\n", osmo_cc_ie_value2name(ie->type), coding, osmo_cc_coding_value2name(coding), capability, osmo_cc_capability_value2name(capability), mode, osmo_cc_mode_value2name(mode)); + LOGP(DCC, level, " %s coding=%d(%s) capability=%d(%s) mode=%d(%s)\n", osmo_cc_ie_value2name(ie->type), coding, osmo_cc_coding_value2name(coding), capability, osmo_cc_capability_value2name(capability), mode, osmo_cc_mode_value2name(mode)); break; case OSMO_CC_IE_REDIR: rc = osmo_cc_get_ie_redir(msg, ie_repeat[ie->type], &type, &plan, &present, &screen, &reason, string, sizeof(string)); if (rc < 0) break; - 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; case OSMO_CC_IE_DTMF: rc = osmo_cc_get_ie_dtmf(msg, ie_repeat[ie->type], &duration_ms, &pause_ms, &dtmf_mode, string, sizeof(string)); if (rc < 0) break; - PDEBUG(DCC, level, " %s duration=%dms pause=%dms mode=%d(%s)\n", osmo_cc_ie_value2name(ie->type), duration_ms, pause_ms, dtmf_mode, osmo_cc_dtmf_mode_value2name(dtmf_mode)); + LOGP(DCC, level, " %s duration=%dms pause=%dms mode=%d(%s)\n", osmo_cc_ie_value2name(ie->type), duration_ms, pause_ms, dtmf_mode, osmo_cc_dtmf_mode_value2name(dtmf_mode)); break; case OSMO_CC_IE_KEYPAD: rc = osmo_cc_get_ie_keypad(msg, ie_repeat[ie->type], string, sizeof(string)); if (rc < 0) break; - 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; case OSMO_CC_IE_PROGRESS: rc = osmo_cc_get_ie_progress(msg, ie_repeat[ie->type], &coding, &location, &progress); if (rc < 0) break; - PDEBUG(DCC, level, " %s coding=%d(%s) location=%d(%s) progress=%d(%s)\n", osmo_cc_ie_value2name(ie->type), coding, osmo_cc_coding_value2name(coding), location, osmo_cc_location_value2name(location), progress, osmo_cc_progress_value2name(progress)); + LOGP(DCC, level, " %s coding=%d(%s) location=%d(%s) progress=%d(%s)\n", osmo_cc_ie_value2name(ie->type), coding, osmo_cc_coding_value2name(coding), location, osmo_cc_location_value2name(location), progress, osmo_cc_progress_value2name(progress)); break; case OSMO_CC_IE_NOTIFY: rc = osmo_cc_get_ie_notify(msg, ie_repeat[ie->type], ¬ify); if (rc < 0) break; - 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; case OSMO_CC_IE_CAUSE: rc = osmo_cc_get_ie_cause(msg, ie_repeat[ie->type], &location, &isdn_cause, &sip_cause, &socket_cause); if (rc < 0) break; - PDEBUG(DCC, level, " %s location=%d(%s) isdn_cause=%d(%s) sip_cause=%d socket_cause=%d(%s)\n", osmo_cc_ie_value2name(ie->type), location, osmo_cc_location_value2name(location), isdn_cause, osmo_cc_isdn_cause_value2name(isdn_cause), sip_cause, socket_cause, osmo_cc_socket_cause_value2name(socket_cause)); + LOGP(DCC, level, " %s location=%d(%s) isdn_cause=%d(%s) sip_cause=%d socket_cause=%d(%s)\n", osmo_cc_ie_value2name(ie->type), location, osmo_cc_location_value2name(location), isdn_cause, osmo_cc_isdn_cause_value2name(isdn_cause), sip_cause, socket_cause, osmo_cc_socket_cause_value2name(socket_cause)); break; case OSMO_CC_IE_DISPLAY: rc = osmo_cc_get_ie_display(msg, ie_repeat[ie->type], string, sizeof(string)); if (rc < 0) break; - 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; case OSMO_CC_IE_SDP: 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') 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; case OSMO_CC_IE_SOCKET_ADDRESS: rc = osmo_cc_get_ie_socket_address(msg, ie_repeat[ie->type], string, sizeof(string)); if (rc < 0) break; - PDEBUG(DCC, level, " %s address='%s'\n", osmo_cc_ie_value2name(ie->type), string); + LOGP(DCC, level, " %s address='%s'\n", osmo_cc_ie_value2name(ie->type), string); break; case OSMO_CC_IE_PRIVATE: rc = osmo_cc_get_ie_private(msg, ie_repeat[ie->type], &unique, (uint8_t *)string, sizeof(string)); if (rc < 0) break; - 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; 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]++; 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; /* check for minimum IE length */ if (msg_len < sizeof(*ie)) { - PDEBUG(DCC, DEBUG_ERROR, "MSG short read\n"); - osmo_cc_debug_ie(msg, DEBUG_ERROR); + LOGP(DCC, LOGL_ERROR, "MSG short read\n"); + osmo_cc_debug_ie(msg, LOGL_ERROR); return -EINVAL; } /* get actual IE length */ len = ntohs(ie->length_networkorder); /* check if IE length does not exceed message */ if (msg_len < sizeof(*ie) + len) { - PDEBUG(DCC, DEBUG_ERROR, "MSG short read\n"); - osmo_cc_debug_ie(msg, DEBUG_ERROR); + LOGP(DCC, LOGL_ERROR, "MSG short read\n"); + osmo_cc_debug_ie(msg, LOGL_ERROR); return -EINVAL; } /* check if IE matches the one that is searched for */ @@ -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*/ 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; } *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); new_msg_len = msg_len + sizeof(*ie) + ie_len; if (new_msg_len > 65535) { - PDEBUG(DCC, DEBUG_ERROR, "MSG overflow\n"); + LOGP(DCC, LOGL_ERROR, "MSG overflow\n"); return NULL; } msg->length_networkorder = htons(new_msg_len); diff --git a/src/libosmocc/rtp.c b/src/libosmocc/rtp.c index fc70748..613d12c 100644 --- a/src/libosmocc/rtp.c +++ b/src/libosmocc/rtp.c @@ -28,6 +28,7 @@ #include #include "../libdebug/debug.h" #include "../libtimer/timer.h" +#include "../libselect/select.h" #include "endpoint.h" #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 (errno == 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; } 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; } @@ -86,20 +87,20 @@ static int rtp_receive(int sock, uint8_t **payload_p, int *payload_len_p, uint8_ *ssrc_p = ntohl(rtph->ssrc); 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; } payload = data + sizeof(*rtph) + (csrc_count << 2); payload_len = len - sizeof(*rtph) - (csrc_count << 2); if (payload_len < 0) { - PDEBUG(DCC, DEBUG_NOTICE, "Received RTP frame too short (len = %d, csrc count = %d).\n", len, csrc_count); + LOGP(DCC, LOGL_NOTICE, "Received RTP frame too short (len = %d, csrc count = %d).\n", len, csrc_count); return -EINVAL; } if (extension) { if (payload_len < (int)sizeof(*rtpxh)) { - 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; } 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_len -= x_len; 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; } } if (padding) { 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; } payload_len -= payload[payload_len - 1]; 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; } } @@ -132,6 +133,22 @@ static int rtp_receive(int sock, uint8_t **payload_p, int *payload_len_p, uint8_ 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) { 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); len += payload_len; if (len > (int)sizeof(data)) { - PDEBUG(DCC, DEBUG_NOTICE, "Buffer overflow, please fix!.\n"); + LOGP(DCC, LOGL_NOTICE, "Buffer overflow, please fix!.\n"); abort(); } memcpy(data + sizeof(*rtph), payload, payload_len); rc = write(sock, data, len); if (rc < 0) - PDEBUG(DCC, DEBUG_DEBUG, "Write errno = %d (%s)\n", errno, strerror(errno)); + 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 * 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); if (rc < 1) { 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; } sport = &sa4->sin_port; @@ -204,7 +224,7 @@ pton_error: slen = sizeof(*sa6); break; case osmo_cc_session_addrtype_unknown: - PDEBUG(DCC, DEBUG_NOTICE, "Unsupported address type '%s'.\n", media->connection_data_local.addrtype_name); + LOGP(DCC, LOGL_NOTICE, "Unsupported address type '%s'.\n", media->connection_data_local.addrtype_name); return -EINVAL; } @@ -217,46 +237,54 @@ pton_error: rc = socket(domain, SOCK_DGRAM, IPPROTO_UDP); if (rc < 0) { socket_error: - PDEBUG(DCC, DEBUG_ERROR, "Cannot create socket (domain=%d, errno=%d(%s))\n", domain, errno, strerror(errno)); + LOGP(DCC, LOGL_ERROR, "Cannot create socket (domain=%d, errno=%d(%s))\n", domain, errno, strerror(errno)); osmo_cc_rtp_close(media); return -EIO; } - media->rtp_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); if (rc < 0) 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 */ *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) { bind_error: osmo_cc_rtp_close(media); conf->rtp_port_next = (conf->rtp_port_next + 2 > conf->rtp_port_to) ? conf->rtp_port_from : conf->rtp_port_next + 2; if (conf->rtp_port_next == start_port) { - PDEBUG(DCC, DEBUG_ERROR, "Cannot bind socket (errno=%d(%s))\n", errno, strerror(errno)); + LOGP(DCC, LOGL_ERROR, "Cannot bind socket (errno=%d(%s))\n", errno, strerror(errno)); return -EIO; } continue; } *sport = htons(conf->rtp_port_next + 1); - rc = bind(media->rtcp_socket, (struct sockaddr *)&sa, slen); + rc = bind(media->rtcp_ofd.fd, (struct sockaddr *)&sa, slen); if (rc < 0) goto bind_error; media->description.port_local = conf->rtp_port_next; conf->rtp_port_next = (conf->rtp_port_next + 2 > conf->rtp_port_to) ? conf->rtp_port_from : conf->rtp_port_next + 2; - /* set nonblocking io */ - flags = fcntl(media->rtp_socket, F_GETFL); + /* set nonblocking io, to prevent write to block */ + flags = fcntl(media->rtp_ofd.fd, F_GETFL); flags |= O_NONBLOCK; - fcntl(media->rtp_socket, F_SETFL, flags); - flags = fcntl(media->rtcp_socket, F_GETFL); + fcntl(media->rtp_ofd.fd, F_SETFL, flags); + flags = fcntl(media->rtcp_ofd.fd, F_GETFL); flags |= O_NONBLOCK; - fcntl(media->rtcp_socket, F_SETFL, flags); + fcntl(media->rtcp_ofd.fd, F_SETFL, flags); 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; } @@ -273,7 +301,7 @@ int osmo_cc_rtp_connect(osmo_cc_session_media_t *media) uint16_t *sport; 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) { 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); if (rc < 1) { 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; } sport = &sa4->sin_port; @@ -300,20 +328,20 @@ pton_error: slen = sizeof(*sa6); break; case osmo_cc_session_addrtype_unknown: - PDEBUG(DCC, DEBUG_NOTICE, "Unsupported address type '%s'.\n", media->connection_data_local.addrtype_name); + LOGP(DCC, LOGL_NOTICE, "Unsupported address type '%s'.\n", media->connection_data_local.addrtype_name); return -EINVAL; } *sport = htons(media->description.port_remote); - rc = connect(media->rtp_socket, (struct sockaddr *)&sa, slen); + rc = connect(media->rtp_ofd.fd, (struct sockaddr *)&sa, slen); if (rc < 0) { 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); return -EIO; } *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) 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; int payload_len = 0; - if (!codec || !codec->media->rtp_socket) + if (!codec || !codec->media->rtp_ofd.fd) return; 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; } - 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_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); } -/* receive rtp data for given media, return < 0, if there is nothing this time */ -int osmo_cc_rtp_receive(osmo_cc_session_media_t *media, void *priv) +static int rtp_listen_cb(struct osmo_fd *ofd, unsigned int when) { + osmo_cc_session_media_t *media = ofd->data; int rc; uint8_t *payload = NULL; int payload_len = 0; @@ -356,49 +384,63 @@ int osmo_cc_rtp_receive(osmo_cc_session_media_t *media, void *priv) uint8_t *data; int len; - if (!media || media->rtp_socket <= 0) - return -EIO; + if (when & OSMO_FD_READ) { + 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); - if (rc < 0) - return rc; + /* search for codec */ + for (codec = media->codec_list; codec; codec = codec->next) { + if (codec->payload_type_local == payload_type) + break; + } + if (!codec) { + LOGP(DCC, LOGL_NOTICE, "Received RTP frame for unknown codec (payload_type = %d).\n", payload_type); + return 0; + } - /* search for codec */ - for (codec = media->codec_list; codec; codec = codec->next) { - - if (codec->payload_type_local == payload_type) - break; - } - if (!codec) { - PDEBUG(DCC, DEBUG_NOTICE, "Received RTP frame for unknown codec (payload_type = %d).\n", payload_type); - return 0; + if (codec->decoder) + codec->decoder(payload, payload_len, &data, &len, media->session->priv); + else { + data = payload; + len = payload_len; + } + + if (codec->media->receive) + codec->media->receiver(codec, marker, media->rx_sequence, media->rx_timestamp, media->rx_ssrc, data, len); + + if (codec->decoder) + free(data); } - if (codec->decoder) - codec->decoder(payload, payload_len, &data, &len, priv); - else { - data = payload; - len = payload_len; + return 0; +} + +static int rtcp_listen_cb(struct osmo_fd *ofd, unsigned int when) +{ + 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; } void osmo_cc_rtp_close(osmo_cc_session_media_t *media) { - if (media->rtp_socket) { - close(media->rtp_socket); - media->rtp_socket = 0; + if (media->rtp_ofd.fd) { + osmo_fd_unregister(&media->rtp_ofd); + close(media->rtp_ofd.fd); + media->rtp_ofd.fd = 0; } - if (media->rtcp_socket) { - close(media->rtcp_socket); - media->rtcp_socket = 0; + if (media->rtcp_ofd.fd) { + osmo_fd_unregister(&media->rtcp_ofd); + close(media->rtcp_ofd.fd); + media->rtcp_ofd.fd = 0; } } diff --git a/src/libosmocc/rtp.h b/src/libosmocc/rtp.h index f6e5632..ea1b31f 100644 --- a/src/libosmocc/rtp.h +++ b/src/libosmocc/rtp.h @@ -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_connect(osmo_cc_session_media_t *media); void osmo_cc_rtp_send(osmo_cc_session_codec_t *codec, uint8_t *data, int len, uint8_t marker, int inc_sequence, int inc_timestamp, void *priv); -int osmo_cc_rtp_receive(osmo_cc_session_media_t *media, void *priv); void osmo_cc_rtp_close(osmo_cc_session_media_t *media); diff --git a/src/libosmocc/screen.c b/src/libosmocc/screen.c index 5558f42..be12f08 100644 --- a/src/libosmocc/screen.c +++ b/src/libosmocc/screen.c @@ -24,6 +24,7 @@ #include #include #include "../libtimer/timer.h" +#include "../libselect/select.h" #include "../libdebug/debug.h" #include "endpoint.h" #include "message.h" @@ -152,7 +153,7 @@ int osmo_cc_add_screen(osmo_cc_endpoint_t *ep, const char *text) text += 17; list_p = &ep->screen_called_out; } else { - PDEBUG(DCC, DEBUG_ERROR, "Invalid screening definition \"%s\". It must start with 'screen-calling-in' or 'screen-called-in' or 'screen-calling-out' or 'screen-called-out'\n", text); + 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; } @@ -171,7 +172,7 @@ next_from: token = osmo_cc_strtok_quotes(&text); if (!token) { free(list); - PDEBUG(DCC, DEBUG_ERROR, "Missing 'from' string in screening definition \"%s\". If the string shall be empty, use double quotes. (\'\' or \"\")\n", text); + LOGP(DCC, LOGL_ERROR, "Missing 'from' string in screening definition \"%s\". If the string shall be empty, use double quotes. (\'\' or \"\")\n", text); return -EINVAL; } if (!strcasecmp(token, "unknown")) { @@ -208,8 +209,8 @@ next_from: if (no_present) { no_present_error: free(list); - PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text); - PDEBUG(DCC, DEBUG_ERROR, "Keyword '%s' not allowed in screen entry for called number\n", token); + LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text); + LOGP(DCC, LOGL_ERROR, "Keyword '%s' not allowed in screen entry for called number\n", token); return -EINVAL; } list->has_from_present = 1; @@ -231,8 +232,8 @@ no_present_error: if (token[i] == '*') { if (star_used) { free(list); - PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text); - PDEBUG(DCC, DEBUG_ERROR, "The '*' may be used only once.\n"); + LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text); + LOGP(DCC, LOGL_ERROR, "The '*' may be used only once.\n"); return -EINVAL; } list->from[j] = SCREEN_STAR; @@ -250,8 +251,8 @@ next_to: token = osmo_cc_strtok_quotes(&text); if (!token) { free(list); - PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text); - PDEBUG(DCC, DEBUG_ERROR, "Missing screening result. If the string shall be empty, use double quotes. (\'\' or \"\")\n"); + LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text); + LOGP(DCC, LOGL_ERROR, "Missing screening result. If the string shall be empty, use double quotes. (\'\' or \"\")\n"); return -EINVAL; } if (!strcasecmp(token, "unknown")) { @@ -303,8 +304,8 @@ next_to: if (token[i] == '*') { if (star_used) { free(list); - PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text); - PDEBUG(DCC, DEBUG_ERROR, "The '*' may be used only once.\n"); + LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text); + LOGP(DCC, LOGL_ERROR, "The '*' may be used only once.\n"); return -EINVAL; } list->to[j] = SCREEN_STAR; @@ -313,14 +314,14 @@ next_to: if (token[i] == '@') { if (!calling_in) { free(list); - PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text); - PDEBUG(DCC, DEBUG_ERROR, "The '@' may be used only for incoming calls from interface.\n"); + LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text); + LOGP(DCC, LOGL_ERROR, "The '@' may be used only for incoming calls from interface.\n"); return -EINVAL; } if (at_used) { free(list); - PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text); - PDEBUG(DCC, DEBUG_ERROR, "The '@' may be used only once.\n"); + LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text); + LOGP(DCC, LOGL_ERROR, "The '@' may be used only once.\n"); return -EINVAL; } list->to[j] = SCREEN_AT; @@ -337,8 +338,8 @@ next_to: token = osmo_cc_strtok_quotes(&text); if (token) { free(list); - PDEBUG(DCC, DEBUG_ERROR, "Error in screening definition '%s'.\n", text); - PDEBUG(DCC, DEBUG_ERROR, "Got garbage behind screening result.\n"); + LOGP(DCC, LOGL_ERROR, "Error in screening definition '%s'.\n", text); + LOGP(DCC, LOGL_ERROR, "Got garbage behind screening result.\n"); 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; 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) { case OSMO_CC_TYPE_UNKNOWN: - PDEBUG(DCC, DEBUG_INFO, " -> type = unknown\n"); + LOGP(DCC, LOGL_INFO, " -> type = unknown\n"); break; case OSMO_CC_TYPE_INTERNATIONAL: - PDEBUG(DCC, DEBUG_INFO, " -> type = international\n"); + LOGP(DCC, LOGL_INFO, " -> type = international\n"); break; case OSMO_CC_TYPE_NATIONAL: - PDEBUG(DCC, DEBUG_INFO, " -> type = national\n"); + LOGP(DCC, LOGL_INFO, " -> type = national\n"); break; case OSMO_CC_TYPE_NETWORK: - PDEBUG(DCC, DEBUG_INFO, " -> type = network\n"); + LOGP(DCC, LOGL_INFO, " -> type = network\n"); break; case OSMO_CC_TYPE_SUBSCRIBER: - PDEBUG(DCC, DEBUG_INFO, " -> type = subscriber\n"); + LOGP(DCC, LOGL_INFO, " -> type = subscriber\n"); break; case OSMO_CC_TYPE_ABBREVIATED: - PDEBUG(DCC, DEBUG_INFO, " -> type = abbreviated\n"); + LOGP(DCC, LOGL_INFO, " -> type = abbreviated\n"); break; } if (present) switch (*present) { case OSMO_CC_PRESENT_ALLOWED: - PDEBUG(DCC, DEBUG_INFO, " -> present = allowed\n"); + LOGP(DCC, LOGL_INFO, " -> present = allowed\n"); break; case OSMO_CC_PRESENT_RESTRICTED: - PDEBUG(DCC, DEBUG_INFO, " -> present = restricted\n"); + LOGP(DCC, LOGL_INFO, " -> present = restricted\n"); break; } rule = 0; while (list) { rule++; - PDEBUG(DCC, DEBUG_INFO, "Comparing with rule #%d: '%s':\n", rule, print_rule_string(list->from)); + LOGP(DCC, LOGL_INFO, "Comparing with rule #%d: '%s':\n", rule, print_rule_string(list->from)); if (list->has_from_type) switch (list->from_type) { case OSMO_CC_TYPE_UNKNOWN: - PDEBUG(DCC, DEBUG_INFO, " -> type = unknown\n"); + LOGP(DCC, LOGL_INFO, " -> type = unknown\n"); break; case OSMO_CC_TYPE_INTERNATIONAL: - PDEBUG(DCC, DEBUG_INFO, " -> type = international\n"); + LOGP(DCC, LOGL_INFO, " -> type = international\n"); break; case OSMO_CC_TYPE_NATIONAL: - PDEBUG(DCC, DEBUG_INFO, " -> type = national\n"); + LOGP(DCC, LOGL_INFO, " -> type = national\n"); break; case OSMO_CC_TYPE_NETWORK: - PDEBUG(DCC, DEBUG_INFO, " -> type = network\n"); + LOGP(DCC, LOGL_INFO, " -> type = network\n"); break; case OSMO_CC_TYPE_SUBSCRIBER: - PDEBUG(DCC, DEBUG_INFO, " -> type = subscriber\n"); + LOGP(DCC, LOGL_INFO, " -> type = subscriber\n"); break; case OSMO_CC_TYPE_ABBREVIATED: - PDEBUG(DCC, DEBUG_INFO, " -> type = abbreviated\n"); + LOGP(DCC, LOGL_INFO, " -> type = abbreviated\n"); break; } if (list->has_from_present) switch (list->from_present) { case OSMO_CC_PRESENT_ALLOWED: - PDEBUG(DCC, DEBUG_INFO, " -> present = allowed\n"); + LOGP(DCC, LOGL_INFO, " -> present = allowed\n"); break; case OSMO_CC_PRESENT_RESTRICTED: - PDEBUG(DCC, DEBUG_INFO, " -> present = restricted\n"); + LOGP(DCC, LOGL_INFO, " -> present = restricted\n"); break; } suffix = NULL; /* attributes do not match */ if (list->has_from_type && list->from_type != *type) { - PDEBUG(DCC, DEBUG_INFO, "Rule does not match, because 'type' is different.\n"); + LOGP(DCC, LOGL_INFO, "Rule does not match, because 'type' is different.\n"); continue; } if (present && list->has_from_present && list->from_present != *present) { - PDEBUG(DCC, DEBUG_INFO, "Rule does not match, because 'present' is different.\n"); + LOGP(DCC, LOGL_INFO, "Rule does not match, because 'present' is different.\n"); continue; } 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 (list->from[i] == '\0' && id_from[i] == '\0') 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; } @@ -521,37 +522,37 @@ static int osmo_cc_screen(const char *what, osmo_cc_screen_list_t *list, uint8_t } 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) { case OSMO_CC_TYPE_UNKNOWN: - PDEBUG(DCC, DEBUG_INFO, " -> type = unknown\n"); + LOGP(DCC, LOGL_INFO, " -> type = unknown\n"); break; case OSMO_CC_TYPE_INTERNATIONAL: - PDEBUG(DCC, DEBUG_INFO, " -> type = international\n"); + LOGP(DCC, LOGL_INFO, " -> type = international\n"); break; case OSMO_CC_TYPE_NATIONAL: - PDEBUG(DCC, DEBUG_INFO, " -> type = national\n"); + LOGP(DCC, LOGL_INFO, " -> type = national\n"); break; case OSMO_CC_TYPE_NETWORK: - PDEBUG(DCC, DEBUG_INFO, " -> type = network\n"); + LOGP(DCC, LOGL_INFO, " -> type = network\n"); break; case OSMO_CC_TYPE_SUBSCRIBER: - PDEBUG(DCC, DEBUG_INFO, " -> type = subscriber\n"); + LOGP(DCC, LOGL_INFO, " -> type = subscriber\n"); break; case OSMO_CC_TYPE_ABBREVIATED: - PDEBUG(DCC, DEBUG_INFO, " -> type = abbreviated\n"); + LOGP(DCC, LOGL_INFO, " -> type = abbreviated\n"); break; } if (list->has_to_present) switch (list->to_present) { case OSMO_CC_PRESENT_ALLOWED: - PDEBUG(DCC, DEBUG_INFO, " -> present = allowed\n"); + LOGP(DCC, LOGL_INFO, " -> present = allowed\n"); break; case OSMO_CC_PRESENT_RESTRICTED: - PDEBUG(DCC, DEBUG_INFO, " -> present = restricted\n"); + LOGP(DCC, LOGL_INFO, " -> present = restricted\n"); break; } 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; } diff --git a/src/libosmocc/sdp.c b/src/libosmocc/sdp.c index 849bfb9..e350d52 100644 --- a/src/libosmocc/sdp.c +++ b/src/libosmocc/sdp.c @@ -25,6 +25,7 @@ #include #include "../libdebug/debug.h" #include "../libtimer/timer.h" +#include "../libselect/select.h" #include "endpoint.h" #include "sdp.h" @@ -135,7 +136,7 @@ char *osmo_cc_session_gensdp(osmo_cc_session_t *session) /* check for overflow and return */ if (strlen(sdp) == sizeof(sdp) - 1) { - PDEBUG(DCC, DEBUG_ERROR, "Fatal error: Allocated SDP buffer with %d bytes is too small, please fix!\n", (int)sizeof(sdp)); + LOGP(DCC, LOGL_ERROR, "Fatal error: Allocated SDP buffer with %d bytes is too small, please fix!\n", (int)sizeof(sdp)); return NULL; } return sdp; @@ -285,21 +286,21 @@ struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf, continue; 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; } switch(line[0]) { 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) { - 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); return NULL; } break; case 'o': - PDEBUG(DCC, DEBUG_DEBUG, " -> Originator: %s\n", next_word); + LOGP(DCC, LOGL_DEBUG, " -> Originator: %s\n", next_word); /* Originator */ word = wordsep(&next_word); if (!word) @@ -334,12 +335,12 @@ struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf, break; case 's': /* 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 session->name = strdup(next_word); break; 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) cd = &media->connection_data_remote; else @@ -350,7 +351,7 @@ struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf, if (!strcmp(word, "IN")) cd->nettype = osmo_cc_session_nettype_inet; else { - PDEBUG(DCC, DEBUG_NOTICE, "Unsupported network type '%s' in SDP line %d = '%s'\n", word, line_no, line); + LOGP(DCC, LOGL_NOTICE, "Unsupported network type '%s' in SDP line %d = '%s'\n", word, line_no, line); break; } /* address type */ @@ -358,13 +359,13 @@ struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf, break; if (!strcmp(word, "IP4")) { cd->addrtype = osmo_cc_session_addrtype_ipv4; - PDEBUG(DCC, DEBUG_DEBUG, " -> Address Type = IPv4\n"); + LOGP(DCC, LOGL_DEBUG, " -> Address Type = IPv4\n"); } else if (!strcmp(word, "IP6")) { cd->addrtype = osmo_cc_session_addrtype_ipv6; - PDEBUG(DCC, DEBUG_DEBUG, " -> Address Type = IPv6\n"); + LOGP(DCC, LOGL_DEBUG, " -> Address Type = IPv6\n"); } 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; } /* connection address */ @@ -374,10 +375,10 @@ struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf, *p++ = '\0'; free((char *)cd->address); // in case of multiple lines of 'c' cd->address = strdup(word); - PDEBUG(DCC, DEBUG_DEBUG, " -> Address = %s\n", word); + LOGP(DCC, LOGL_DEBUG, " -> Address = %s\n", word); break; 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 */ 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 */ @@ -394,7 +395,7 @@ struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf, else { media->description.type = osmo_cc_session_media_type_unknown; media->description.type_name = strdup(word); - PDEBUG(DCC, DEBUG_DEBUG, "Unsupported media type in SDP line %d = '%s'\n", line_no, line); + LOGP(DCC, LOGL_DEBUG, "Unsupported media type in SDP line %d = '%s'\n", line_no, line); } /* port */ if (!(word = wordsep(&next_word))) @@ -408,7 +409,7 @@ struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf, else { media->description.proto = osmo_cc_session_media_proto_unknown; media->description.proto_name = strdup(word); - PDEBUG(DCC, DEBUG_NOTICE, "Unsupported protocol type in SDP line %d = '%s'\n", line_no, line); + LOGP(DCC, LOGL_NOTICE, "Unsupported protocol type in SDP line %d = '%s'\n", line_no, line); break; } /* create codec description for each codec and link */ @@ -418,17 +419,17 @@ struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf, /* fmt */ codec->payload_type_remote = atoi(word); complete_codec_by_fmt(codec->payload_type_remote, &codec->payload_name, &codec->payload_rate, &codec->payload_channels); - PDEBUG(DCC, DEBUG_DEBUG, " -> payload type = %d\n", codec->payload_type_remote); + LOGP(DCC, LOGL_DEBUG, " -> payload type = %d\n", codec->payload_type_remote); 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) - 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) - PDEBUG(DCC, DEBUG_DEBUG, " -> payload channels = %d\n", codec->payload_channels); + LOGP(DCC, LOGL_DEBUG, " -> payload channels = %d\n", codec->payload_channels); } break; case 'a': - PDEBUG(DCC, DEBUG_DEBUG, " -> Attribute: %s\n", next_word); + LOGP(DCC, LOGL_DEBUG, " -> Attribute: %s\n", next_word); word = wordsep(&next_word); if (!strcmp(word, "sendrecv")) { if (media) { @@ -471,7 +472,7 @@ struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf, break; } else 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; } if (!strncmp(word, "rtpmap:", 7)) { @@ -481,23 +482,23 @@ struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf, break; } 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; } - 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))) goto rtpmap_done; if ((p = strchr(word, '/'))) *p++ = '\0'; free((char *)codec->payload_name); // in case it is already set above codec->payload_name = strdup(word); - PDEBUG(DCC, DEBUG_DEBUG, " -> (rtpmap) payload name = %s\n", codec->payload_name); + LOGP(DCC, LOGL_DEBUG, " -> (rtpmap) payload name = %s\n", codec->payload_name); if (!(word = p)) goto rtpmap_done; if ((p = strchr(word, '/'))) *p++ = '\0'; codec->payload_rate = atoi(word); - 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 no channel is given and no default was specified, we must set 1 channel */ 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; } 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: 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); } } @@ -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 (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); 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++) text[i] = *sdp++; text[i] = '\0'; - PDEBUG(DCC, DEBUG_DEBUG, " | %s\n", text); + LOGP(DCC, LOGL_DEBUG, " | %s\n", text); while (*sdp > 0 && *sdp < 32) sdp++; } diff --git a/src/libosmocc/session.c b/src/libosmocc/session.c index 427eca7..f4e7b88 100644 --- a/src/libosmocc/session.c +++ b/src/libosmocc/session.c @@ -25,6 +25,7 @@ #include #include #include "../libtimer/timer.h" +#include "../libselect/select.h" #include "../libdebug/debug.h" #include "../liboptions/options.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; - 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)); if (!session) { - PDEBUG(DCC, DEBUG_ERROR, "No mem!\n"); + LOGP(DCC, LOGL_ERROR, "No mem!\n"); abort(); } 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; for (i = 0; username[i]; i++) { if ((uint8_t)username[i] < 33) { - PDEBUG(DCC, DEBUG_ERROR, "Fatal error: SDP's originator (username) uses invalid characters, please fix!\n"); + LOGP(DCC, LOGL_ERROR, "Fatal error: SDP's originator (username) uses invalid characters, please fix!\n"); abort(); } } @@ -63,7 +64,7 @@ osmo_cc_session_t *osmo_cc_new_session(osmo_cc_session_config_t *conf, void *pri } if (!username) 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) session->origin_local.sess_id = strdup(sess_id); 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) session->origin_local.sess_version = strdup(ntp_timestamp); } - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> session ID = %s\n", session->origin_local.sess_id); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> session version = %s\n", session->origin_local.sess_version); + if (debug) LOGP(DCC, LOGL_DEBUG, " -> session ID = %s\n", session->origin_local.sess_id); + if (debug) LOGP(DCC, LOGL_DEBUG, " -> session version = %s\n", session->origin_local.sess_version); if (nettype) session->origin_local.nettype = strdup(osmo_cc_session_nettype2string(nettype)); else session->origin_local.nettype = strdup(osmo_cc_session_nettype2string(conf->default_nettype)); - if (debug) 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) session->origin_local.addrtype = strdup(osmo_cc_session_addrtype2string(addrtype)); else session->origin_local.addrtype = strdup(osmo_cc_session_addrtype2string(conf->default_addrtype)); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> address type = %s\n", session->origin_local.addrtype); + if (debug) LOGP(DCC, LOGL_DEBUG, " -> address type = %s\n", session->origin_local.addrtype); if (unicast_address) session->origin_local.unicast_address = strdup(unicast_address); else session->origin_local.unicast_address = strdup(conf->default_unicast_address); - if (debug) 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) session->name = strdup(session_name); if (!session_name) 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; } 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.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)); if (!media) { - PDEBUG(DCC, DEBUG_ERROR, "No mem!\n"); + LOGP(DCC, LOGL_ERROR, "No mem!\n"); abort(); } 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 = media; - if (debug) PDEBUG(DCC, DEBUG_DEBUG, "Adding session media.\n"); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> network type = %s\n", osmo_cc_session_nettype2string(media->connection_data_local.nettype)); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> address type = %s\n", osmo_cc_session_addrtype2string(media->connection_data_local.addrtype)); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> address = %s\n", media->connection_data_local.address); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> media type = %s\n", osmo_cc_session_media_type2string(media->description.type)); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> media port = %d\n", media->description.port_local); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> media proto = %s\n", osmo_cc_session_media_proto2string(media->description.proto)); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, "Opening and binding media port %d\n", media->description.port_local); + if (debug) LOGP(DCC, LOGL_DEBUG, "Adding session media.\n"); + if (debug) LOGP(DCC, LOGL_DEBUG, " -> network type = %s\n", osmo_cc_session_nettype2string(media->connection_data_local.nettype)); + if (debug) LOGP(DCC, LOGL_DEBUG, " -> address type = %s\n", osmo_cc_session_addrtype2string(media->connection_data_local.addrtype)); + if (debug) LOGP(DCC, LOGL_DEBUG, " -> address = %s\n", media->connection_data_local.address); + if (debug) LOGP(DCC, LOGL_DEBUG, " -> media type = %s\n", osmo_cc_session_media_type2string(media->description.type)); + if (debug) LOGP(DCC, LOGL_DEBUG, " -> media port = %d\n", media->description.port_local); + if (debug) LOGP(DCC, LOGL_DEBUG, " -> media proto = %s\n", osmo_cc_session_media_proto2string(media->description.proto)); + if (debug) LOGP(DCC, LOGL_DEBUG, "Opening and binding media port %d\n", media->description.port_local); return media; } @@ -179,7 +180,7 @@ void osmo_cc_free_media(osmo_cc_session_media_t *media) { osmo_cc_session_media_t **mediap; - PDEBUG(DCC, DEBUG_DEBUG, "Free session media.\n"); + LOGP(DCC, LOGL_DEBUG, "Free session media.\n"); osmo_cc_rtp_close(media); 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)); if (!codec) { - PDEBUG(DCC, DEBUG_ERROR, "No mem!\n"); + LOGP(DCC, LOGL_ERROR, "No mem!\n"); abort(); } 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 = codec; - if (debug) PDEBUG(DCC, DEBUG_DEBUG, "Adding session codec.\n"); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> payload type = %d\n", codec->payload_type_local); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> payload name = %s\n", codec->payload_name); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> payload rate = %d\n", codec->payload_rate); - if (debug) PDEBUG(DCC, DEBUG_DEBUG, " -> payload channels = %d\n", codec->payload_channels); + if (debug) LOGP(DCC, LOGL_DEBUG, "Adding session codec.\n"); + if (debug) LOGP(DCC, LOGL_DEBUG, " -> payload type = %d\n", codec->payload_type_local); + if (debug) LOGP(DCC, LOGL_DEBUG, " -> payload name = %s\n", codec->payload_name); + if (debug) LOGP(DCC, LOGL_DEBUG, " -> payload rate = %d\n", codec->payload_rate); + if (debug) LOGP(DCC, LOGL_DEBUG, " -> payload channels = %d\n", codec->payload_channels); return codec; } @@ -244,7 +245,7 @@ void osmo_cc_free_codec(osmo_cc_session_codec_t *codec) { osmo_cc_session_codec_t **codecp; - PDEBUG(DCC, DEBUG_DEBUG, "Free session codec.\n"); + LOGP(DCC, LOGL_DEBUG, "Free session codec.\n"); free((char *)codec->payload_name); codecp = &codec->media->codec_list; @@ -273,15 +274,15 @@ int osmo_cc_session_check(osmo_cc_session_t *session, int remote) || !orig->nettype || !orig->addrtype || !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; } 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; } if (!session->media_list) { - PDEBUG(DCC, DEBUG_NOTICE, "Missing media session\n"); + LOGP(DCC, LOGL_NOTICE, "Missing media session\n"); return -EINVAL; } i = 0; @@ -292,39 +293,39 @@ int osmo_cc_session_check(osmo_cc_session_t *session, int remote) else cd = &media->connection_data_local; if (!cd->nettype && !cd->nettype_name) { - PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d is missing connection network type\n", i); + LOGP(DCC, LOGL_NOTICE, "Session with media #%d is missing connection network type\n", i); return -EINVAL; } if (!cd->addrtype && !cd->addrtype_name) { - PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d is missing connection address type\n", i); + LOGP(DCC, LOGL_NOTICE, "Session with media #%d is missing connection address type\n", i); return -EINVAL; } if (!cd->address) { - PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d is missing connection address\n", i); + LOGP(DCC, LOGL_NOTICE, "Session with media #%d is missing connection address\n", i); return -EINVAL; } md = &media->description; if (!md->type && !md->type_name) { - 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; } 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; } j = 0; osmo_cc_session_for_each_codec(media->codec_list, codec) { j++; if (!codec->payload_name) { - PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d, codec #%d is missing name\n", i, j); + LOGP(DCC, LOGL_NOTICE, "Session with media #%d, codec #%d is missing name\n", i, j); return -EINVAL; } if (!codec->payload_rate) { - PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d, codec #%d is missing rate\n", i, j); + LOGP(DCC, LOGL_NOTICE, "Session with media #%d, codec #%d is missing rate\n", i, j); return -EINVAL; } if (!codec->payload_channels) { - PDEBUG(DCC, DEBUG_NOTICE, "Session with media #%d, codec #%d is missing channel count\n", i, j); + LOGP(DCC, LOGL_NOTICE, "Session with media #%d, codec #%d is missing channel count\n", i, j); return -EINVAL; } } @@ -339,11 +340,11 @@ const char *osmo_cc_session_send_offer(osmo_cc_session_t *session) const char *sdp; int rc; - PDEBUG(DCC, DEBUG_DEBUG, "Generating session offer and opening RTP stream.\n"); + LOGP(DCC, LOGL_DEBUG, "Generating session offer and opening RTP stream.\n"); rc = osmo_cc_session_check(session, 0); if (rc < 0) { - PDEBUG(DCC, DEBUG_ERROR, "Please fix!\n"); + LOGP(DCC, LOGL_ERROR, "Please fix!\n"); 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; int rc; - PDEBUG(DCC, DEBUG_DEBUG, "Parsing session offer.\n"); + LOGP(DCC, LOGL_DEBUG, "Parsing session offer.\n"); osmo_cc_debug_sdp(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->receiver = receiver; - PDEBUG(DCC, DEBUG_DEBUG, "Accepting session media.\n"); - PDEBUG(DCC, DEBUG_DEBUG, " -> network type = %s\n", osmo_cc_session_nettype2string(media->connection_data_local.nettype)); - PDEBUG(DCC, DEBUG_DEBUG, " -> address type = %s\n", osmo_cc_session_addrtype2string(media->connection_data_local.addrtype)); - PDEBUG(DCC, DEBUG_DEBUG, " -> address = %s\n", media->connection_data_local.address); + LOGP(DCC, LOGL_DEBUG, "Accepting session media.\n"); + LOGP(DCC, LOGL_DEBUG, " -> network type = %s\n", osmo_cc_session_nettype2string(media->connection_data_local.nettype)); + LOGP(DCC, LOGL_DEBUG, " -> address type = %s\n", osmo_cc_session_addrtype2string(media->connection_data_local.addrtype)); + LOGP(DCC, LOGL_DEBUG, " -> address = %s\n", media->connection_data_local.address); } @@ -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 */ codec->payload_type_local = codec->payload_type_remote; - PDEBUG(DCC, DEBUG_DEBUG, "Accepting session codec.\n"); - PDEBUG(DCC, DEBUG_DEBUG, " -> payload type = %d\n", codec->payload_type_local); - PDEBUG(DCC, DEBUG_DEBUG, " -> payload name = %s\n", codec->payload_name); - PDEBUG(DCC, DEBUG_DEBUG, " -> payload rate = %d\n", codec->payload_rate); - PDEBUG(DCC, DEBUG_DEBUG, " -> payload channels = %d\n", codec->payload_channels); + LOGP(DCC, LOGL_DEBUG, "Accepting session codec.\n"); + LOGP(DCC, LOGL_DEBUG, " -> payload type = %d\n", codec->payload_type_local); + LOGP(DCC, LOGL_DEBUG, " -> payload name = %s\n", codec->payload_name); + LOGP(DCC, LOGL_DEBUG, " -> payload rate = %d\n", codec->payload_rate); + LOGP(DCC, LOGL_DEBUG, " -> payload channels = %d\n", codec->payload_channels); } /* remove codecs/media that have not been accepted and generate SDP */ @@ -426,7 +427,7 @@ const char *osmo_cc_session_send_answer(osmo_cc_session_t *session) const char *sdp; int rc; - PDEBUG(DCC, DEBUG_DEBUG, "Generating session answer.\n"); + LOGP(DCC, LOGL_DEBUG, "Generating session answer.\n"); /* loop all 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); if (rc < 0) { - PDEBUG(DCC, DEBUG_ERROR, "Please fix!\n"); + LOGP(DCC, LOGL_ERROR, "Please fix!\n"); 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; int rc; - PDEBUG(DCC, DEBUG_DEBUG, "Negotiating session.\n"); + LOGP(DCC, LOGL_DEBUG, "Negotiating session.\n"); /* copy remote session information */ 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) { - 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; } 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; } @@ -549,7 +550,7 @@ int osmo_cc_session_receive_answer(osmo_cc_session_t *session, const char *sdp) osmo_cc_session_t *session_remote; int rc; - PDEBUG(DCC, DEBUG_DEBUG, "Parsing session answer.\n"); + LOGP(DCC, LOGL_DEBUG, "Parsing session answer.\n"); osmo_cc_debug_sdp(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); } -int osmo_cc_session_handle(osmo_cc_session_t *session, void *codec_priv) -{ - osmo_cc_session_media_t *media; - int w = 0, rc; - - osmo_cc_session_for_each_media(session->media_list, media) { - do { - rc = osmo_cc_rtp_receive(media, codec_priv); - if (rc >= 0) - w = 1; - } while (rc >= 0); - } - - return w; -} - diff --git a/src/libosmocc/session.h b/src/libosmocc/session.h index 0330f51..ddbed82 100644 --- a/src/libosmocc/session.h +++ b/src/libosmocc/session.h @@ -80,8 +80,8 @@ typedef struct osmo_cc_session_media { struct osmo_cc_session_codec *codec_list; int send, receive; void (*receiver)(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len); - int rtp_socket; - int rtcp_socket; + struct osmo_fd rtp_ofd; + struct osmo_fd rtcp_ofd; uint32_t tx_ssrc, rx_ssrc; uint16_t tx_sequence, rx_sequence; uint32_t tx_timestamp, rx_timestamp; @@ -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_proto2string(enum osmo_cc_session_media_proto media_proto); int osmo_cc_session_if_codec(osmo_cc_session_codec_t *codec, const char *name, uint32_t rate, int channels); -int osmo_cc_session_handle(osmo_cc_session_t *session, void *codec_priv); diff --git a/src/libosmocc/socket.c b/src/libosmocc/socket.c index d25e1f1..9d8f30a 100644 --- a/src/libosmocc/socket.c +++ b/src/libosmocc/socket.c @@ -28,6 +28,7 @@ #include #include "../libdebug/debug.h" #include "../libtimer/timer.h" +#include "../libselect/select.h" #include "message.h" #include "cause.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); 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; @@ -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); } -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; /* 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); -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); } +static int socket_listen_cb(struct osmo_fd *ofd, unsigned int when); + /* create socket process and bind socket */ int osmo_cc_open_socket(osmo_cc_socket_t *os, const char *host, uint16_t port, void *priv, void (*recv_msg_cb)(void *priv, uint32_t callref, osmo_cc_msg_t *msg), uint8_t location) { int try = 0, auto_port = 0; struct addrinfo *result, *rp; - int rc, sock, flags; + int rc, sock; memset(os, 0, sizeof(*os)); @@ -118,7 +121,7 @@ try_again: 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); if (rc < 0) @@ -137,26 +140,27 @@ try_again: freeaddrinfo(result); if (rp == NULL) { if (auto_port && port < OSMO_CC_DEFAULT_PORT_MAX) { - PDEBUG(DCC, DEBUG_DEBUG, "Failed to bind host %s port %d, trying again.\n", host, port); + LOGP(DCC, LOGL_DEBUG, "Failed to bind host %s port %d, trying again.\n", host, port); goto try_again; } - PDEBUG(DCC, DEBUG_ERROR, "Failed to bind given host %s port %d.\n", host, port); + LOGP(DCC, LOGL_ERROR, "Failed to bind given host %s port %d.\n", host, port); return -EIO; } /* listen to socket */ rc = listen(sock, 10); if (rc < 0) { - PDEBUG(DCC, DEBUG_ERROR, "Failed to listen on socket.\n"); + LOGP(DCC, LOGL_ERROR, "Failed to listen on socket.\n"); + close(sock); return rc; } - /* set nonblocking io */ - flags = fcntl(sock, F_GETFL); - flags |= O_NONBLOCK; - fcntl(sock, F_SETFL, flags); - - os->socket = sock; + /* register */ + os->ofd.fd = sock; + os->ofd.cb = socket_listen_cb; + os->ofd.data = os; + os->ofd.when = OSMO_FD_READ; + osmo_fd_register(&os->ofd); os->recv_msg_cb = recv_msg_cb; os->priv = priv; os->location = location; @@ -164,6 +168,8 @@ try_again: return port; } +static int socket_conn_cb(struct osmo_fd *ofd, unsigned int when); + /* create a connection */ static osmo_cc_conn_t *open_conn(osmo_cc_socket_t *os, int sock, uint32_t callref, int read_setup) { @@ -172,11 +178,15 @@ static osmo_cc_conn_t *open_conn(osmo_cc_socket_t *os, int sock, uint32_t callre /* create connection */ conn = calloc(1, sizeof(*conn)); if (!conn) { - PDEBUG(DCC, DEBUG_ERROR, "No mem!\n"); + LOGP(DCC, LOGL_ERROR, "No mem!\n"); abort(); } 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->write_version = 1; 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->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 */ 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); } - 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 */ - if (conn->socket) - close(conn->socket); + if (conn->ofd.fd) { + osmo_fd_unregister(&conn->ofd); + close(conn->ofd.fd); + } /* free partly received message */ if (conn->read_msg) osmo_cc_free_msg(conn->read_msg); @@ -244,15 +256,16 @@ void osmo_cc_close_socket(osmo_cc_socket_t *os) { osmo_cc_msg_list_t *ml; - PDEBUG(DCC, DEBUG_DEBUG, "Destroy socket.\n"); + LOGP(DCC, LOGL_DEBUG, "Destroy socket.\n"); /* free all connections */ while (os->conn_list) close_conn(os->conn_list, 0); /* close socket */ - if (os->socket > 0) { - close(os->socket); - os->socket = 0; + if (os->ofd.fd > 0) { + osmo_fd_unregister(&os->ofd); + close(os->ofd.fd); + os->ofd.fd = 0; } /* free send queue */ while ((ml = os->write_list)) { @@ -293,7 +306,7 @@ static int receive_conn(osmo_cc_conn_t *conn) /* get version from remote */ if (conn->read_version) { - rc = recv(conn->socket, conn->read_version_string + conn->read_version_pos, strlen(version_string) - conn->read_version_pos, 0); + rc = recv(conn->ofd.fd, conn->read_version_string + conn->read_version_pos, strlen(version_string) - conn->read_version_pos, 0); if (rc < 0 && errno == EAGAIN) return work; work = 1; @@ -304,12 +317,12 @@ static int receive_conn(osmo_cc_conn_t *conn) if (conn->read_version_pos == strlen(version_string)) { conn->read_version = 0; if (!!memcmp(conn->read_version_string, version_string, strlen(version_string) - 1)) { - PDEBUG(DCC, DEBUG_NOTICE, "Remote does not seem to be an Osmo-CC socket, rejecting!\n"); + LOGP(DCC, LOGL_NOTICE, "Remote does not seem to be an Osmo-CC socket, rejecting!\n"); socket_cause = OSMO_CC_SOCKET_CAUSE_FAILED; goto close; } if (conn->read_version_string[strlen(version_string) - 1] != version_string[strlen(version_string) - 1]) { - 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; goto close; } @@ -320,7 +333,7 @@ static int receive_conn(osmo_cc_conn_t *conn) try_next_message: /* read message header from remote */ if (!conn->read_msg) { - rc = recv(conn->socket, ((uint8_t *)&conn->read_hdr) + conn->read_pos, sizeof(conn->read_hdr) - conn->read_pos, 0); + rc = recv(conn->ofd.fd, ((uint8_t *)&conn->read_hdr) + conn->read_pos, sizeof(conn->read_hdr) - conn->read_pos, 0); if (rc < 0 && errno == EAGAIN) return work; work = 1; @@ -344,7 +357,7 @@ try_next_message: len = ntohs(msg->length_networkorder); if (len == 0) goto empty_message; - rc = recv(conn->socket, msg->data + conn->read_pos, len - conn->read_pos, 0); + rc = recv(conn->ofd.fd, msg->data + conn->read_pos, len - conn->read_pos, 0); if (rc < 0 && errno == EAGAIN) return work; work = 1; @@ -369,7 +382,7 @@ empty_message: else conn->os->recv_msg_cb(conn->os->priv, conn->callref, msg); if (msg_type == OSMO_CC_MSG_REL_REQ || msg_type == OSMO_CC_MSG_REJ_REQ) { - PDEBUG(DCC, DEBUG_DEBUG, "closing socket because we received a release or reject message.\n"); + LOGP(DCC, LOGL_DEBUG, "closing socket because we received a release or reject message.\n"); close_conn(conn, 0); return 1; /* conn removed */ } @@ -378,7 +391,7 @@ empty_message: return work; 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); return work; /* conn removed */ } @@ -397,7 +410,7 @@ static int transmit_conn(osmo_cc_conn_t *conn) /* send socket version to remote */ 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) return work; work = 1; @@ -405,7 +418,7 @@ static int transmit_conn(osmo_cc_conn_t *conn) goto close; } 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(); } conn->write_version = 0; @@ -416,7 +429,7 @@ static int transmit_conn(osmo_cc_conn_t *conn) timer_stop(&conn->tx_keepalive_timer); msg = conn->write_list->msg; 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) return work; work = 1; @@ -424,12 +437,12 @@ static int transmit_conn(osmo_cc_conn_t *conn) goto close; } if (rc != len) { - PDEBUG(DCC, DEBUG_ERROR, "short write, please fix handling!\n"); + LOGP(DCC, LOGL_ERROR, "short write, please fix handling!\n"); abort(); } /* close socket after sending release/reject message */ if (msg->type == OSMO_CC_MSG_REL_REQ || msg->type == OSMO_CC_MSG_REJ_REQ) { - 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); return work; /* conn removed */ } @@ -450,7 +463,7 @@ static int transmit_conn(osmo_cc_conn_t *conn) return work; close: - PDEBUG(DCC, DEBUG_NOTICE, "OsmoCC-Socket failed.\n"); + LOGP(DCC, LOGL_NOTICE, "OsmoCC-Socket failed.\n"); close_conn(conn, socket_cause); return work; /* conn removed */ } @@ -460,8 +473,6 @@ close: */ int osmo_cc_handle_socket(osmo_cc_socket_t *os) { - struct sockaddr_storage sa; - socklen_t slen = sizeof(sa); int sock; osmo_cc_conn_t *conn; osmo_cc_msg_list_t *ml, **mlp; @@ -487,6 +498,7 @@ int osmo_cc_handle_socket(osmo_cc_socket_t *os) while (*mlp) mlp = &((*mlp)->next); *mlp = ml; + conn->ofd.when |= OSMO_FD_WRITE; /* done with message */ continue; } @@ -504,7 +516,7 @@ int osmo_cc_handle_socket(osmo_cc_socket_t *os) /* reject, if this is not a setup message */ if (ml->msg->type != OSMO_CC_MSG_SETUP_REQ && ml->msg->type != OSMO_CC_MSG_ATTACH_REQ) { - PDEBUG(DCC, DEBUG_ERROR, "Message with unknown callref.\n"); + LOGP(DCC, LOGL_ERROR, "Message with unknown callref.\n"); rej_msg(os, ml->callref, 0, OSMO_CC_ISDN_CAUSE_INVAL_CALLREF, 0); /* drop message */ osmo_cc_free_msg(ml->msg); @@ -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); if (sock < 0) continue; - /* set nonblocking io */ + /* set nonblocking io, to prevent connect() and subsequent reads from blocking */ flags = fcntl(sock, F_GETFL); flags |= O_NONBLOCK; fcntl(sock, F_SETFL, flags); @@ -538,7 +550,7 @@ int osmo_cc_handle_socket(osmo_cc_socket_t *os) } freeaddrinfo(result); 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); /* drop message */ 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); /* attach to list */ conn->write_list = ml; + conn->ofd.when |= OSMO_FD_WRITE; /* 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; } +static int socket_listen_cb(struct osmo_fd *ofd, unsigned int when) +{ + osmo_cc_socket_t *os = ofd->data; + struct sockaddr_storage sa; + socklen_t slen = sizeof(sa); + int sock; + int flags; + + if (when & OSMO_FD_READ) { + /* handle new socket connection */ + if ((sock = accept(os->ofd.fd, (struct sockaddr *)&sa, &slen)) > 0) { + /* set nonblocking io, to prevent subsequent reads from blocking */ + flags = fcntl(sock, F_GETFL); + flags |= O_NONBLOCK; + fcntl(sock, F_SETFL, flags); + /* create connection */ + open_conn(os, sock, 0, 1); + } + } + + return 0; +} + +static int socket_conn_cb(struct osmo_fd *ofd, unsigned int when) +{ + osmo_cc_conn_t *conn = ofd->data; + int work; + + if (when & OSMO_FD_READ) { + /* check for rx */ + work = receive_conn(conn); + /* if "change" is set, connection list might have changed, so we restart processing the list */ + if (work) + return 0; + } + if (when & OSMO_FD_WRITE) { + /* check for tx */ + work = transmit_conn(conn); + /* if "change" is set, connection list might have changed, so we restart processing the list */ + if (work) + return 0; + else + conn->ofd.when &= ~OSMO_FD_WRITE; + } + + return 0; +} + diff --git a/src/libosmocc/socket.h b/src/libosmocc/socket.h index bcd8b7c..a3cc046 100644 --- a/src/libosmocc/socket.h +++ b/src/libosmocc/socket.h @@ -12,7 +12,7 @@ struct osmo_cc_socket; typedef struct osmo_cc_conn { struct osmo_cc_conn *next; struct osmo_cc_socket *os; - int socket; + struct osmo_fd ofd; uint32_t callref; int read_setup; int read_version; @@ -28,7 +28,7 @@ typedef struct osmo_cc_conn { } osmo_cc_conn_t; typedef struct osmo_cc_socket { - int socket; + struct osmo_fd ofd; osmo_cc_conn_t *conn_list; osmo_cc_msg_list_t *write_list; void (*recv_msg_cb)(void *priv, uint32_t callref, osmo_cc_msg_t *msg); diff --git a/src/libph_socket/ph_socket.c b/src/libph_socket/ph_socket.c index 98b6070..28ec30f 100644 --- a/src/libph_socket/ph_socket.c +++ b/src/libph_socket/ph_socket.c @@ -26,55 +26,58 @@ #include #include #include -#include +#include "../libtimer/timer.h" +#include "../libselect/select.h" #include "../libdebug/debug.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; - 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; + if (s->connect_ofd.fd > 0) + return; - 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); - - if (server) { - rc = socket(PF_UNIX, SOCK_STREAM, 0); - 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); + LOGP(DPH, LOGL_DEBUG, "Trying to connect to PH-socket server.\n"); + rc = socket(PF_UNIX, SOCK_STREAM, 0); + if (rc < 0) { + LOGP(DPH, LOGL_ERROR, "Failed to create UNIX socket.\n"); + osmo_timer_schedule(&s->retry_timer, SOCKET_RETRY_TIMER, 0); + return; } - - PDEBUG_CHAN(DPH, DEBUG_INFO, "Created PH-socket at '%s'.\n", s->name); - - return 0; + s->connect_ofd.fd = rc; + s->connect_ofd.data = s; + s->connect_ofd.when = BSC_FD_READ; + 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) @@ -82,16 +85,17 @@ static void close_connection(ph_socket_t *s) struct socket_msg_list *ml; uint8_t disable = PH_CTRL_BLOCK; - if (s->connect <= 0) + if (s->connect_ofd.fd <= 0) 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 */ - 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); - s->connect = 0; + osmo_fd_unregister(&s->connect_ofd); + close(s->connect_ofd.fd); + s->connect_ofd.fd = 0; while ((ml = s->tx_list)) { s->tx_list = ml->next; @@ -103,147 +107,176 @@ static void close_connection(ph_socket_t *s) s->rx_msg = NULL; } - /* set timer, so that retry is delayed */ - static struct timespec tv; - clock_gettime(CLOCK_REALTIME, &tv); - double now = (double)tv.tv_sec + (double)tv.tv_nsec / 1000000000.0; - s->connect_timer = now + SOCKET_RETRY_TIMER; + if (s->listen_ofd.fd <= 0) { + /* set timer, so that retry is delayed */ + osmo_timer_schedule(&s->retry_timer, SOCKET_RETRY_TIMER, 0); + } +} + +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) { - PDEBUG_CHAN(DPH, DEBUG_INFO, "Destroyed PH-socket.\n"); + LOGP(DPH, LOGL_INFO, "Destroyed PH-socket.\n"); close_connection(s); - if (s->listen > 0) { - close(s->listen); - s->listen = 0; + if (s->listen_ofd.fd > 0) { + osmo_fd_unregister(&s->listen_ofd); + 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; int rc, flags; - int work = 0; - if (s->listen > 0) { - struct sockaddr_un sock_address; - socklen_t sock_len = sizeof(sock_address); - /* see if there is an incoming connection */ - rc = accept(s->listen, (struct sockaddr *)&sock_address, &sock_len); - if (rc > 0) { - if (s->connect > 0) { - PDEBUG_CHAN(DPH, DEBUG_ERROR, "Rejecting incoming connection, because we already have a client connected!\n"); - close(rc); - } else { - PDEBUG_CHAN(DPH, DEBUG_INFO, "Connection from PH-socket client.\n"); - s->connect = rc; - /* 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_REQ, &enable, 1); - } - work = 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); - } + socklen_t sock_len = sizeof(sock_address); + /* see if there is an incoming connection */ + rc = accept(s->listen_ofd.fd, (struct sockaddr *)&sock_address, &sock_len); + if (rc > 0) { + if (s->connect_ofd.fd > 0) { + LOGP(DPH, LOGL_ERROR, "Rejecting incoming connection, because we already have a client " + "connected!\n"); + close(rc); + } else { + LOGP(DPH, LOGL_INFO, "Connection from PH-socket client.\n"); + s->connect_ofd.fd = rc; + s->connect_ofd.data = s; + s->connect_ofd.when = BSC_FD_READ; + 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); + /* 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_REQ, &enable, 1); } } - /* handle connection, if any */ - if (s->connect > 0) { + return 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) s->rx_msg = calloc(1, sizeof(*s->rx_msg)); -rx_again: if (s->rx_header_index < (int)sizeof(s->rx_msg->msg.header)) { /* 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) { s->rx_header_index += rc; - work = 1; goto rx_again; } else if (rc == 0 || errno != EAGAIN) { close_connection(s); - work = 1; + return 0; } } else if (s->rx_data_index < s->rx_msg->msg.header.length) { /* 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) { s->rx_data_index += rc; - work = 1; goto rx_again; } else if (rc == 0 || errno != EAGAIN) { close_connection(s); - work = 1; + return 0; } } else { /* process and free message */ 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_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) - 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); s->rx_msg = NULL; /* reset rx buffer */ s->rx_header_index = 0; s->rx_data_index = 0; } + } -tx_again: + if (what & BSC_FD_WRITE) { if (s->tx_list) { /* 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) { struct socket_msg_list *ml; 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 */ ml = s->tx_list; @@ -251,16 +284,22 @@ tx_again: if (s->tx_list == NULL) s->tx_list_tail = &s->tx_list; free(ml); - work = 1; - goto tx_again; } else if (rc == 0 || errno != EAGAIN) { 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) @@ -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 && prim != PH_PRIM_DATA_IND && 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) - 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)) { - 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; } - if (s->connect <= 0) { - PDEBUG_CHAN(DPH, DEBUG_NOTICE, "Dropping message for socket, socket is closed!\n"); + if (s->connect_ofd.fd <= 0) { + LOGP(DPH, LOGL_NOTICE, "Dropping message for socket, socket is closed!\n"); 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 */ *s->tx_list_tail = tx_msg; s->tx_list_tail = &tx_msg->next; + s->connect_ofd.when |= BSC_FD_WRITE; } diff --git a/src/libph_socket/ph_socket.h b/src/libph_socket/ph_socket.h index 4bcfeee..97293c3 100644 --- a/src/libph_socket/ph_socket.h +++ b/src/libph_socket/ph_socket.h @@ -85,17 +85,17 @@ struct socket_msg_list { struct socket_msg msg; }; -#define SOCKET_RETRY_TIMER 2.0 +#define SOCKET_RETRY_TIMER 2 typedef struct ph_socket { const char *name; void (*ph_socket_rx_msg)(struct ph_socket *s, int channel, uint8_t prim, uint8_t *data, int length); void *priv; struct sockaddr_un sock_address; - int listen; /* socket to listen to incoming connections */ - int connect; /* socket of incoming connection */ - int connect_failed; /* used to print a failure only once */ - double connect_timer; /* time when to connect again */ + struct osmo_fd listen_ofd; /* socket to listen to incoming connections */ + struct osmo_fd connect_ofd; /* socket of incoming connection */ + int connect_failed; /* used to print a failure only once */ + struct osmo_timer_list retry_timer; /* timer to connect again */ struct socket_msg_list *tx_list, **tx_list_tail; struct socket_msg_list *rx_msg; 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); 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); -int ph_socket_work(ph_socket_t *s); - - diff --git a/src/libselect/Makefile.am b/src/libselect/Makefile.am new file mode 100644 index 0000000..76ff4d6 --- /dev/null +++ b/src/libselect/Makefile.am @@ -0,0 +1,6 @@ +AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) + +noinst_LIBRARIES = libselect.a + +libselect_a_SOURCES = \ + select.c diff --git a/src/libselect/select.c b/src/libselect/select.c new file mode 100644 index 0000000..3a4c0b1 --- /dev/null +++ b/src/libselect/select.c @@ -0,0 +1,168 @@ +/* Timer handling + * + * (C) 2023 by Andreas Eversberg + * All Rights Reserved + * + * Inspired by libosmocore + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include "select.h" + +//#define DEBUG + +#define MAX_OFD 1024 + +struct osmo_fd *ofd_list = NULL; +int ofd_changed = 0; + +int osmo_fd_register(struct osmo_fd *ofd) +{ + struct osmo_fd **ofdp; + + /* attach to list, if not already */ + ofdp = &ofd_list; + while (*ofdp) { + if (*ofdp == ofd) + break; + ofdp = &((*ofdp)->next); + } + if (!*ofdp) { +#ifdef DEBUG + fprintf(stderr, "%s: ofd=%p fd=%d registers.\n", __func__, ofd, ofd->fd); +#endif + ofd->next = NULL; + *ofdp = ofd; + ofd_changed = 1; + } + + return 0; +} + +void osmo_fd_unregister(struct osmo_fd *ofd) +{ + struct osmo_fd **ofdp; + + /* detach from list, if not already */ + ofdp = &ofd_list; + while (*ofdp) { + if (*ofdp == ofd) + break; + ofdp = &((*ofdp)->next); + } + if (*ofdp) { +#ifdef DEBUG + fprintf(stderr, "%s: ofd=%p fd=%d unregisters.\n", __func__, ofd, ofd->fd); +#endif + *ofdp = ofd->next; + ofd->next = NULL; + ofd_changed = 1; + } +} + +int osmo_fd_select(double timeout) +{ + fd_set readset; + fd_set writeset; + fd_set exceptset; + struct osmo_fd *ofd; + struct timeval tv; + int max_fd; + unsigned int what; + int work = 0; + int rc; + + /* init event sets */ + FD_ZERO(&readset); + FD_ZERO(&writeset); + FD_ZERO(&exceptset); + + /* populate event set with all file descriptios */ + ofd = ofd_list; + max_fd = 0; + while (ofd) { + if (ofd->fd > max_fd) + max_fd = ofd->fd; + if (ofd->when & OSMO_FD_READ) + FD_SET(ofd->fd, &readset); + if (ofd->when & OSMO_FD_WRITE) + FD_SET(ofd->fd, &writeset); + if (ofd->when & OSMO_FD_EXCEPT) + FD_SET(ofd->fd, &exceptset); + ofd = ofd->next; + } + + if (timeout >= 0) { + /* prepare timeout */ + tv.tv_sec = floor(timeout); + tv.tv_usec = (timeout - tv.tv_sec) * 1000000.0; + /* wait for event or timeout */ + rc = select(max_fd + 1, &readset, &writeset, &exceptset, &tv); + } else { + /* wait for event */ + rc = select(max_fd + 1, &readset, &writeset, &exceptset, NULL); + } + if (rc < 0) { + if (errno != EINTR) + fprintf(stderr, "%s: select() failed: '%d' with errno %d (%s) Please fix!\n", __func__, rc, errno, strerror(errno)); + return 0; + } + +again: + /* check the result and call handler */ + ofd_changed = 0; + ofd = ofd_list; + while (ofd) { + what = 0; + if (FD_ISSET(ofd->fd, &readset)) { +#ifdef DEBUG + fprintf(stderr, "%s: ofd=%p fd=%d get READ event.\n", __func__, ofd, ofd->fd); +#endif + what |= OSMO_FD_READ; + FD_CLR(ofd->fd, &readset); + } + if (FD_ISSET(ofd->fd, &writeset)) { +#ifdef DEBUG + fprintf(stderr, "%s: ofd=%p fd=%d get WRITE event.\n", __func__, ofd, ofd->fd); +#endif + what |= OSMO_FD_WRITE; + FD_CLR(ofd->fd, &writeset); + } + if (FD_ISSET(ofd->fd, &exceptset)) { +#ifdef DEBUG + fprintf(stderr, "%s: ofd=%p fd=%d get EXCEPTION event.\n", __func__, ofd, ofd->fd); +#endif + what |= OSMO_FD_EXCEPT; + FD_CLR(ofd->fd, &exceptset); + } + if (what) { + work = 1; + ofd->cb(ofd, what); + /* list has changed */ + if (ofd_changed) + goto again; + } + ofd = ofd->next; + } + + return work; +} + diff --git a/src/libselect/select.h b/src/libselect/select.h new file mode 100644 index 0000000..def1000 --- /dev/null +++ b/src/libselect/select.h @@ -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); + diff --git a/src/libtimer/timer.c b/src/libtimer/timer.c index 174533f..a5fa85c 100644 --- a/src/libtimer/timer.c +++ b/src/libtimer/timer.c @@ -26,6 +26,8 @@ #include #include "timer.h" +//#define DEBUG + static struct timer *timer_head = NULL; 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; } -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) { 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->fn = fn; - timer->priv = priv; + timer->cb = fn; + timer->data = priv; timer->next = NULL; *timer_tail_p = timer; timer_tail_p = &timer->next; timer->linked = 1; +#ifdef DEBUG + fprintf(stderr, "%s: timer=%p linked.\n", __func__, timer); +#endif } void timer_exit(struct timer *timer) @@ -64,6 +69,9 @@ void timer_exit(struct timer *timer) timer_tail_p = &((*timer_tail_p)->next); } timer->linked = 0; +#ifdef DEBUG + fprintf(stderr, "%s: timer=%p unlinked.\n", __func__, timer); +#endif } void timer_start(struct timer *timer, double duration) @@ -75,6 +83,9 @@ void timer_start(struct timer *timer, double duration) timer->duration = duration; timer->timeout = get_time() + duration; +#ifdef DEBUG + fprintf(stderr, "%s: timer=%p started %.3f seconds.\n", __func__, timer, duration); +#endif } void timer_stop(struct timer *timer) @@ -85,6 +96,9 @@ void timer_stop(struct timer *timer) } timer->timeout = 0; +#ifdef DEBUG + fprintf(stderr, "%s: timer=%p stopped.\n", __func__, timer); +#endif } int timer_running(struct timer *timer) @@ -97,23 +111,55 @@ int timer_running(struct timer *timer) return (timer->timeout != 0); } -void process_timer(void) +double process_timer(void) { struct timer *timer; - double now; + double now, timeout = -1.0; now = get_time(); again: timer = timer_head; - while (timer) { - if (timer->linked && timer->timeout > 0 && now >= timer->timeout) { - timer->timeout = 0; - timer->fn(timer); - goto again; + if (timer->linked && timer->timeout > 0) { + /* timeout, handle it, set timeout to 0 */ + if (now >= timer->timeout) { + timer->timeout = 0; +#ifdef DEBUG + fprintf(stderr, "%s: timer=%p fired.\n", __func__, timer); +#endif + if (!timer->cb) + abort(); + timer->cb(timer->data); + timeout = 0.0; + goto again; + } + /* in the future, set timeout to future */ + if (timeout < 0.0 || (timer->timeout - now) < timeout) + timeout = timer->timeout - now; } timer = timer->next; } + + return timeout; +} + +void osmo_timer_schedule(struct osmo_timer_list *ti, time_t sec, suseconds_t usec) +{ + if (!ti->linked) + timer_init(ti, ti->cb, ti->data); + timer_start(ti, (double)sec + (double)usec / 1000000.0); +} + +void osmo_timer_del(struct osmo_timer_list *ti) +{ + timer_exit(ti); +} + +int osmo_timer_pending(struct osmo_timer_list *ti) +{ + if (!ti->linked) + return 0; + return (ti->timeout != 0); } diff --git a/src/libtimer/timer.h b/src/libtimer/timer.h index 2073a8f..f7dbbbc 100644 --- a/src/libtimer/timer.h +++ b/src/libtimer/timer.h @@ -4,15 +4,20 @@ struct timer { int linked; /* set is timer is initialized and linked */ double duration; double timeout; - void (*fn)(struct timer *timer); - void *priv; + void (*cb)(void *data); + void *data; }; 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_start(struct timer *timer, double duration); void timer_stop(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);