aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2019-10-21 03:24:11 +0200
committerNeels Hofmeyr <neels@hofmeyr.de>2020-01-06 18:00:40 +0100
commitf31a1ccd9a3eb474936f5b946287581514b29436 (patch)
treeec59ae18c6e54b3530bf2f56e09d99bc23390b0d /include
parent02dd265d68b771bf315cfe6620c9b2371edea828 (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.am2
-rw-r--r--include/osmocom/msc/call_leg.h4
-rw-r--r--include/osmocom/msc/cc_sdp.h42
-rw-r--r--include/osmocom/msc/codec_sdp_cc_t9n.h58
-rw-r--r--include/osmocom/msc/gsm_04_08.h5
-rw-r--r--include/osmocom/msc/msc_a.h4
-rw-r--r--include/osmocom/msc/msc_ho.h4
-rw-r--r--include/osmocom/msc/rtp_stream.h12
-rw-r--r--include/osmocom/msc/sdp_msg.h5
-rw-r--r--include/osmocom/msc/transaction.h7
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;