Initially implement the new osmo-mgw and libosmo-mgcp
Leave the old osmo-bsc_mgcp and libosmo-legacy-mgcp as it is; on a copy thereof
(added by a previous commit), apply changes to initially implement the new
osmo-mgw.
Adjust build system and debian packaging to accomodate the new libosmo-mgcp and
osmo-mgw.
The main differences:
*) use a list to manage rtp connections.
Aggregate all rtp related information inside a single struct.
Use a linked list to manage the both connections (net and bts).
The idea behind using a list is that we might support conference
calls at some later point.
Store the linked list in struct mgcp_endpoint, have a private linked
list for each endpoint. The list contains connection items which are
implemented in struct mgcp_conn. A connection is allocated and freed
using the functions in mgcp_conn.c. A connection is allocated on the
reception of a CRCX command and freed with the reception of a DLCX
command.
*) remove external transcoder feature
Fortunatelly the external transcoder feature is not needed
anymore. This patch removes the related code.
*) vty: get rid of CONN_BTS and CONN_NET
Since the new connection model does not make a difference
between BTS and NET connections the VTY should not use
the fixed CONN_BTS and CONN_NET constants.
- Handle the conns list inside the endpoint directly
- introduce function to dump basic rtp connection info
- introduce human readable names for connections
Parts of the code adjusted to use generalized connections instead of explicit
BTS/NET ones:
- teach mgcp_send_dummy() to send dummy packets to any RTP connection
- network: generalize mgcp_bind_net/bts_rtp_port()
- network: generalize mgcp_send()
- tap: generalize call tapping feature
- stat: generalize statistics
- Replace rtp_data_net() and rtp_data_bts() with generalized rtp_data_rx()
*) mgcp_protocol.c fixes:
- check ci string before it is converted:
In case of missing ci, a nullpointer is delivered to strtoul().
Add a function that takes ci, checks it and converts it to an
uint32_t. Use the return code to react on missing ci.
- output error message on missing CI.
- when parsing the mode, print log message when mode is missing.
- use mode_orig when mode is missing.
- fix ptime formatstring to use %u rather than %d.
- cosmetic: log when connection is deleted on DLCX.
- change loglevels of CRCX, MDCX, DLCX events from DEBUG to NOTICE.
*) mgcp_test
- apply rename of strline_r() to mgcp_strline().
- MGCP command macros:
- Add 'I: 1' parameters.
- Use proper port numbers:
from m=audio 0 RTP/AVP 126
to m=audio 16002 RTP/AVP 128
- Change ptime to 'a=ptime:40' because this is what the MGW currently
returns. CRCX generally feed a ptime:40 and this is expected to be
returned.
- struct mgcp_test: Use only one ptype, there are no explicit BTS and NET
endpoints anymore.
Hence remove one column from tests[].
- test_messages():
- Enable: remove '#if 0'
- Remove concept of BTS and NET endpoints: test only one conn, as they are
now interchangeable anyway.
- remove endpoint init, now done internally.
- add false asserts in error cases.
- test_retransmission():
- remove endpoint init, now done internally.
- add false asserts in error cases.
- test_packet_error_detection():
- Remove concept of BTS and NET endpoints: test only one conn, as they are
now interchangeable anyway. Use arbitrary conn ids (e.g. 4711).
- remove endpoint init, now done internally.
- add false assert in error case.
- Assert that a conn really vanishes on DLCX, previously the conn would
remain and just be unused, now it is actually discarded.
- test_no_cycle()
- Remove concept of BTS and NET endpoints: test only one conn, as they are
now interchangeable anyway. Use arbitrary conn ids (e.g. 4711).
- test_no_name()
- Enable: remove '#if 0'.
- remove endpoint init, now done internally.
- add false assert in error case.
- mgcp_test.ok: adjust expected results to status quo:
- We now see two dummy packets instead of one, now sent to both sides because
we don't know of BTS or NET side. (maybe drop dummy packets later...)
- packet duration, conn mode: now sane defaults show instead of unset.
- various whitespace and formatting changes from lindent.
Change-Id: Ie008599136c7ed8a0dfbb0cf803188975a499fc5
diff --git a/src/libosmo-mgcp/mgcp_osmux.c b/src/libosmo-mgcp/mgcp_osmux.c
index 743d3f9..60ffe06 100644
--- a/src/libosmo-mgcp/mgcp_osmux.c
+++ b/src/libosmo-mgcp/mgcp_osmux.c
@@ -20,9 +20,10 @@
#include <osmocom/netif/osmux.h>
#include <osmocom/netif/rtp.h>
-#include <osmocom/legacy_mgcp/mgcp.h>
-#include <osmocom/legacy_mgcp/mgcp_internal.h>
-#include <osmocom/legacy_mgcp/osmux.h>
+#include <osmocom/mgcp/mgcp.h>
+#include <osmocom/mgcp/mgcp_internal.h>
+#include <osmocom/mgcp/osmux.h>
+#include <osmocom/mgcp/mgcp_conn.h>
static struct osmo_fd osmux_fd;
@@ -38,7 +39,8 @@
static void *osmux;
-static void osmux_deliver(struct msgb *batch_msg, void *data)
+/* Deliver OSMUX batch to the remote end */
+static void osmux_deliver_cb(struct msgb *batch_msg, void *data)
{
struct osmux_handle *handle = data;
struct sockaddr_in out = {
@@ -52,12 +54,12 @@
msgb_free(batch_msg);
}
+/* Lookup existing OSMUX handle for specified destination address. */
static struct osmux_handle *
osmux_handle_find_get(struct in_addr *addr, int rem_port)
{
struct osmux_handle *h;
- /* Lookup for existing OSMUX handle for this destination address. */
llist_for_each_entry(h, &osmux_handle_list, head) {
if (memcmp(&h->rem_addr, addr, sizeof(struct in_addr)) == 0 &&
h->rem_port == rem_port) {
@@ -72,11 +74,11 @@
return NULL;
}
+/* Put down no longer needed OSMUX handle */
static void osmux_handle_put(struct osmux_in_handle *in)
{
struct osmux_handle *h;
- /* Lookup for existing OSMUX handle for this destination address. */
llist_for_each_entry(h, &osmux_handle_list, head) {
if (h->in == in) {
if (--h->refcnt == 0) {
@@ -101,6 +103,7 @@
LOGP(DLMGCP, LOGL_ERROR, "cannot find Osmux input handle %p\n", in);
}
+/* Allocate free OSMUX handle */
static struct osmux_handle *
osmux_handle_alloc(struct mgcp_config *cfg, struct in_addr *addr, int rem_port)
{
@@ -119,11 +122,14 @@
return NULL;
}
- h->in->osmux_seq = 0; /* sequence number to start OSmux message from */
+ /* sequence number to start OSMUX message from */
+ h->in->osmux_seq = 0;
+
h->in->batch_factor = cfg->osmux_batch;
+
/* If batch size is zero, the library defaults to 1470 bytes. */
h->in->batch_size = cfg->osmux_batch_size;
- h->in->deliver = osmux_deliver;
+ h->in->deliver = osmux_deliver_cb;
osmux_xfrm_input_init(h->in);
h->in->data = h;
@@ -135,6 +141,8 @@
return h;
}
+/* Lookup existing handle for a specified address, if the handle can not be
+ * foud a the function will automatically allocate one */
static struct osmux_in_handle *
osmux_handle_lookup(struct mgcp_config *cfg, struct in_addr *addr, int rem_port)
{
@@ -151,47 +159,60 @@
return h->in;
}
-int osmux_xfrm_to_osmux(int type, char *buf, int rc, struct mgcp_endpoint *endp)
+/*! send RTP packet through OSMUX connection.
+ * \param[in] buf rtp data
+ * \param[in] buf_len length of rtp data
+ * \param[in] conn associated RTP connection
+ * \returns 0 on success, -1 on ERROR */
+int osmux_xfrm_to_osmux(char *buf, int buf_len, struct mgcp_conn_rtp *conn)
{
int ret;
struct msgb *msg;
msg = msgb_alloc(4096, "RTP");
if (!msg)
- return 0;
+ return -1;
- memcpy(msg->data, buf, rc);
- msgb_put(msg, rc);
+ memcpy(msg->data, buf, buf_len);
+ msgb_put(msg, buf_len);
- while ((ret = osmux_xfrm_input(endp->osmux.in, msg, endp->osmux.cid)) > 0) {
+ while ((ret = osmux_xfrm_input(conn->osmux.in, msg, conn->osmux.cid)) > 0) {
/* batch full, build and deliver it */
- osmux_xfrm_input_deliver(endp->osmux.in);
+ osmux_xfrm_input_deliver(conn->osmux.in);
}
return 0;
}
+/* Lookup the endpoint that corresponds to the specified address (port) */
static struct mgcp_endpoint *
endpoint_lookup(struct mgcp_config *cfg, int cid,
struct in_addr *from_addr, int type)
{
- struct mgcp_endpoint *tmp = NULL;
+ struct mgcp_endpoint *endp = NULL;
int i;
+ struct mgcp_conn_rtp *conn_net = NULL;
+ struct mgcp_conn_rtp *conn_bts = NULL;
- /* Lookup for the endpoint that corresponds to this port */
for (i=0; i<cfg->trunk.number_endpoints; i++) {
struct in_addr *this;
- tmp = &cfg->trunk.endpoints[i];
+ endp = &cfg->trunk.endpoints[i];
+#if 0
if (!tmp->allocated)
continue;
+#endif
switch(type) {
case MGCP_DEST_NET:
- this = &tmp->net_end.addr;
+ /* FIXME: Get rid of CONN_ID_XXX! */
+ conn_net = mgcp_conn_get_rtp(endp, CONN_ID_NET);
+ this = &conn_net->end.addr;
break;
case MGCP_DEST_BTS:
- this = &tmp->bts_end.addr;
+ /* FIXME: Get rid of CONN_ID_XXX! */
+ conn_bts = mgcp_conn_get_rtp(endp, CONN_ID_BTS);
+ this = &conn_bts->end.addr;
break;
default:
/* Should not ever happen */
@@ -199,8 +220,10 @@
return NULL;
}
- if (tmp->osmux.cid == cid && this->s_addr == from_addr->s_addr)
- return tmp;
+ /* FIXME: Get rid of CONN_ID_XXX! */
+ conn_net = mgcp_conn_get_rtp(endp, CONN_ID_NET);
+ if (conn_net->osmux.cid == cid && this->s_addr == from_addr->s_addr)
+ return endp;
}
LOGP(DLMGCP, LOGL_ERROR, "Cannot find endpoint with cid=%d\n", cid);
@@ -211,30 +234,54 @@
static void scheduled_tx_net_cb(struct msgb *msg, void *data)
{
struct mgcp_endpoint *endp = data;
+ struct mgcp_conn_rtp *conn_net = NULL;
+ struct mgcp_conn_rtp *conn_bts = NULL;
+
+ /* FIXME: Get rid of CONN_ID_XXX! */
+ conn_bts = mgcp_conn_get_rtp(endp, CONN_ID_BTS);
+ conn_net = mgcp_conn_get_rtp(endp, CONN_ID_NET);
+ if (!conn_bts || !conn_net)
+ return;
+
struct sockaddr_in addr = {
- .sin_addr = endp->net_end.addr,
- .sin_port = endp->net_end.rtp_port,
+ .sin_addr = conn_net->end.addr,
+ .sin_port = conn_net->end.rtp_port,
};
- endp->bts_end.octets += msg->len;
- endp->bts_end.packets++;
+ conn_bts->end.octets_tx += msg->len;
+ conn_bts->end.packets_tx++;
- mgcp_send(endp, MGCP_DEST_NET, 1, &addr, (char *)msg->data, msg->len);
+ /* Send RTP data to NET */
+ /* FIXME: Get rid of conn_bts and conn_net! */
+ mgcp_send(endp, 1, &addr, (char *)msg->data, msg->len,
+ conn_bts, conn_net);
msgb_free(msg);
}
static void scheduled_tx_bts_cb(struct msgb *msg, void *data)
{
struct mgcp_endpoint *endp = data;
+ struct mgcp_conn_rtp *conn_net = NULL;
+ struct mgcp_conn_rtp *conn_bts = NULL;
+
+ /* FIXME: Get rid of CONN_ID_XXX! */
+ conn_bts = mgcp_conn_get_rtp(endp, CONN_ID_BTS);
+ conn_net = mgcp_conn_get_rtp(endp, CONN_ID_NET);
+ if (!conn_bts || !conn_net)
+ return;
+
struct sockaddr_in addr = {
- .sin_addr = endp->bts_end.addr,
- .sin_port = endp->bts_end.rtp_port,
+ .sin_addr = conn_bts->end.addr,
+ .sin_port = conn_bts->end.rtp_port,
};
- endp->net_end.octets += msg->len;
- endp->net_end.packets++;
+ conn_net->end.octets_tx += msg->len;
+ conn_net->end.packets_tx++;
- mgcp_send(endp, MGCP_DEST_BTS, 1, &addr, (char *)msg->data, msg->len);
+ /* Send RTP data to BTS */
+ /* FIXME: Get rid of conn_bts and conn_net! */
+ mgcp_send(endp, 1, &addr, (char *)msg->data, msg->len,
+ conn_net, conn_bts);
msgb_free(msg);
}
@@ -271,6 +318,7 @@
struct sockaddr_in addr;
struct mgcp_config *cfg = ofd->data;
uint32_t rem;
+ struct mgcp_conn_rtp *conn_net = NULL;
msg = osmux_recv(ofd, &addr);
if (!msg)
@@ -287,17 +335,23 @@
/* Yes, we use MGCP_DEST_NET to locate the origin */
endp = endpoint_lookup(cfg, osmuxh->circuit_id,
&addr.sin_addr, MGCP_DEST_NET);
+
+ /* FIXME: Get rid of CONN_ID_XXX! */
+ conn_net = mgcp_conn_get_rtp(endp, CONN_ID_NET);
+ if (!conn_net)
+ goto out;
+
if (!endp) {
LOGP(DLMGCP, LOGL_ERROR,
"Cannot find an endpoint for circuit_id=%d\n",
osmuxh->circuit_id);
goto out;
}
- endp->osmux.stats.octets += osmux_chunk_length(msg, rem);
- endp->osmux.stats.chunks++;
+ conn_net->osmux.stats.octets += osmux_chunk_length(msg, rem);
+ conn_net->osmux.stats.chunks++;
rem = msg->len;
- osmux_xfrm_output(osmuxh, &endp->osmux.out, &list);
+ osmux_xfrm_output(osmuxh, &conn_net->osmux.out, &list);
osmux_tx_sched(&list, scheduled_tx_bts_cb, endp);
}
out:
@@ -311,6 +365,7 @@
{
struct mgcp_endpoint *endp;
uint8_t osmux_cid;
+ struct mgcp_conn_rtp *conn_net = NULL;
if (msg->len < 1 + sizeof(osmux_cid)) {
LOGP(DLMGCP, LOGL_ERROR,
@@ -337,10 +392,14 @@
goto out;
}
- if (endp->osmux.state == OSMUX_STATE_ENABLED)
+ conn_net = mgcp_conn_get_rtp(endp, CONN_ID_NET);
+ if (!conn_net)
goto out;
- if (osmux_enable_endpoint(endp, &addr->sin_addr, addr->sin_port) < 0 ) {
+ if (conn_net->osmux.state == OSMUX_STATE_ENABLED)
+ goto out;
+
+ if (osmux_enable_conn(endp, conn_net, &addr->sin_addr, addr->sin_port) < 0 ) {
LOGP(DLMGCP, LOGL_ERROR,
"Could not enable osmux in endpoint %d\n",
ENDPOINT_NUMBER(endp));
@@ -363,6 +422,7 @@
struct sockaddr_in addr;
struct mgcp_config *cfg = ofd->data;
uint32_t rem;
+ struct mgcp_conn_rtp *conn_net = NULL;
msg = osmux_recv(ofd, &addr);
if (!msg)
@@ -379,17 +439,23 @@
/* Yes, we use MGCP_DEST_BTS to locate the origin */
endp = endpoint_lookup(cfg, osmuxh->circuit_id,
&addr.sin_addr, MGCP_DEST_BTS);
+
+ /* FIXME: Get rid of CONN_ID_XXX! */
+ conn_net = mgcp_conn_get_rtp(endp, CONN_ID_NET);
+ if (!conn_net)
+ goto out;
+
if (!endp) {
LOGP(DLMGCP, LOGL_ERROR,
"Cannot find an endpoint for circuit_id=%d\n",
osmuxh->circuit_id);
goto out;
}
- endp->osmux.stats.octets += osmux_chunk_length(msg, rem);
- endp->osmux.stats.chunks++;
+ conn_net->osmux.stats.octets += osmux_chunk_length(msg, rem);
+ conn_net->osmux.stats.chunks++;
rem = msg->len;
- osmux_xfrm_output(osmuxh, &endp->osmux.out, &list);
+ osmux_xfrm_output(osmuxh, &conn_net->osmux.out, &list);
osmux_tx_sched(&list, scheduled_tx_net_cb, endp);
}
out:
@@ -432,116 +498,155 @@
return 0;
}
-int osmux_enable_endpoint(struct mgcp_endpoint *endp, struct in_addr *addr, uint16_t port)
+/*! enable OSXMUX circuit for a specified connection.
+ * \param[in] endp mgcp endpoint (configuration)
+ * \param[in] conn connection to disable
+ * \param[in] addr IP address of remote OSMUX endpoint
+ * \param[in] port portnumber of the remote OSMUX endpoint
+ * \returns 0 on success, -1 on ERROR */
+int osmux_enable_conn(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn,
+ struct in_addr *addr, uint16_t port)
{
- /* If osmux is enabled, initialize the output handler. This handler is
- * used to reconstruct the RTP flow from osmux. The RTP SSRC is
- * allocated based on the circuit ID (endp->osmux.cid), which is unique
- * in the local scope to the BSC/BSC-NAT. We use it to divide the RTP
- * SSRC space (2^32) by the 256 possible circuit IDs, then randomly
- * select one value from that window. Thus, we have no chance to have
- * overlapping RTP SSRC traveling to the BTSes behind the BSC,
- * similarly, for flows traveling to the MSC.
+ /*! If osmux is enabled, initialize the output handler. This handler is
+ * used to reconstruct the RTP flow from osmux. The RTP SSRC is
+ * allocated based on the circuit ID (conn_net->osmux.cid), which is unique
+ * in the local scope to the BSC/BSC-NAT. We use it to divide the RTP
+ * SSRC space (2^32) by the 256 possible circuit IDs, then randomly
+ * select one value from that window. Thus, we have no chance to have
+ * overlapping RTP SSRC traveling to the BTSes behind the BSC,
+ * similarly, for flows traveling to the MSC.
*/
static const uint32_t rtp_ssrc_winlen = UINT32_MAX / 256;
+ uint16_t osmux_dummy = endp->cfg->osmux_dummy;
- if (endp->osmux.state == OSMUX_STATE_DISABLED) {
- LOGP(DLMGCP, LOGL_ERROR, "Endpoint %u didn't request Osmux\n",
- ENDPOINT_NUMBER(endp));
+ /* Check if osmux is enabled for the specified connection */
+ if (conn->osmux.state == OSMUX_STATE_DISABLED) {
+ LOGP(DLMGCP, LOGL_ERROR, "OSMUX not enabled for conn:%s\n",
+ mgcp_conn_dump(conn->conn));
return -1;
}
- osmux_xfrm_output_init(&endp->osmux.out,
- (endp->osmux.cid * rtp_ssrc_winlen) +
+ osmux_xfrm_output_init(&conn->osmux.out,
+ (conn->osmux.cid * rtp_ssrc_winlen) +
(random() % rtp_ssrc_winlen));
- endp->osmux.in = osmux_handle_lookup(endp->cfg, addr, port);
- if (!endp->osmux.in) {
- LOGP(DLMGCP, LOGL_ERROR, "Cannot allocate input osmux handle\n");
+ conn->osmux.in = osmux_handle_lookup(endp->cfg, addr, port);
+ if (!conn->osmux.in) {
+ LOGP(DLMGCP, LOGL_ERROR, "Cannot allocate input osmux handle for conn:%s\n",
+ mgcp_conn_dump(conn->conn));
return -1;
}
- if (!osmux_xfrm_input_open_circuit(endp->osmux.in, endp->osmux.cid,
- endp->cfg->osmux_dummy)) {
- LOGP(DLMGCP, LOGL_ERROR, "Cannot open osmux circuit %u\n",
- endp->osmux.cid);
+ if (!osmux_xfrm_input_open_circuit(conn->osmux.in, conn->osmux.cid, osmux_dummy)) {
+ LOGP(DLMGCP, LOGL_ERROR, "Cannot open osmux circuit %u for conn:%s\n",
+ conn->osmux.cid, mgcp_conn_dump(conn->conn));
return -1;
}
switch (endp->cfg->role) {
case MGCP_BSC_NAT:
- endp->type = MGCP_OSMUX_BSC_NAT;
+ conn->type = MGCP_OSMUX_BSC_NAT;
break;
case MGCP_BSC:
- endp->type = MGCP_OSMUX_BSC;
+ conn->type = MGCP_OSMUX_BSC;
break;
}
- endp->osmux.state = OSMUX_STATE_ENABLED;
+
+ conn->osmux.state = OSMUX_STATE_ENABLED;
return 0;
}
-void osmux_disable_endpoint(struct mgcp_endpoint *endp)
+/*! disable OSXMUX circuit for a specified connection.
+ * \param[in] conn connection to disable */
+void osmux_disable_conn(struct mgcp_conn_rtp *conn)
{
- LOGP(DLMGCP, LOGL_INFO, "Releasing endpoint %u using Osmux CID %u\n",
- ENDPOINT_NUMBER(endp), endp->osmux.cid);
- osmux_xfrm_input_close_circuit(endp->osmux.in, endp->osmux.cid);
- endp->osmux.state = OSMUX_STATE_DISABLED;
- endp->osmux.cid = -1;
- osmux_handle_put(endp->osmux.in);
+ if (!conn)
+ return;
+
+ if (conn->osmux.state != OSMUX_STATE_ENABLED)
+ return;
+
+ LOGP(DLMGCP, LOGL_INFO, "Releasing connection %u using Osmux CID %u\n",
+ conn->conn->id, conn->osmux.cid);
+ osmux_xfrm_input_close_circuit(conn->osmux.in, conn->osmux.cid);
+ conn->osmux.state = OSMUX_STATE_DISABLED;
+ conn->osmux.cid = -1;
+ osmux_handle_put(conn->osmux.in);
}
-void osmux_release_cid(struct mgcp_endpoint *endp)
+/*! relase OSXMUX cid, that had been allocated to this connection.
+ * \param[in] conn connection with OSMUX cid to release */
+void osmux_release_cid(struct mgcp_conn_rtp *conn)
{
- if (endp->osmux.allocated_cid >= 0)
- osmux_put_cid(endp->osmux.allocated_cid);
- endp->osmux.allocated_cid = -1;
+ if (!conn)
+ return;
+
+ if (conn->osmux.state != OSMUX_STATE_ENABLED)
+ return;
+
+ if (conn->osmux.allocated_cid >= 0)
+ osmux_put_cid(conn->osmux.allocated_cid);
+ conn->osmux.allocated_cid = -1;
}
-void osmux_allocate_cid(struct mgcp_endpoint *endp)
+/*! allocate OSXMUX cid to connection.
+ * \param[in] conn connection for which we allocate the OSMUX cid*/
+void osmux_allocate_cid(struct mgcp_conn_rtp *conn)
{
- osmux_release_cid(endp);
- endp->osmux.allocated_cid = osmux_get_cid();
+ osmux_release_cid(conn);
+ conn->osmux.allocated_cid = osmux_get_cid();
}
-/* We don't need to send the dummy load for osmux so often as another endpoint
- * may have already punched the hole in the firewall. This approach is simple
- * though.
- */
-int osmux_send_dummy(struct mgcp_endpoint *endp)
+/*! send RTP dummy packet to OSMUX connection port.
+ * \param[in] endp mcgp endpoint that holds the RTP connection
+ * \param[in] conn associated RTP connection
+ * \returns bytes sent, -1 on error */
+int osmux_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn)
{
char buf[1 + sizeof(uint8_t)];
struct in_addr addr_unset = {};
+ /*! The dummy packet will not be sent via the actual OSMUX connection,
+ * instead it is sent out of band to port where the remote OSMUX
+ * multplexer is listening. The goal is to ensure that the connection
+ * is kept open */
+
+ /*! We don't need to send the dummy load for osmux so often as another
+ * endpoint may have already punched the hole in the firewall. This
+ * approach is simple though. */
+
buf[0] = MGCP_DUMMY_LOAD;
- memcpy(&buf[1], &endp->osmux.cid, sizeof(endp->osmux.cid));
+ memcpy(&buf[1], &conn->osmux.cid, sizeof(conn->osmux.cid));
/* Wait until we have the connection information from MDCX */
- if (memcmp(&endp->net_end.addr, &addr_unset, sizeof(addr_unset)) == 0)
+ if (memcmp(&conn->end.addr, &addr_unset, sizeof(addr_unset)) == 0)
return 0;
- if (endp->osmux.state == OSMUX_STATE_ACTIVATING) {
- if (osmux_enable_endpoint(endp, &endp->net_end.addr,
- htons(endp->cfg->osmux_port)) < 0) {
+ if (conn->osmux.state == OSMUX_STATE_ACTIVATING) {
+ if (osmux_enable_conn(endp, conn, &conn->end.addr,
+ htons(endp->cfg->osmux_port)) < 0) {
LOGP(DLMGCP, LOGL_ERROR,
- "Could not activate osmux in endpoint %d\n",
- ENDPOINT_NUMBER(endp));
+ "Could not activate osmux for conn:%s\n",
+ mgcp_conn_dump(conn->conn));
}
LOGP(DLMGCP, LOGL_ERROR,
"Osmux CID %u for %s:%u is now enabled\n",
- endp->osmux.cid, inet_ntoa(endp->net_end.addr),
+ conn->osmux.cid, inet_ntoa(conn->end.addr),
endp->cfg->osmux_port);
}
LOGP(DLMGCP, LOGL_DEBUG,
"sending OSMUX dummy load to %s CID %u\n",
- inet_ntoa(endp->net_end.addr), endp->osmux.cid);
+ inet_ntoa(conn->end.addr), conn->osmux.cid);
- return mgcp_udp_send(osmux_fd.fd, &endp->net_end.addr,
+ return mgcp_udp_send(osmux_fd.fd, &conn->end.addr,
htons(endp->cfg->osmux_port), buf, sizeof(buf));
}
-/* bsc-nat allocates/releases the Osmux circuit ID */
+/*! bsc-nat allocates/releases the OSMUX cids (Circuit IDs). */
static uint8_t osmux_cid_bitmap[(OSMUX_CID_MAX + 1) / 8];
+/*! count the number of taken OSMUX cids.
+ * \returns number of OSMUX cids in use */
int osmux_used_cid(void)
{
int i, j, used = 0;
@@ -556,6 +661,8 @@
return used;
}
+/*! take a free OSMUX cid.
+ * \returns OSMUX cid */
int osmux_get_cid(void)
{
int i, j;
@@ -576,6 +683,8 @@
return -1;
}
+/*! put back a no longer used OSMUX cid.
+ * \param[in] osmux_cid OSMUX cid */
void osmux_put_cid(uint8_t osmux_cid)
{
LOGP(DLMGCP, LOGL_DEBUG, "Osmux CID %u is back to the pool\n", osmux_cid);