aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/libtrau
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src/libtrau')
-rw-r--r--openbsc/src/libtrau/rtp_proxy.c53
1 files changed, 47 insertions, 6 deletions
diff --git a/openbsc/src/libtrau/rtp_proxy.c b/openbsc/src/libtrau/rtp_proxy.c
index 143bfa006..95729ef05 100644
--- a/openbsc/src/libtrau/rtp_proxy.c
+++ b/openbsc/src/libtrau/rtp_proxy.c
@@ -192,21 +192,41 @@ static int rtp_decode(struct msgb *msg, uint32_t callref, struct msgb **data)
return -EINVAL;
}
break;
+ case RTP_PT_AMR:
+ break;
default:
DEBUGPC(DLMUX, "received RTP frame with unknown payload "
"type %d\n", rtph->payload_type);
return -EINVAL;
}
- new_msg = msgb_alloc(sizeof(struct gsm_data_frame) + payload_len,
- "GSM-DATA");
+ if (payload_len > 33) {
+ DEBUGPC(DLMUX, "RTP payload too large (%d octets)\n",
+ payload_len);
+ return -EINVAL;
+ }
+
+ if (rtph->payload_type == RTP_PT_AMR) {
+ new_msg = msgb_alloc(sizeof(struct gsm_data_frame) + 1
+ + payload_len, "GSM-DATA (AMR)");
+ } else {
+ new_msg = msgb_alloc(sizeof(struct gsm_data_frame)
+ + payload_len, "GSM-DATA");
+ }
if (!new_msg)
return -ENOMEM;
frame = (struct gsm_data_frame *)(new_msg->data);
frame->msg_type = msg_type;
frame->callref = callref;
- memcpy(frame->data, payload, payload_len);
- msgb_put(new_msg, sizeof(struct gsm_data_frame) + payload_len);
+ if (rtph->payload_type == RTP_PT_AMR) {
+ frame->data[0] = payload_len;
+ msgb_put(new_msg, sizeof(struct gsm_data_frame) + 1
+ + payload_len);
+ memcpy(frame->data + 1, payload, payload_len);
+ } else {
+ msgb_put(new_msg, sizeof(struct gsm_data_frame) + payload_len);
+ memcpy(frame->data, payload, payload_len);
+ }
*data = new_msg;
return 0;
@@ -264,6 +284,11 @@ int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame)
payload_len = RTP_LEN_GSM_HALF;
duration = RTP_GSM_DURATION;
break;
+ case GSM_TCH_FRAME_AMR:
+ payload_type = RTP_PT_AMR;
+ payload_len = frame->data[0];
+ duration = RTP_GSM_DURATION;
+ break;
default:
DEBUGPC(DLMUX, "unsupported message type %d\n",
frame->msg_type);
@@ -291,7 +316,18 @@ int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame)
}
}
- msg = msgb_alloc(sizeof(struct rtp_hdr) + payload_len, "RTP-GSM-FULL");
+ if (payload_len > 33) {
+ DEBUGPC(DLMUX, "RTP payload too large (%d octets)\n",
+ payload_len);
+ return -EINVAL;
+ }
+
+ if (frame->msg_type == GSM_TCH_FRAME_AMR)
+ msg = msgb_alloc(sizeof(struct rtp_hdr) + payload_len,
+ "RTP-GSM (AMR)");
+ else
+ msg = msgb_alloc(sizeof(struct rtp_hdr) + payload_len,
+ "RTP-GSM");
if (!msg)
return -ENOMEM;
rtph = (struct rtp_hdr *)msg->data;
@@ -305,7 +341,12 @@ int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame)
rtph->timestamp = htonl(rs->transmit.timestamp);
rs->transmit.timestamp += duration;
rtph->ssrc = htonl(rs->transmit.ssrc);
- memcpy(msg->data + sizeof(struct rtp_hdr), frame->data, payload_len);
+ if (frame->msg_type == GSM_TCH_FRAME_AMR)
+ memcpy(msg->data + sizeof(struct rtp_hdr), frame->data + 1,
+ payload_len);
+ else
+ memcpy(msg->data + sizeof(struct rtp_hdr), frame->data,
+ payload_len);
msgb_put(msg, sizeof(struct rtp_hdr) + payload_len);
msgb_enqueue(&rss->tx_queue, msg);
rss->bfd.when |= BSC_FD_WRITE;