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.c42
-rw-r--r--openbsc/src/libtrau/trau_mux.c14
2 files changed, 53 insertions, 3 deletions
diff --git a/openbsc/src/libtrau/rtp_proxy.c b/openbsc/src/libtrau/rtp_proxy.c
index 0074b4a04..8ad248843 100644
--- a/openbsc/src/libtrau/rtp_proxy.c
+++ b/openbsc/src/libtrau/rtp_proxy.c
@@ -169,13 +169,28 @@ static int rtp_decode(struct msgb *msg, uint32_t callref, struct msgb **data)
msg_type = GSM_TCHF_FRAME;
if (payload_len != 33) {
DEBUGPC(DLMUX, "received RTP full rate frame with "
- "payload length != 32 (len = %d)\n",
+ "payload length != 33 (len = %d)\n",
payload_len);
return -EINVAL;
}
break;
case RTP_PT_GSM_EFR:
msg_type = GSM_TCHF_FRAME_EFR;
+ if (payload_len != 31) {
+ DEBUGPC(DLMUX, "received RTP extended full rate frame "
+ "with payload length != 31 (len = %d)\n",
+ payload_len);
+ return -EINVAL;
+ }
+ break;
+ case RTP_PT_GSM_HALF:
+ msg_type = GSM_TCHF_FRAME_HR;
+ if (payload_len != 14) {
+ DEBUGPC(DLMUX, "received RTP half rate frame with "
+ "payload length != 14 (len = %d)\n",
+ payload_len);
+ return -EINVAL;
+ }
break;
default:
DEBUGPC(DLMUX, "received RTP frame with unknown payload "
@@ -244,6 +259,11 @@ int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame)
payload_len = 31;
duration = 160;
break;
+ case GSM_TCHF_FRAME_HR:
+ payload_type = RTP_PT_GSM_HALF;
+ payload_len = 14;
+ duration = 160;
+ break;
default:
DEBUGPC(DLMUX, "unsupported message type %d\n",
frame->msg_type);
@@ -426,7 +446,7 @@ static int rtp_socket_read(struct rtp_socket *rs, struct rtp_sub_socket *rss)
other_rss->bfd.when |= BSC_FD_WRITE;
break;
- case RTP_RECV_UPSTREAM:
+ case RTP_RECV_UPSTREAM: /* from BTS to application */
if (!rs->receive.callref || !rs->receive.net) {
rc = -EIO;
goto out_free;
@@ -455,6 +475,24 @@ static int rtp_socket_read(struct rtp_socket *rs, struct rtp_sub_socket *rss)
trau_tx_to_mncc(rs->receive.net, new_msg);
break;
+ case RTP_RECV_L4: /* from L4 */
+ if (!rs->receive.callref || !rs->receive.net) {
+ rc = -EIO;
+ goto out_free;
+ }
+ if (rss->bfd.priv_nr != RTP_PRIV_RTP) {
+ rc = ENOTSUP;
+ goto out_free;
+ }
+ rc = rtp_decode(msg, rs->receive.callref, &new_msg);
+ if (rc < 0)
+ goto out_free;
+ msgb_free(msg);
+ tch_frame_down(rs->receive.net, rs->receive.callref,
+ (struct gsm_data_frame *) new_msg->data);
+ msgb_free(new_msg);
+ break;
+
case RTP_NONE: /* if socket exists, but disabled by app */
msgb_free(msg);
break;
diff --git a/openbsc/src/libtrau/trau_mux.c b/openbsc/src/libtrau/trau_mux.c
index 9272ac04f..ac410c3fc 100644
--- a/openbsc/src/libtrau/trau_mux.c
+++ b/openbsc/src/libtrau/trau_mux.c
@@ -122,7 +122,9 @@ int trau_mux_unmap(const struct gsm_e1_subslot *ss, uint32_t callref)
llist_del(&ue->list);
return 0;
}
- if (ss && !memcmp(&ue->src, ss, sizeof(*ss))) {
+ /* Only release, if no callref is given. We must ensure that
+ * only the transaction's upstream is removed, if exists. */
+ if (ss && !callref && !memcmp(&ue->src, ss, sizeof(*ss))) {
llist_del(&ue->list);
return 0;
}
@@ -280,6 +282,7 @@ int trau_send_frame(struct gsm_lchan *lchan, struct gsm_data_frame *frame)
uint8_t trau_bits_out[TRAU_FRAME_BITS];
struct gsm_e1_subslot *dst_e1_ss = &lchan->ts->e1_link;
struct subch_mux *mx;
+ struct upqueue_entry *ue;
int i, j, k, l, o;
unsigned char *data = frame->data;
struct decoded_trau_frame tf;
@@ -287,6 +290,15 @@ int trau_send_frame(struct gsm_lchan *lchan, struct gsm_data_frame *frame)
mx = e1inp_get_mux(dst_e1_ss->e1_nr, dst_e1_ss->e1_ts);
if (!mx)
return -EINVAL;
+ if (!(ue = lookup_trau_upqueue(dst_e1_ss))) {
+ /* Call might be on hold, so we drop frames. */
+ return 0;
+ }
+ if (ue->callref != frame->callref) {
+ /* Slot has different transaction, due to
+ * another call. (Ours is on hold.) */
+ return 0;
+ }
switch (frame->msg_type) {
case GSM_TCHF_FRAME: