aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/mgcp/mgcp_protocol.c
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-02-21 11:11:04 +0100
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-02-22 12:09:41 +0100
commit1b0ea97457e6f0c00ad34a44fe77d99668bf840c (patch)
tree3ab61b9e634d1a5a0001f1b679a051eea29f2412 /openbsc/src/mgcp/mgcp_protocol.c
parent6414a0cb223f5ec0651ff3423c7cf9f66d4e0909 (diff)
[mgcp] Move the network bits to a separate file...
This change separates the protocol from the actual network code (bind, forward data). This will allow to more easily hook up the RTP code from OpenBSC and to not use local sockets at all.
Diffstat (limited to 'openbsc/src/mgcp/mgcp_protocol.c')
-rw-r--r--openbsc/src/mgcp/mgcp_protocol.c190
1 files changed, 5 insertions, 185 deletions
diff --git a/openbsc/src/mgcp/mgcp_protocol.c b/openbsc/src/mgcp/mgcp_protocol.c
index f7588cd38..aaa9bc582 100644
--- a/openbsc/src/mgcp/mgcp_protocol.c
+++ b/openbsc/src/mgcp/mgcp_protocol.c
@@ -30,9 +30,6 @@
#include <limits.h>
#include <unistd.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-
#include <openbsc/debug.h>
#include <openbsc/msgb.h>
#include <openbsc/talloc.h>
@@ -41,8 +38,6 @@
#include <openbsc/mgcp.h>
#include <openbsc/mgcp_internal.h>
-#warning "Make use of the rtp proxy code"
-
enum mgcp_connection_mode {
MGCP_CONN_NONE = 0,
MGCP_CONN_RECV_ONLY = 1,
@@ -50,16 +45,6 @@ enum mgcp_connection_mode {
MGCP_CONN_RECV_SEND = MGCP_CONN_RECV_ONLY | MGCP_CONN_SEND_ONLY,
};
-enum {
- DEST_NETWORK = 0,
- DEST_BTS = 1,
-};
-
-enum {
- PROTO_RTP,
- PROTO_RTCP,
-};
-
/**
* Macro for tokenizing MGCP messages and SDP in one go.
*
@@ -140,168 +125,6 @@ static unsigned int generate_transaction_id()
return abs(rand());
}
-static int udp_send(int fd, struct in_addr *addr, int port, char *buf, int len)
-{
- struct sockaddr_in out;
- out.sin_family = AF_INET;
- out.sin_port = port;
- memcpy(&out.sin_addr, addr, sizeof(*addr));
-
- return sendto(fd, buf, len, 0, (struct sockaddr *)&out, sizeof(out));
-}
-
-/*
- * There is data coming. We will have to figure out if it
- * came from the BTS or the MediaGateway of the MSC. On top
- * of that we need to figure out if it was RTP or RTCP.
- *
- * Currently we do not communicate with the BSC so we have
- * no idea where the BTS is listening for RTP and need to
- * do the classic routing trick. Wait for the first packet
- * from the BTS and then go ahead.
- */
-static int rtp_data_cb(struct bsc_fd *fd, unsigned int what)
-{
- char buf[4096];
- struct sockaddr_in addr;
- socklen_t slen = sizeof(addr);
- struct mgcp_endpoint *endp;
- struct mgcp_config *cfg;
- int rc, dest, proto;
-
- endp = (struct mgcp_endpoint *) fd->data;
- cfg = endp->cfg;
-
- rc = recvfrom(fd->fd, &buf, sizeof(buf), 0,
- (struct sockaddr *) &addr, &slen);
- if (rc < 0) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to receive message on: 0x%x\n",
- ENDPOINT_NUMBER(endp));
- return -1;
- }
-
- /* do not forward aynthing... maybe there is a packet from the bts */
- if (endp->ci == CI_UNUSED) {
- LOGP(DMGCP, LOGL_ERROR, "Unknown message on endpoint: 0x%x\n", ENDPOINT_NUMBER(endp));
- return -1;
- }
-
- /*
- * Figure out where to forward it to. This code assumes that we
- * have received the Connection Modify and know who is a legitimate
- * partner. According to the spec we could attempt to forward even
- * after the Create Connection but we will not as we are not really
- * able to tell if this is legitimate.
- */
- #warning "Slight spec violation. With connection mode recvonly we should attempt to forward."
- dest = memcmp(&addr.sin_addr, &endp->remote, sizeof(addr.sin_addr)) == 0 &&
- (endp->net_rtp == addr.sin_port || endp->net_rtcp == addr.sin_port)
- ? DEST_BTS : DEST_NETWORK;
- proto = fd == &endp->local_rtp ? PROTO_RTP : PROTO_RTCP;
-
- /* We have no idea who called us, maybe it is the BTS. */
- if (dest == DEST_NETWORK && (endp->bts_rtp == 0 || cfg->forward_ip)) {
- /* it was the BTS... */
- if (!cfg->bts_ip || memcmp(&addr.sin_addr, &cfg->bts_in, sizeof(cfg->bts_in)) == 0) {
- if (fd == &endp->local_rtp) {
- endp->bts_rtp = addr.sin_port;
- } else {
- endp->bts_rtcp = addr.sin_port;
- }
-
- endp->bts = addr.sin_addr;
- LOGP(DMGCP, LOGL_NOTICE, "Found BTS for endpoint: 0x%x on port: %d/%d\n",
- ENDPOINT_NUMBER(endp), ntohs(endp->bts_rtp), ntohs(endp->bts_rtcp));
- }
- }
-
- /* dispatch */
- if (cfg->audio_loop)
- dest = !dest;
-
- if (dest == DEST_NETWORK) {
- return udp_send(fd->fd, &endp->remote,
- proto == PROTO_RTP ? endp->net_rtp : endp->net_rtcp,
- buf, rc);
- } else {
- return udp_send(fd->fd, &endp->bts,
- proto == PROTO_RTP ? endp->bts_rtp : endp->bts_rtcp,
- buf, rc);
- }
-}
-
-static int create_bind(const char *source_addr, struct bsc_fd *fd, int port)
-{
- struct sockaddr_in addr;
- int on = 1;
-
- fd->fd = socket(AF_INET, SOCK_DGRAM, 0);
- if (fd->fd < 0) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to create UDP port.\n");
- return -1;
- }
-
- setsockopt(fd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
- inet_aton(source_addr, &addr.sin_addr);
-
- if (bind(fd->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- return -1;
- }
-
- return 0;
-}
-
-static int bind_rtp(struct mgcp_endpoint *endp)
-{
- struct mgcp_config *cfg = endp->cfg;
-
- if (create_bind(cfg->source_addr, &endp->local_rtp, endp->rtp_port) != 0) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to create RTP port: %s:%d on 0x%x\n",
- cfg->source_addr, endp->rtp_port, ENDPOINT_NUMBER(endp));
- goto cleanup0;
- }
-
- if (create_bind(cfg->source_addr, &endp->local_rtcp, endp->rtp_port + 1) != 0) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to create RTCP port: %s:%d on 0x%x\n",
- cfg->source_addr, endp->rtp_port + 1, ENDPOINT_NUMBER(endp));
- goto cleanup1;
- }
-
- endp->local_rtp.cb = rtp_data_cb;
- endp->local_rtp.data = endp;
- endp->local_rtp.when = BSC_FD_READ;
- if (bsc_register_fd(&endp->local_rtp) != 0) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to register RTP port %d on 0x%x\n",
- endp->rtp_port, ENDPOINT_NUMBER(endp));
- goto cleanup2;
- }
-
- endp->local_rtcp.cb = rtp_data_cb;
- endp->local_rtcp.data = endp;
- endp->local_rtcp.when = BSC_FD_READ;
- if (bsc_register_fd(&endp->local_rtcp) != 0) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to register RTCP port %d on 0x%x\n",
- endp->rtp_port + 1, ENDPOINT_NUMBER(endp));
- goto cleanup3;
- }
-
- return 0;
-
-cleanup3:
- bsc_unregister_fd(&endp->local_rtp);
-cleanup2:
- close(endp->local_rtcp.fd);
- endp->local_rtcp.fd = -1;
-cleanup1:
- close(endp->local_rtp.fd);
- endp->local_rtp.fd = -1;
-cleanup0:
- return -1;
-}
-
/*
* array of function pointers for handling various
* messages. In the future this might be binary sorted
@@ -575,6 +398,7 @@ static struct msgb *handle_create_con(struct mgcp_config *cfg, struct msgb *msg)
const char *trans_id;
struct mgcp_endpoint *endp;
int error_code = 500;
+ int port;
found = analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp);
if (found != 0)
@@ -618,8 +442,10 @@ static struct msgb *handle_create_con(struct mgcp_config *cfg, struct msgb *msg)
memset(&endp->remote, 0, sizeof(endp->remote));
/* bind to the port now */
- endp->rtp_port = rtp_calculate_port(ENDPOINT_NUMBER(endp), cfg->rtp_base_port);
- if (!cfg->early_bind && bind_rtp(endp) != 0)
+ port = rtp_calculate_port(ENDPOINT_NUMBER(endp), cfg->rtp_base_port);
+ if (cfg->early_bind)
+ endp->rtp_port = port;
+ else if (mgcp_bind_rtp_port(endp, port) != 0)
goto error2;
/* assign a local call identifier or fail */
@@ -841,9 +667,3 @@ int mgcp_endpoints_allocate(struct mgcp_config *cfg)
return 0;
}
-
-int mgcp_bind_rtp_port(struct mgcp_endpoint *endp, int rtp_port)
-{
- endp->rtp_port = rtp_port;
- return bind_rtp(endp);
-}