diff options
author | Neels Hofmeyr <neels@hofmeyr.de> | 2019-10-21 03:24:11 +0200 |
---|---|---|
committer | Neels Hofmeyr <neels@hofmeyr.de> | 2020-01-06 18:00:40 +0100 |
commit | f31a1ccd9a3eb474936f5b946287581514b29436 (patch) | |
tree | ec59ae18c6e54b3530bf2f56e09d99bc23390b0d /include | |
parent | 02dd265d68b771bf315cfe6620c9b2371edea828 (diff) |
add full SDP codec information to the MNCC socket
This way osmo-msc can benefit from the complete codec information received via
SIP, which was so far terminated at osmo-sip-connector. osmo-sip-connector
could/should have translated the received SDP to MNCC bearer_cap, but this was
never implemented properly. Since osmo-msc already handles SDP towards the MGW,
it makes most sense to pass SDP to osmo-msc transparently.
To be able to send a valid RTP IP:port in the SDP upon the first MNCC_SETUP_IND
going out, move the CN side CRCX to the very start of establishing a voice
call. As a result, first create MGW conns for both RAN and CN before starting.
The voice_call_full.msc chart shows the change in message sequence for MO and
MT voice calls.
Implement cc_sdp.c, which accumulates codec information from various sources
(MS, BSS, Assignment, remote call leg) and provides filtering to get the
available set of codecs at any point in time.
Implement codec_sdp_cc_t9n.c, to translate between SDP and the various
libosmo-mgcp-client, CC and BSSMAP representations of codecs:
- Speech Version,
- Permitted Speech,
- Speech Codec Type,
- default Payload Type numbers,
- enum mgcp_codecs,
- FR/HR compatibility
- SDP audio codec names,
- various AMR configurations.
A codec_map lists these relations in one large data record.
Various functions provide conversions by traversing this map.
Add trans->cc.mnccc_release_sent: so far, avoiding to send an MNCC release
during trans_free() was done by setting the callref = 0. But that also skips CC
Release. On codec mismatch, we send a specific MNCC error code but still want a
normal CC Release: hence send the MNCC message, set mnccc_release_sent = true
and do normal CC Release in trans_free().
(A better way to do this would be to adopt the mncc_call FSM from inter-MSC
handover also for local voice calls, but that is out of scope for now. I want
to try that soon, as time permits.)
Change-Id: I8c3b2de53ffae4ec3a66b9dabf308c290a2c999f
Diffstat (limited to 'include')
-rw-r--r-- | include/osmocom/msc/Makefile.am | 2 | ||||
-rw-r--r-- | include/osmocom/msc/call_leg.h | 4 | ||||
-rw-r--r-- | include/osmocom/msc/cc_sdp.h | 42 | ||||
-rw-r--r-- | include/osmocom/msc/codec_sdp_cc_t9n.h | 58 | ||||
-rw-r--r-- | include/osmocom/msc/gsm_04_08.h | 5 | ||||
-rw-r--r-- | include/osmocom/msc/msc_a.h | 4 | ||||
-rw-r--r-- | include/osmocom/msc/msc_ho.h | 4 | ||||
-rw-r--r-- | include/osmocom/msc/rtp_stream.h | 12 | ||||
-rw-r--r-- | include/osmocom/msc/sdp_msg.h | 5 | ||||
-rw-r--r-- | include/osmocom/msc/transaction.h | 7 |
10 files changed, 135 insertions, 8 deletions
diff --git a/include/osmocom/msc/Makefile.am b/include/osmocom/msc/Makefile.am index faf1048dc..572430309 100644 --- a/include/osmocom/msc/Makefile.am +++ b/include/osmocom/msc/Makefile.am @@ -1,6 +1,8 @@ noinst_HEADERS = \ call_leg.h \ + cc_sdp.h \ cell_id_list.h \ + codec_sdp_cc_t9n.h \ db.h \ debug.h \ e_link.h \ diff --git a/include/osmocom/msc/call_leg.h b/include/osmocom/msc/call_leg.h index a225b6683..c7d3b9739 100644 --- a/include/osmocom/msc/call_leg.h +++ b/include/osmocom/msc/call_leg.h @@ -12,6 +12,7 @@ struct gsm_network; struct gsm_trans; struct rtp_stream; enum rtp_direction; +struct sdp_audio_codecs; extern struct osmo_tdef g_mgw_tdefs[]; @@ -74,7 +75,8 @@ int call_leg_local_bridge(struct call_leg *cl1, uint32_t call_id1, struct gsm_tr int call_leg_ensure_rtp_alloc(struct call_leg *cl, enum rtp_direction dir, uint32_t call_id, struct gsm_trans *for_trans); int call_leg_ensure_ci(struct call_leg *cl, enum rtp_direction dir, uint32_t call_id, struct gsm_trans *for_trans, - const enum mgcp_codecs *codec_if_known, const struct osmo_sockaddr_str *remote_addr_if_known); + const struct sdp_audio_codecs *codecs_if_known, + const struct osmo_sockaddr_str *remote_addr_if_known); struct osmo_sockaddr_str *call_leg_local_ip(struct call_leg *cl, enum rtp_direction dir); void call_leg_rtp_stream_gone(struct call_leg *cl, struct rtp_stream *rtps); diff --git a/include/osmocom/msc/cc_sdp.h b/include/osmocom/msc/cc_sdp.h new file mode 100644 index 000000000..549a888d3 --- /dev/null +++ b/include/osmocom/msc/cc_sdp.h @@ -0,0 +1,42 @@ +#pragma once + +#include <osmocom/gsm/gsm_utils.h> +#include <osmocom/gsm/mncc.h> +#include <osmocom/mgcp_client/mgcp_client.h> + +#include <osmocom/msc/sdp_msg.h> + +struct gsm0808_speech_codec_list; + +struct cc_sdp { + /* The fixed set of codecs available on the RAN type, per definition. */ + struct sdp_audio_codecs ran; + /* The codecs advertised by the MS Bearer Capabilities */ + struct sdp_audio_codecs ms; + /* If known, the set of codecs the current RAN cell allows / has available. + * This may not be available if the BSC does not issue this information early enough. + * Should be ignored if empty. */ + struct sdp_audio_codecs cell; + + /* SDP as last received from the remote call leg. */ + struct sdp_msg remote; + + /* After a channel was assigned, this reflects the chosen codec. */ + struct sdp_audio_codec assignment; + + /* Resulting choice of supported codecs, usually the intersection of the above, + * and the local RTP address to be sent to the remote call leg. */ + struct sdp_msg result; +}; + +void cc_sdp_init(struct cc_sdp *cc_sdp, + enum osmo_rat_type ran_type, + const struct gsm_mncc_bearer_cap *ms_bearer_cap, + const struct gsm0808_speech_codec_list *codec_list_bss_supported); +void cc_sdp_set_cell(struct cc_sdp *cc_sdp, + const struct gsm0808_speech_codec_list *codec_list_bss_supported); +int cc_sdp_filter(struct cc_sdp *cc_sdp); + +int cc_sdp_name_buf(char *buf, size_t buflen, const struct cc_sdp *cc_sdp); +char *cc_sdp_name_c(void *ctx, const struct cc_sdp *cc_sdp); +const char *cc_sdp_name(const struct cc_sdp *cc_sdp); diff --git a/include/osmocom/msc/codec_sdp_cc_t9n.h b/include/osmocom/msc/codec_sdp_cc_t9n.h new file mode 100644 index 000000000..b082f159e --- /dev/null +++ b/include/osmocom/msc/codec_sdp_cc_t9n.h @@ -0,0 +1,58 @@ +/* Routines for translation ("t9n") between SDP codec names and CC/BSSMAP codec constants */ +#pragma once + +#include <osmocom/gsm/protocol/gsm_04_08.h> +#include <osmocom/gsm/protocol/gsm_08_08.h> +#include <osmocom/mgcp_client/mgcp_client.h> +#include <osmocom/msc/sdp_msg.h> +#include <osmocom/gsm/mncc.h> + +#define NO_MGCP_CODEC 0xffffffff + +extern const struct gsm_mncc_bearer_cap bearer_cap_empty; + +enum codec_frhr { + CODEC_FRHR_NONE = 0, + CODEC_FRHR_FR, + CODEC_FRHR_HR, +}; + +struct codec_mapping { + struct sdp_audio_codec sdp; + enum mgcp_codecs mgcp; + unsigned int speech_ver_count; + enum gsm48_bcap_speech_ver speech_ver[8]; + uint32_t mncc_payload_msg_type; + /* gsm0808_speech_codec_type corresponds to gsm0808_speech_codec[_list]->type */ + bool has_gsm0808_speech_codec_type; + enum gsm0808_speech_codec_type gsm0808_speech_codec_type; + enum gsm0808_permitted_speech perm_speech; + enum codec_frhr frhr; +}; + +extern const struct codec_mapping codec_map[]; +#define foreach_codec_mapping(CODEC_MAPPING) \ + for ((CODEC_MAPPING) = codec_map; (CODEC_MAPPING) < codec_map + ARRAY_SIZE(codec_map); (CODEC_MAPPING)++) + +const struct codec_mapping *codec_mapping_by_speech_ver(enum gsm48_bcap_speech_ver speech_ver); +const struct codec_mapping *codec_mapping_by_gsm0808_speech_codec_type(enum gsm0808_speech_codec_type sct, + uint16_t cfg); +const struct codec_mapping *codec_mapping_by_perm_speech(enum gsm0808_permitted_speech perm_speech); +const struct codec_mapping *codec_mapping_by_subtype_name(const char *subtype_name); +const struct codec_mapping *codec_mapping_by_mgcp_codec(enum mgcp_codecs mgcp); + +int bearer_cap_add_speech_ver(struct gsm_mncc_bearer_cap *bearer_cap, enum gsm48_bcap_speech_ver speech_ver); +int sdp_audio_codec_add_to_bearer_cap(struct gsm_mncc_bearer_cap *bearer_cap, const struct sdp_audio_codec *codec); +int sdp_audio_codecs_to_bearer_cap(struct gsm_mncc_bearer_cap *bearer_cap, const struct sdp_audio_codecs *ac); +int bearer_cap_set_radio(struct gsm_mncc_bearer_cap *bearer_cap); + +struct sdp_audio_codec *sdp_audio_codecs_add_speech_ver(struct sdp_audio_codecs *ac, + enum gsm48_bcap_speech_ver speech_ver); +struct sdp_audio_codec *sdp_audio_codecs_add_mgcp_codec(struct sdp_audio_codecs *ac, enum mgcp_codecs mgcp_codec); +void sdp_audio_codecs_from_bearer_cap(struct sdp_audio_codecs *ac, const struct gsm_mncc_bearer_cap *bc); + +void sdp_audio_codecs_from_speech_codec_list(struct sdp_audio_codecs *ac, const struct gsm0808_speech_codec_list *cl); + +int sdp_audio_codecs_to_gsm0808_channel_type(struct gsm0808_channel_type *ct, const struct sdp_audio_codecs *ac); + +enum mgcp_codecs sdp_audio_codec_to_mgcp_codec(const struct sdp_audio_codec *codec); diff --git a/include/osmocom/msc/gsm_04_08.h b/include/osmocom/msc/gsm_04_08.h index 661da42b3..fc8ebd192 100644 --- a/include/osmocom/msc/gsm_04_08.h +++ b/include/osmocom/msc/gsm_04_08.h @@ -45,6 +45,11 @@ int gsm48_send_rr_app_info(struct msc_a *msc_a, uint8_t apdu_id, uint8_t apdu_le int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan, uint8_t power_class); int gsm48_send_ho_cmd(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan, uint8_t power_command, uint8_t ho_ref); +void gsm48_cc_rx_setup_cn_local_rtp_port_known(struct gsm_trans *trans); +void gsm48_cc_rx_call_conf_cn_local_rtp_port_known(struct gsm_trans *trans); +int cc_cn_local_rtp_port_known(struct gsm_trans *trans); +int cc_assignment_done(struct gsm_trans *trans); + int mncc_tx_to_cc(struct gsm_network *net, void *arg); /* convert a ASCII phone number to call-control BCD */ diff --git a/include/osmocom/msc/msc_a.h b/include/osmocom/msc/msc_a.h index 18973f9af..b9311cd11 100644 --- a/include/osmocom/msc/msc_a.h +++ b/include/osmocom/msc/msc_a.h @@ -121,6 +121,9 @@ struct msc_a { * \-------RTP--> (ISUP) <--RTP--> <--RTP--> */ struct { + /* Codec List (BSS Supported) as received during Complete Layer 3 Information */ + struct gsm0808_speech_codec_list codec_list_bss_supported; + /* All of the RTP stream handling */ struct call_leg *call_leg; struct mncc_call *mncc_forwarding_to_remote_ran; @@ -203,6 +206,7 @@ void msc_a_up_ciph_res(struct msc_a *msc_a, bool success, const char *imeisv); bool msc_a_is_accepted(const struct msc_a *msc_a); bool msc_a_is_establishing_auth_ciph(const struct msc_a *msc_a); +int msc_a_ensure_cn_local_rtp(struct msc_a *msc_a, struct gsm_trans *cc_trans); int msc_a_try_call_assignment(struct gsm_trans *cc_trans); const char *msc_a_cm_service_type_to_use(enum osmo_cm_service_type cm_service_type); diff --git a/include/osmocom/msc/msc_ho.h b/include/osmocom/msc/msc_ho.h index 99956f1e6..a3f60c7f2 100644 --- a/include/osmocom/msc/msc_ho.h +++ b/include/osmocom/msc/msc_ho.h @@ -31,7 +31,7 @@ #include <osmocom/msc/neighbor_ident.h> #include <osmocom/msc/ran_msg.h> #include <osmocom/msc/mncc_call.h> - +#include <osmocom/msc/sdp_msg.h> struct gsm0808_handover_required; @@ -92,7 +92,7 @@ struct msc_ho_state { struct { /* Saved RTP IP:port and codec in case we need to roll back */ struct osmo_sockaddr_str ran_remote_rtp; - enum mgcp_codecs codec; + struct sdp_audio_codecs codecs; } old_cell; }; diff --git a/include/osmocom/msc/rtp_stream.h b/include/osmocom/msc/rtp_stream.h index c53c4f179..c654edd54 100644 --- a/include/osmocom/msc/rtp_stream.h +++ b/include/osmocom/msc/rtp_stream.h @@ -5,6 +5,7 @@ #include <osmocom/core/sockaddr_str.h> #include <osmocom/mgcp_client/mgcp_client.h> +#include <osmocom/msc/sdp_msg.h> struct gsm_trans; @@ -37,9 +38,9 @@ struct rtp_stream { struct osmo_sockaddr_str remote; bool remote_sent_to_mgw; - bool codec_known; - enum mgcp_codecs codec; - bool codec_sent_to_mgw; + bool codecs_known; + struct sdp_audio_codecs codecs; + bool codecs_sent_to_mgw; struct osmo_mgcpc_ep_ci *ci; @@ -64,8 +65,11 @@ struct rtp_stream *rtp_stream_alloc(struct call_leg *parent_call_leg, enum rtp_d int rtp_stream_ensure_ci(struct rtp_stream *rtps, struct osmo_mgcpc_ep *at_endpoint); int rtp_stream_do_mdcx(struct rtp_stream *rtps); -void rtp_stream_set_codec(struct rtp_stream *rtps, enum mgcp_codecs codec); +void rtp_stream_set_codecs(struct rtp_stream *rtps, const struct sdp_audio_codecs *codecs); +void rtp_stream_set_one_codec(struct rtp_stream *rtps, const struct sdp_audio_codec *codec); +bool rtp_stream_set_codecs_from_mgcp_codec(struct rtp_stream *rtps, enum mgcp_codecs codec); void rtp_stream_set_remote_addr(struct rtp_stream *rtps, const struct osmo_sockaddr_str *r); +void rtp_stream_set_remote_addr_and_codecs(struct rtp_stream *rtps, const struct sdp_msg *sdp); void rtp_stream_set_remote_osmux_cid(struct rtp_stream *rtps, uint8_t osmux_cid); int rtp_stream_commit(struct rtp_stream *rtps); diff --git a/include/osmocom/msc/sdp_msg.h b/include/osmocom/msc/sdp_msg.h index 7ac6036f6..a8ecba573 100644 --- a/include/osmocom/msc/sdp_msg.h +++ b/include/osmocom/msc/sdp_msg.h @@ -36,7 +36,10 @@ struct sdp_msg { const char *sdp_msg_line_end(const char *src); -int sdp_audio_codec_cmp(const struct sdp_audio_codec *a, const struct sdp_audio_codec *b); +int sdp_audio_codec_cmp(const struct sdp_audio_codec *a, const struct sdp_audio_codec *b, + bool cmp_fmtp, bool cmp_payload_type); +int sdp_audio_codecs_cmp(const struct sdp_audio_codecs *a, const struct sdp_audio_codecs *b, + bool cmp_fmtp, bool cmp_payload_type); struct sdp_audio_codec *sdp_audio_codec_add(struct sdp_audio_codecs *ac, unsigned int payload_type, const char *subtype_name, unsigned int rate, const char *fmtp); diff --git a/include/osmocom/msc/transaction.h b/include/osmocom/msc/transaction.h index 928b137ae..c091be244 100644 --- a/include/osmocom/msc/transaction.h +++ b/include/osmocom/msc/transaction.h @@ -10,6 +10,7 @@ #include <osmocom/msc/debug.h> #include <osmocom/gsm/gsm0411_smc.h> #include <osmocom/gsm/gsm0411_smr.h> +#include <osmocom/msc/cc_sdp.h> struct vty; @@ -87,6 +88,10 @@ struct gsm_trans { /* bearer capabilities (rate and codec) */ struct gsm_mncc_bearer_cap bearer_cap; + /* if true, TCH_RTP_CREATE is sent after the + * assignment is done */ + bool tch_rtp_create; + union { struct { @@ -100,6 +105,8 @@ struct gsm_trans { struct osmo_timer_list timer_guard; struct gsm_mncc msg; /* stores setup/disconnect/release message */ bool mncc_initiated; /* Whether an MNCC Release is necessary on failure */ + bool mncc_release_sent; /* Mark when special error handling already did MNCC rel */ + struct cc_sdp sdp; /* Track SDP codec info from BSS and remote call leg */ } cc; struct { struct gsm411_smc_inst smc_inst; |