static void create_transcoder(struct mgcp_endpoint *endp) { int port; int in_endp = ENDPOINT_NUMBER(endp); int out_endp = endp_back_channel(in_endp); if (!endp->is_transcoded) return; send_msg(endp, in_endp, endp->trans_bts.local_port, "CRCX", "sendrecv"); send_msg(endp, in_endp, endp->trans_bts.local_port, "MDCX", "sendrecv"); send_msg(endp, out_endp, endp->trans_net.local_port, "CRCX", "sendrecv"); send_msg(endp, out_endp, endp->trans_net.local_port, "MDCX", "sendrecv"); port = rtp_calculate_port(in_endp, endp->cfg->transcoder_remote_base); endp->trans_bts.rtp_port = htons(port); endp->trans_bts.rtcp_port = htons(port + 1); port = rtp_calculate_port(out_endp, endp->cfg->transcoder_remote_base); endp->trans_net.rtp_port = htons(port); endp->trans_net.rtcp_port = htons(port + 1); }
/* * Handle the assignment request message. * * See §3.2.1.1 for the message type */ static int bssmap_handle_assignm_req(struct osmo_bsc_sccp_con *conn, struct msgb *msg, unsigned int length) { struct msgb *resp; struct osmo_msc_data *msc; struct tlv_parsed tp; uint8_t *data; uint8_t timeslot; uint8_t multiplex; enum gsm48_chan_mode chan_mode = GSM48_CMODE_SIGN; int i, supported, port, full_rate = -1; if (!conn->conn) { LOGP(DMSC, LOGL_ERROR, "No lchan/msc_data in cipher mode command.\n"); return -1; } tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, length - 1, 0, 0); if (!TLVP_PRESENT(&tp, GSM0808_IE_CHANNEL_TYPE)) { LOGP(DMSC, LOGL_ERROR, "Mandatory channel type not present.\n"); goto reject; } if (!TLVP_PRESENT(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE)) { LOGP(DMSC, LOGL_ERROR, "Identity code missing. Audio routing will not work.\n"); goto reject; } conn->cic = ntohs(read_data16(TLVP_VAL(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE))); timeslot = conn->cic & 0x1f; multiplex = (conn->cic & ~0x1f) >> 5; /* * Currently we only support a limited subset of all * possible channel types. The limitation ends by not using * multi-slot, limiting the channel coding, speech... */ if (TLVP_LEN(&tp, GSM0808_IE_CHANNEL_TYPE) < 3) { LOGP(DMSC, LOGL_ERROR, "ChannelType len !=3 not supported: %d\n", TLVP_LEN(&tp, GSM0808_IE_CHANNEL_TYPE)); goto reject; } /* * Try to figure out if we support the proposed speech codecs. For * now we will always pick the full rate codecs. */ data = (uint8_t *) TLVP_VAL(&tp, GSM0808_IE_CHANNEL_TYPE); if ((data[0] & 0xf) != 0x1) { LOGP(DMSC, LOGL_ERROR, "ChannelType != speech: %d\n", data[0]); goto reject; } /* * go through the list of preferred codecs of our gsm network * and try to find it among the permitted codecs. If we found * it we will send chan_mode to the right mode and break the * inner loop. The outer loop will exit due chan_mode having * the correct value. */ full_rate = 0; msc = conn->msc; for (supported = 0; chan_mode == GSM48_CMODE_SIGN && supported < msc->audio_length; ++supported) { int perm_val = audio_support_to_gsm88(msc->audio_support[supported]); for (i = 2; i < TLVP_LEN(&tp, GSM0808_IE_CHANNEL_TYPE); ++i) { if ((data[i] & 0x7f) == perm_val) { chan_mode = gsm88_to_chan_mode(perm_val); full_rate = (data[i] & 0x4) == 0; break; } else if ((data[i] & 0x80) == 0x00) { break; } } } if (chan_mode == GSM48_CMODE_SIGN) { LOGP(DMSC, LOGL_ERROR, "No supported audio type found.\n"); goto reject; } /* map it to a MGCP Endpoint and a RTP port */ port = mgcp_timeslot_to_endpoint(multiplex, timeslot); conn->rtp_port = rtp_calculate_port(port, msc->rtp_base); return gsm0808_assign_req(conn->conn, chan_mode, full_rate); reject: resp = gsm0808_create_assignment_failure(GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE, NULL); if (!resp) { LOGP(DMSC, LOGL_ERROR, "Channel allocation failure.\n"); return -1; } bsc_queue_for_msc(conn, resp); return -1; }