diff options
Diffstat (limited to 'openbsc/src/libtrau')
-rw-r--r-- | openbsc/src/libtrau/rtp_proxy.c | 42 | ||||
-rw-r--r-- | openbsc/src/libtrau/trau_mux.c | 14 |
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: |