aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/libmgcp/mgcp_protocol.c
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src/libmgcp/mgcp_protocol.c')
-rw-r--r--openbsc/src/libmgcp/mgcp_protocol.c84
1 files changed, 64 insertions, 20 deletions
diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c
index 964971b00..862bf175d 100644
--- a/openbsc/src/libmgcp/mgcp_protocol.c
+++ b/openbsc/src/libmgcp/mgcp_protocol.c
@@ -28,6 +28,7 @@
#include <time.h>
#include <limits.h>
#include <unistd.h>
+#include <errno.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/talloc.h>
@@ -77,6 +78,7 @@ char *strline_r(char *str, char **saveptr)
#define DEFAULT_RTP_AUDIO_FRAME_DUR_DEN 1000
#define DEFAULT_RTP_AUDIO_PACKET_DURATION_MS 20
#define DEFAULT_RTP_AUDIO_DEFAULT_RATE 8000
+#define DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS 1
static void mgcp_rtp_end_reset(struct mgcp_rtp_end *end);
@@ -244,6 +246,8 @@ static struct msgb *create_response_with_sdp(struct mgcp_endpoint *endp,
{
const char *addr = endp->cfg->local_ip;
const char *fmtp_extra = endp->bts_end.fmtp_extra;
+ const char *audio_name = endp->bts_end.audio_name;
+ int payload_type = endp->bts_end.payload_type;
char sdp_record[4096];
int len;
@@ -257,12 +261,13 @@ static struct msgb *create_response_with_sdp(struct mgcp_endpoint *endp,
"c=IN IP4 %s\r\n"
"t=0 0\r\n"
"m=audio %d RTP/AVP %d\r\n"
- "a=rtpmap:%d %s\r\n"
+ "a=rtpmap:%d%s%s\r\n"
"%s%s",
endp->ci, endp->cfg->osmux && endp->osmux ? "\nX-Osmux: On" : "",
endp->ci, addr, addr,
- endp->net_end.local_port, endp->bts_end.payload_type,
- endp->bts_end.payload_type, endp->tcfg->audio_name,
+ endp->net_end.local_port, payload_type,
+ payload_type,
+ audio_name ? " " : "", audio_name ? audio_name : "",
fmtp_extra ? fmtp_extra : "", fmtp_extra ? "\r\n" : "");
if (len < 0 || len >= sizeof(sdp_record))
@@ -528,6 +533,48 @@ static int parse_conn_mode(const char *msg, struct mgcp_endpoint *endp)
return ret;
}
+static int set_audio_info(void *ctx, struct mgcp_rtp_end *rtp,
+ int payload_type, const char *audio_name)
+{
+ int rate = rtp->rate;
+ int channels = rtp->channels;
+ char audio_codec[64];
+
+ talloc_free(rtp->subtype_name);
+ rtp->subtype_name = NULL;
+ talloc_free(rtp->audio_name);
+ rtp->audio_name = NULL;
+
+ rtp->payload_type = payload_type;
+
+ if (!audio_name) {
+ switch (payload_type) {
+ case 3: audio_name = "GSM/8000/1"; break;
+ case 8: audio_name = "PCMA/8000/1"; break;
+ case 18: audio_name = "G729/8000/1"; break;
+ default:
+ /* Payload type is unknown, don't change rate and
+ * channels. */
+ /* TODO: return value? */
+ return 0;
+ }
+ }
+
+ if (sscanf(audio_name, "%63[^/]/%d/%d",
+ audio_codec, &rate, &channels) < 2)
+ return -EINVAL;
+
+ rtp->rate = rate;
+ rtp->channels = channels;
+ rtp->subtype_name = talloc_strdup(ctx, audio_codec);
+ rtp->audio_name = talloc_strdup(ctx, audio_name);
+ if (channels != 1)
+ LOGP(DMGCP, LOGL_NOTICE,
+ "Channels != 1 in SDP: '%s'\n", audio_name);
+
+ return 0;
+}
+
static int allocate_port(struct mgcp_endpoint *endp, struct mgcp_rtp_end *end,
struct mgcp_port_range *range,
int (*alloc)(struct mgcp_endpoint *endp, int port))
@@ -614,11 +661,8 @@ static int parse_sdp_data(struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p)
break;
case 'a': {
int payload;
- int rate;
- int channels = 1;
int ptime, ptime2 = 0;
char audio_name[64];
- char audio_codec[64];
if (audio_payload == -1)
break;
@@ -628,15 +672,7 @@ static int parse_sdp_data(struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p)
if (payload != audio_payload)
break;
- if (sscanf(audio_name, "%[^/]/%d/%d",
- audio_codec, &rate, &channels) < 2)
- break;
-
- rtp->rate = rate;
- if (channels != 1)
- LOGP(DMGCP, LOGL_NOTICE,
- "Channels != 1 in SDP: '%s' on 0x%x\n",
- line, ENDPOINT_NUMBER(p->endp));
+ set_audio_info(p->cfg, rtp, payload, audio_name);
} else if (sscanf(line, "a=ptime:%d-%d",
&ptime, &ptime2) >= 1) {
if (ptime2 > 0 && ptime2 != ptime)
@@ -659,8 +695,8 @@ static int parse_sdp_data(struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p)
&port, &audio_payload) == 2) {
rtp->rtp_port = htons(port);
rtp->rtcp_port = htons(port + 1);
- rtp->payload_type = audio_payload;
found_media = 1;
+ set_audio_info(p->cfg, rtp, audio_payload, NULL);
}
break;
}
@@ -851,7 +887,7 @@ mgcp_header_done:
endp->allocated = 1;
/* set up RTP media parameters */
- endp->bts_end.payload_type = tcfg->audio_payload;
+ set_audio_info(p->cfg, &endp->bts_end, tcfg->audio_payload, tcfg->audio_name);
endp->bts_end.fmtp_extra = talloc_strdup(tcfg->endpoints,
tcfg->audio_fmtp_extra);
if (have_sdp) {
@@ -1297,6 +1333,10 @@ static void mgcp_rtp_end_reset(struct mgcp_rtp_end *end)
end->local_alloc = -1;
talloc_free(end->fmtp_extra);
end->fmtp_extra = NULL;
+ talloc_free(end->subtype_name);
+ end->subtype_name = NULL;
+ talloc_free(end->audio_name);
+ end->audio_name = NULL;
talloc_free(end->rtp_process_data);
end->rtp_process_data = NULL;
@@ -1306,6 +1346,7 @@ static void mgcp_rtp_end_reset(struct mgcp_rtp_end *end)
end->frames_per_packet = 0; /* unknown */
end->packet_duration_ms = DEFAULT_RTP_AUDIO_PACKET_DURATION_MS;
end->rate = DEFAULT_RTP_AUDIO_DEFAULT_RATE;
+ end->channels = DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS;
end->output_enabled = 0;
}
@@ -1383,6 +1424,8 @@ static void send_msg(struct mgcp_endpoint *endp, int endpoint, int port,
{
char buf[2096];
int len;
+ const char *audio_name = endp->bts_end.audio_name;
+ int payload_type = endp->bts_end.payload_type;
/* hardcoded to AMR right now, we do not know the real type at this point */
len = snprintf(buf, sizeof(buf),
@@ -1392,10 +1435,11 @@ static void send_msg(struct mgcp_endpoint *endp, int endpoint, int port,
"\r\n"
"c=IN IP4 %s\r\n"
"m=audio %d RTP/AVP %d\r\n"
- "a=rtpmap:%d %s\r\n",
+ "a=rtpmap:%d%s%s\r\n",
msg, endpoint, mode, endp->cfg->source_addr,
- port, endp->tcfg->audio_payload,
- endp->tcfg->audio_payload, endp->tcfg->audio_name);
+ port, payload_type,
+ payload_type,
+ audio_name ? " " : "", audio_name ? audio_name : "");
if (len < 0)
return;