diff options
-rw-r--r-- | openbsc/src/libmsc/a_iface.c | 22 | ||||
-rw-r--r-- | openbsc/src/libmsc/a_iface_bssap.c | 43 | ||||
-rw-r--r-- | openbsc/src/libmsc/msc_ifaces.c | 20 |
3 files changed, 72 insertions, 13 deletions
diff --git a/openbsc/src/libmsc/a_iface.c b/openbsc/src/libmsc/a_iface.c index 029860300..545cdaada 100644 --- a/openbsc/src/libmsc/a_iface.c +++ b/openbsc/src/libmsc/a_iface.c @@ -29,6 +29,8 @@ #include <openbsc/a_iface.h> #include <openbsc/a_iface_bssap.h> #include <openbsc/transaction.h> +#include <openbsc/mgcpgw_client.h> +#include <osmocom/core/byteswap.h> /* A pointer to the GSM network we work with. By the current paradigm, * there can only be one gsm_network per MSC. The pointer is set once @@ -128,15 +130,14 @@ int a_assign(struct gsm_trans *trans) { struct gsm_subscriber_connection *conn; struct gsm0808_channel_type ct; - uint16_t cic; - uint16_t *cic_ptr = NULL; - struct sockaddr_storage *ss = NULL; struct gsm0808_speech_codec_list *scl = NULL; uint32_t *ci_ptr = NULL; + struct msgb *msg; + struct sockaddr_storage rtp_addr; + struct sockaddr_in rtp_addr_in; conn = trans->conn; OSMO_ASSERT(conn); - struct msgb *msg; /* FIXME: This is still work in progress */ /* Some fake parameters for testing */ @@ -145,14 +146,19 @@ int a_assign(struct gsm_trans *trans) ct.perm_spch[0] = GSM0808_PERM_FR1; ct.perm_spch_len = 1; - cic = 0x0023; - cic_ptr = &cic; + /* Package RTP-Address data */ + memset(&rtp_addr_in, 0, sizeof(rtp_addr_in)); + rtp_addr_in.sin_family = AF_INET; + rtp_addr_in.sin_port = osmo_htons(conn->iu.mgcp_rtp_port_ue); + rtp_addr_in.sin_addr.s_addr = osmo_htonl(mgcpgw_client_remote_addr_n(gsm_network->mgcpgw.client)); - msg = gsm0808_create_ass(&ct, cic_ptr, ss, scl, ci_ptr); + memset(&rtp_addr, 0, sizeof(rtp_addr)); + memcpy(&rtp_addr, &rtp_addr_in, sizeof(rtp_addr_in)); + + msg = gsm0808_create_ass(&ct, NULL, &rtp_addr, scl, ci_ptr); LOGP(DMSC, LOGL_DEBUG, "N-DATA.req(%u, %s)\n", conn->a.conn_id, osmo_hexdump(msg->data, msg->len)); return osmo_sccp_tx_data_msg(conn->a.scu, conn->a.conn_id, msg); - } /* Callback function, called by the SSCP stack when data arrives */ diff --git a/openbsc/src/libmsc/a_iface_bssap.c b/openbsc/src/libmsc/a_iface_bssap.c index 258f125fa..eafc4e418 100644 --- a/openbsc/src/libmsc/a_iface_bssap.c +++ b/openbsc/src/libmsc/a_iface_bssap.c @@ -30,6 +30,9 @@ #include <openbsc/a_iface_bssap.h> #include <openbsc/iu.h> #include <openbsc/osmo_msc.h> +#include <osmocom/core/byteswap.h> + +#define IP_V4_ADDR_LEN 4 /* Addresses of all BSCs which have been registered to this MSC */ static LLIST_HEAD(bsc_addr_list); @@ -526,14 +529,52 @@ static int bssmap_ass_compl(struct osmo_sccp_user *scu, struct a_conn_info *a_co { struct gsm_network *network = a_conn_info->network; struct gsm_subscriber_connection *conn; + struct mgcpgw_client *mgcp; + struct tlv_parsed tp; + struct sockaddr_storage rtp_addr; + struct sockaddr_in *rtp_addr_in; + int rc; conn = subscr_conn_lookup_a(network, a_conn_info->conn_id); if (!conn) goto fail; + mgcp = conn->network->mgcpgw.client; + OSMO_ASSERT(mgcp); + LOGP(DMSC, LOGL_NOTICE, "BSC sends assignment complete message (conn_id=%i)\n", conn->a.conn_id); - /* Inform the MSC about the assignment completion event */ + tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 1, msgb_l3len(msg) - 1, 0, 0); + + if (!TLVP_PRESENT(&tp, GSM0808_IE_AOIP_TRASP_ADDR)) { + LOGP(DMSC, LOGL_ERROR, "AoIP transport identifier missing -- discarding message!\n"); + goto fail; + } + + /* Decode AoIP transport address element */ + rc = gsm0808_dec_aoip_trasp_addr(&rtp_addr, TLVP_VAL(&tp, GSM0808_IE_AOIP_TRASP_ADDR), TLVP_LEN(&tp, GSM0808_IE_AOIP_TRASP_ADDR)); + if (rc < 0) { + LOGP(DMSC, LOGL_ERROR, "Unable to decode aoip transport address.\n"); + goto fail; + } + + /* use address / port supplied with the AoIP + * transport address element */ + if(rtp_addr.ss_family == AF_INET) + { + rtp_addr_in = (struct sockaddr_in *)&rtp_addr; + conn->iu.mgcp_rtp_port_ue = osmo_ntohs(rtp_addr_in->sin_port); + /* FIXME: We also get the IP-Address of the remote (e.g. BTS) + * end with the response. Currently we just ignore that address. + * Instead we expect that our local MGCP gateway and the code + * controlling it, magically knows the IP of the remote end. */ + } else { + LOGP(DMSC, LOGL_ERROR, "Unsopported addressing scheme. (supports only IPV4)\n"); + goto fail; + } + + /* FIXME: Seems to be related to authentication or, + encryption. Is this really in the right place? */ msc_rx_sec_mode_compl(conn); msgb_free(msg); diff --git a/openbsc/src/libmsc/msc_ifaces.c b/openbsc/src/libmsc/msc_ifaces.c index e0e4773ad..7162f5f12 100644 --- a/openbsc/src/libmsc/msc_ifaces.c +++ b/openbsc/src/libmsc/msc_ifaces.c @@ -172,9 +172,17 @@ static void mgcp_response_rab_act_cs_crcx(struct mgcp_response *r, void *priv) conn->iu.mgcp_rtp_port_cn = r->audio_port; rtp_ip = mgcpgw_client_remote_addr_n(conn->network->mgcpgw.client); - iu_rab_act_cs(uectx, conn->iu.rab_id, rtp_ip, - conn->iu.mgcp_rtp_port_ue); - /* use_x213_nsap == 0 for ip.access nano3G */ + + if (trans->conn->via_ran == RAN_UTRAN_IU) { + /* Assign a voice channel via RANAP on 3G */ + iu_rab_act_cs(uectx, conn->iu.rab_id, rtp_ip, + conn->iu.mgcp_rtp_port_ue); + /* use_x213_nsap == 0 for ip.access nano3G */ + } else if (trans->conn->via_ran == RAN_GERAN_A) { + /* Assign a voice channel via A on 2G */ + return a_assign(trans); + } else + goto rab_act_cs_error; rab_act_cs_error: /* FIXME abort call, invalidate conn, ... */ @@ -213,7 +221,11 @@ int msc_call_assignment(struct gsm_trans *trans) switch (conn->via_ran) { case RAN_GERAN_A: - return a_assign(trans); + /* FIXME We first go for conn_iu_rab_act_cs(), this function + * will create a loopback rtp connection first and then call + * a_assign(). Probably we need to find another name for + * conn_iu_rab_act_cs? */ + return conn_iu_rab_act_cs(trans); case RAN_UTRAN_IU: #ifdef BUILD_IU |