diff options
author | Holger Hans Peter Freyther <zecke@selfish.org> | 2010-09-20 02:59:25 +0800 |
---|---|---|
committer | Holger Hans Peter Freyther <zecke@selfish.org> | 2010-09-20 02:59:25 +0800 |
commit | af8a0104481846858bfe3ada9ddf3a2a42c38818 (patch) | |
tree | e74d583fa34f24095056cec9922db58db88a9978 /openbsc/src/mgcp/mgcp_protocol.c | |
parent | e02860af0011e968dd21c33fa65aee8e106dab7e (diff) | |
parent | 9aa8a9c5a7f35770582bdb6d564f13caf852f91d (diff) |
Merge branch 'zecke/mgcp-transcoder'openbsc/0.9.8
Diffstat (limited to 'openbsc/src/mgcp/mgcp_protocol.c')
-rw-r--r-- | openbsc/src/mgcp/mgcp_protocol.c | 142 |
1 files changed, 134 insertions, 8 deletions
diff --git a/openbsc/src/mgcp/mgcp_protocol.c b/openbsc/src/mgcp/mgcp_protocol.c index 943fd0b6b..d1699e17f 100644 --- a/openbsc/src/mgcp/mgcp_protocol.c +++ b/openbsc/src/mgcp/mgcp_protocol.c @@ -89,6 +89,9 @@ static struct msgb *handle_delete_con(struct mgcp_config *cfg, struct msgb *msg) static struct msgb *handle_modify_con(struct mgcp_config *cfg, struct msgb *msg); static struct msgb *handle_rsip(struct mgcp_config *cfg, struct msgb *msg); +static void create_transcoder(struct mgcp_endpoint *endp); +static void delete_transcoder(struct mgcp_endpoint *endp); + static uint32_t generate_call_id(struct mgcp_config *cfg) { int i; @@ -373,7 +376,8 @@ static int parse_conn_mode(const char *msg, int *conn_mode) } static int allocate_port(struct mgcp_endpoint *endp, struct mgcp_rtp_end *end, - struct mgcp_port_range *range, int for_net) + struct mgcp_port_range *range, + int (*alloc)(struct mgcp_endpoint *endp, int port)) { int i; @@ -390,9 +394,7 @@ static int allocate_port(struct mgcp_endpoint *endp, struct mgcp_rtp_end *end, if (range->last_port >= range->range_end) range->last_port = range->range_start; - rc = for_net ? - mgcp_bind_net_rtp_port(endp, range->last_port) : - mgcp_bind_bts_rtp_port(endp, range->last_port); + rc = alloc(endp, range->last_port); range->last_port += 2; if (rc == 0) { @@ -402,18 +404,28 @@ static int allocate_port(struct mgcp_endpoint *endp, struct mgcp_rtp_end *end, } - LOGP(DMGCP, LOGL_ERROR, "Allocating a RTP/RTCP port failed 200 times 0x%x net: %d\n", - ENDPOINT_NUMBER(endp), for_net); + LOGP(DMGCP, LOGL_ERROR, "Allocating a RTP/RTCP port failed 200 times 0x%x.\n", + ENDPOINT_NUMBER(endp)); return -1; } static int allocate_ports(struct mgcp_endpoint *endp) { - if (allocate_port(endp, &endp->net_end, &endp->cfg->net_ports, 1) != 0) + if (allocate_port(endp, &endp->net_end, &endp->cfg->net_ports, + mgcp_bind_net_rtp_port) != 0) + return -1; + + if (allocate_port(endp, &endp->bts_end, &endp->cfg->bts_ports, + mgcp_bind_bts_rtp_port) != 0) { + mgcp_rtp_end_reset(&endp->net_end); return -1; + } - if (allocate_port(endp, &endp->bts_end, &endp->cfg->bts_ports, 0) != 0) { + if (endp->cfg->transcoder_ip && + allocate_port(endp, &endp->transcoder_end, &endp->cfg->transcoder_ports, + mgcp_bind_transcoder_rtp_port) != 0) { mgcp_rtp_end_reset(&endp->net_end); + mgcp_rtp_end_reset(&endp->bts_end); return -1; } @@ -503,6 +515,7 @@ static struct msgb *handle_create_con(struct mgcp_config *cfg, struct msgb *msg) break; case MGCP_POLICY_DEFER: /* stop processing */ + create_transcoder(endp); return NULL; break; case MGCP_POLICY_CONT: @@ -517,6 +530,7 @@ static struct msgb *handle_create_con(struct mgcp_config *cfg, struct msgb *msg) if (cfg->change_cb) cfg->change_cb(cfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_CRCX); + create_transcoder(endp); return create_response_with_sdp(endp, "CRCX", trans_id); error: LOGP(DMGCP, LOGL_ERROR, "Malformed line: %s on 0x%x with: line_start: %d %d\n", @@ -710,6 +724,7 @@ static struct msgb *handle_delete_con(struct mgcp_config *cfg, struct msgb *msg) break; case MGCP_POLICY_DEFER: /* stop processing */ + delete_transcoder(endp); return NULL; break; case MGCP_POLICY_CONT: @@ -721,6 +736,8 @@ static struct msgb *handle_delete_con(struct mgcp_config *cfg, struct msgb *msg) /* free the connection */ LOGP(DMGCP, LOGL_DEBUG, "Deleted endpoint on: 0x%x Server: %s:%u\n", ENDPOINT_NUMBER(endp), inet_ntoa(endp->net_end.addr), ntohs(endp->net_end.rtp_port)); + + delete_transcoder(endp); mgcp_free_endp(endp); if (cfg->change_cb) cfg->change_cb(cfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_DLCX); @@ -763,6 +780,7 @@ struct mgcp_config *mgcp_config_alloc(void) cfg->source_addr = talloc_strdup(cfg, "0.0.0.0"); cfg->audio_name = talloc_strdup(cfg, "AMR/8000"); cfg->audio_payload = 126; + cfg->transcoder_remote_base = 4000; cfg->bts_ports.base_port = RTP_PORT_DEFAULT; cfg->net_ports.base_port = RTP_PORT_NET_DEFAULT; @@ -805,6 +823,7 @@ int mgcp_endpoints_allocate(struct mgcp_config *cfg) cfg->endpoints[i].cfg = cfg; mgcp_rtp_end_init(&cfg->endpoints[i].net_end); mgcp_rtp_end_init(&cfg->endpoints[i].bts_end); + mgcp_rtp_end_init(&cfg->endpoints[i].transcoder_end); } return 0; @@ -828,6 +847,7 @@ void mgcp_free_endp(struct mgcp_endpoint *endp) mgcp_rtp_end_reset(&endp->bts_end); mgcp_rtp_end_reset(&endp->net_end); + mgcp_rtp_end_reset(&endp->transcoder_end); memset(&endp->net_state, 0, sizeof(endp->net_state)); memset(&endp->bts_state, 0, sizeof(endp->bts_state)); @@ -837,3 +857,109 @@ void mgcp_free_endp(struct mgcp_endpoint *endp) memset(&endp->taps, 0, sizeof(endp->taps)); } + +/* For transcoding we need to manage an in and an output that are connected */ +static int back_channel(int endpoint) +{ + return endpoint + 60; +} + +static int send_trans(struct mgcp_config *cfg, const char *buf, int len) +{ + struct sockaddr_in addr; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr = cfg->transcoder_in; + addr.sin_port = htons(2427); + return sendto(cfg->gw_fd.bfd.fd, buf, len, 0, + (struct sockaddr *) &addr, sizeof(addr)); +} + +static void send_msg(struct mgcp_endpoint *endp, int endpoint, int port, + const char *msg, const char *mode) +{ + char buf[2096]; + int len; + + /* hardcoded to AMR right now, we do not know the real type at this point */ + len = snprintf(buf, sizeof(buf), + "%s 42 %x@mgw MGCP 1.0\r\n" + "C: 4256\r\n" + "M: %s\r\n" + "\r\n" + "c=IN IP4 %s\r\n" + "m=audio %d RTP/AVP %d\r\n" + "a=rtpmap:%d %s\r\n", + msg, endpoint, mode, endp->cfg->source_addr, + port, endp->cfg->audio_payload, + endp->cfg->audio_payload, endp->cfg->audio_name); + + if (len < 0) + return; + + buf[sizeof(buf) - 1] = '\0'; + + send_trans(endp->cfg, buf, len); +} + +static void send_dlcx(struct mgcp_endpoint *endp, int endpoint) +{ + char buf[2096]; + int len; + + len = snprintf(buf, sizeof(buf), + "DLCX 43 %x@mgw MGCP 1.0\r\n" + "C: 4256\r\n" + , endpoint); + + if (len < 0) + return; + + buf[sizeof(buf) - 1] = '\0'; + + send_trans(endp->cfg, buf, len); +} + +static void create_transcoder(struct mgcp_endpoint *endp) +{ + int port; + int in_endp = ENDPOINT_NUMBER(endp); + int out_endp = back_channel(in_endp); + + if (!endp->cfg->transcoder_ip) + return; + + send_msg(endp, in_endp, endp->bts_end.local_port, "CRCX", "recvonly"); + send_msg(endp, in_endp, endp->bts_end.local_port, "MDCX", "recvonly"); + send_msg(endp, out_endp, endp->transcoder_end.local_port, "CRCX", "sendrecv"); + send_msg(endp, out_endp, endp->transcoder_end.local_port, "MDCX", "sendrecv"); + + port = rtp_calculate_port(out_endp, endp->cfg->transcoder_remote_base); + endp->transcoder_end.rtp_port = htons(port); + endp->transcoder_end.rtcp_port = htons(port + 1); +} + +static void delete_transcoder(struct mgcp_endpoint *endp) +{ + int in_endp = ENDPOINT_NUMBER(endp); + int out_endp = back_channel(in_endp); + + if (!endp->cfg->transcoder_ip) + return; + + send_dlcx(endp, in_endp); + send_dlcx(endp, out_endp); +} + +int mgcp_reset_transcoder(struct mgcp_config *cfg) +{ + if (!cfg->transcoder_ip) + return -1; + + static const char mgcp_reset[] = { + "RSIP 1 13@mgw MGCP 1.0\r\n" + }; + + return send_trans(cfg, mgcp_reset, sizeof mgcp_reset -1); +} |