Change in osmo-msc[master]: libmsc: Allow different channel types to be requested as silent calls

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

tnt gerrit-no-reply at lists.osmocom.org
Wed Mar 13 17:17:33 UTC 2019


tnt has uploaded this change for review. ( https://gerrit.osmocom.org/13242


Change subject: libmsc: Allow different channel types to be requested as silent calls
......................................................................

libmsc: Allow different channel types to be requested as silent calls

Change-Id: I82645708dd27864cf33ea9cc993ead0983415602
Signed-off-by: Sylvain Munaut <tnt at 246tNt.com>
---
M include/osmocom/msc/silent_call.h
M src/libmsc/msc_vty.c
M src/libmsc/silent_call.c
3 files changed, 153 insertions(+), 22 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-msc refs/changes/42/13242/1

diff --git a/include/osmocom/msc/silent_call.h b/include/osmocom/msc/silent_call.h
index 70324e5..dbd7dcc 100644
--- a/include/osmocom/msc/silent_call.h
+++ b/include/osmocom/msc/silent_call.h
@@ -2,9 +2,12 @@
 #define _SILENT_CALL_H
 
 struct ran_conn;
+struct gsm0808_channel_type;
 
 extern int gsm_silent_call_start(struct vlr_subscr *vsub,
-                                 void *data, int type);
+		struct gsm0808_channel_type *ct,
+		const char *traffic_dst_ip, uint16_t traffic_dst_port,
+		void *data);
 extern int gsm_silent_call_stop(struct vlr_subscr *vsub);
 
 #if 0
diff --git a/src/libmsc/msc_vty.c b/src/libmsc/msc_vty.c
index 2adb2a4..4ec2e5b 100644
--- a/src/libmsc/msc_vty.c
+++ b/src/libmsc/msc_vty.c
@@ -1042,21 +1042,35 @@
 	return rc;
 }
 
-#define CHAN_TYPES "(any|tch/f|tch/any|sdcch)"
+#define CHAN_TYPES "(any|tch/f|tch/h|tch/any|sdcch)"
 #define CHAN_TYPE_HELP 			\
 		"Any channel\n"		\
 		"TCH/F channel\n"	\
+		"TCH/H channel\n"	\
 		"Any TCH channel\n"	\
 		"SDCCH channel\n"
 
+#define CHAN_MODES "(signalling|speech-hr|speech-fr|speech-efr|speech-amr)"
+#define CHAN_MODE_HELP				\
+		"Signalling only\n"		\
+		"Speech with HR codec\n"	\
+		"Speech with FR codec\n"	\
+		"Speech with EFR codec\n"	\
+		"Speech with AMR codec\n"
+
 DEFUN(subscriber_silent_call_start,
       subscriber_silent_call_start_cmd,
-      "subscriber " SUBSCR_TYPES " ID silent-call start (any|tch/f|tch/any|sdcch)",
+      "subscriber " SUBSCR_TYPES " ID silent-call start " CHAN_TYPES " " CHAN_MODES " [IP] [<0-65536>]",
 	SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
-	CHAN_TYPE_HELP)
+	CHAN_TYPE_HELP CHAN_MODE_HELP
+	"Target IP for RTP traffic (default 127.0.0.1)\n"
+	"Target port for RTP traffic (default: 4000)\n")
 {
 	struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
-	int rc, type;
+	struct gsm0808_channel_type ct;
+	const char *ip = NULL;
+	uint16_t port = 0;
+	int rc, speech;
 
 	if (!vsub) {
 		vty_out(vty, "%% No subscriber found for %s %s%s",
@@ -1064,16 +1078,52 @@
 		return CMD_WARNING;
 	}
 
-	if (!strcmp(argv[2], "tch/f"))
-		type = RSL_CHANNEED_TCH_F;
-	else if (!strcmp(argv[2], "tch/any"))
-		type = RSL_CHANNEED_TCH_ForH;
-	else if (!strcmp(argv[2], "sdcch"))
-		type = RSL_CHANNEED_SDCCH;
-	else
-		type = RSL_CHANNEED_ANY;	/* Defaults to ANY */
+	memset(&ct, 0x00, sizeof(ct));
 
-	rc = gsm_silent_call_start(vsub, vty, type);
+	if (!strcmp(argv[3], "signalling")) {
+		ct.ch_indctr = GSM0808_CHAN_SIGN;
+		ct.perm_spch[0] = 0; /* Spare but required */
+		ct.perm_spch_len = 1;
+	} else if (!strcmp(argv[3], "speech-hr")) {
+		ct.ch_indctr = GSM0808_CHAN_SPEECH;
+		ct.perm_spch[0] = GSM0808_PERM_HR1;
+		ct.perm_spch_len = 1;
+	} else if (!strcmp(argv[3], "speech-fr")) {
+		ct.ch_indctr = GSM0808_CHAN_SPEECH;
+		ct.perm_spch[0] = GSM0808_PERM_FR1;
+		ct.perm_spch_len = 1;
+	} else if (!strcmp(argv[3], "speech-efr")) {
+		ct.ch_indctr = GSM0808_CHAN_SPEECH;
+		ct.perm_spch[0] = GSM0808_PERM_FR2;
+		ct.perm_spch_len = 1;
+	} else if (!strcmp(argv[3], "speech-amr")) {
+		ct.ch_indctr = GSM0808_CHAN_SPEECH;
+		ct.perm_spch[0] = GSM0808_PERM_FR3;
+		ct.perm_spch[1] = GSM0808_PERM_HR3;
+		ct.perm_spch_len = 2;
+	}
+
+	speech = ct.ch_indctr == GSM0808_CHAN_SPEECH;
+
+	if (!strcmp(argv[2], "tch/f"))
+		ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_BM : GSM0808_SIGN_FULL_BM;
+	else if (!strcmp(argv[2], "tch/h"))
+		ct.ch_rate_type = speech ? GSM0808_SPEECH_HALF_LM : GSM0808_SIGN_HALF_LM;
+	else if (!strcmp(argv[2], "tch/any"))
+		ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_FULL_PREF;
+	else if (!strcmp(argv[2], "sdcch")) {
+		if (speech) {
+			vty_out(vty, "Can't request speech on SDCCH%s", VTY_NEWLINE);
+			return CMD_WARNING;
+		}
+		ct.ch_rate_type = GSM0808_SIGN_SDCCH;
+	} else
+		ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_ANY;
+
+	ip   = argc >= 5 ? argv[4] : "127.0.0.1";
+	port = argc >= 6 ? atoi(argv[5]) : 4000;
+
+	rc = gsm_silent_call_start(vsub, &ct, ip, port, vty);
 	switch (rc) {
 	case -ENODEV:
 		vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
diff --git a/src/libmsc/silent_call.c b/src/libmsc/silent_call.c
index 2a9fa9c..cadd17d 100644
--- a/src/libmsc/silent_call.c
+++ b/src/libmsc/silent_call.c
@@ -24,6 +24,7 @@
 #include <unistd.h>
 #include <errno.h>
 
+#include <osmocom/core/byteswap.h>
 #include <osmocom/core/msgb.h>
 #include <osmocom/msc/signal.h>
 #include <osmocom/msc/debug.h>
@@ -31,13 +32,37 @@
 #include <osmocom/msc/gsm_subscriber.h>
 #include <osmocom/msc/vlr.h>
 
+#include <osmocom/sigtran/sccp_helpers.h>
+
+struct silent_call_data {
+	struct gsm0808_channel_type ct;
+
+	char traffic_ip[INET_ADDRSTRLEN];
+	uint16_t traffic_port;
+
+	void *data;
+
+	struct osmo_timer_list timer;
+	struct ran_conn *conn;
+};
+
+static void timer_cb(void *data)
+{
+	struct silent_call_data *scd = (struct silent_call_data *)data;
+	ran_conn_communicating(scd->conn);
+	talloc_free(scd);
+}
+
 /* paging of the requested subscriber has completed */
 static int paging_cb_silent(unsigned int hooknum, unsigned int event,
 			    struct msgb *msg, void *_conn, void *_data)
 {
+	struct silent_call_data *scd = (struct silent_call_data *)_data;
 	struct ran_conn *conn = _conn;
 	struct scall_signal_data sigdata;
+	struct msgb *msg_ass;
 	int rc = 0;
+	int i;
 
 	if (hooknum != GSM_HOOK_RR_PAGING)
 		return -EINVAL;
@@ -45,7 +70,7 @@
 	DEBUGP(DLSMS, "paging_cb_silent: ");
 
 	sigdata.conn = conn;
-	sigdata.data = _data;
+	sigdata.data = scd->data;
 
 	switch (event) {
 	case GSM_PAGING_SUCCEEDED:
@@ -56,20 +81,58 @@
 			conn->lchan->ts->nr, conn->lchan->ts->trx->arfcn);
 #endif
 		conn->silent_call = 1;
+
+		/* Increment lchan reference count and mark as active*/
 		ran_conn_get(conn, RAN_CONN_USE_SILENT_CALL);
-		/* increment lchan reference count */
+
+		/* Schedule a timer to mark it as active */
+		scd->conn = conn;
+		osmo_timer_setup(&scd->timer, timer_cb, scd);
+		osmo_timer_schedule(&scd->timer, 0, 0);
+
+		/* Manually craft an assignement message with requested mode */
+		if (scd->ct.ch_indctr == GSM0808_CHAN_SPEECH) {
+			struct gsm0808_speech_codec_list scl;
+			union {
+				struct sockaddr_storage st;
+				struct sockaddr_in in;
+			} rtp_addr;
+
+			memset(&rtp_addr, 0, sizeof(rtp_addr));
+			rtp_addr.in.sin_family = AF_INET;
+			rtp_addr.in.sin_port = osmo_htons(scd->traffic_port);
+			rtp_addr.in.sin_addr.s_addr = inet_addr(scd->traffic_ip);
+
+			for (i=0; i<scd->ct.perm_spch_len; i++)
+				gsm0808_speech_codec_from_chan_type(&scl.codec[i], scd->ct.perm_spch[i]);
+			scl.len = scd->ct.perm_spch_len;
+
+			msg_ass = gsm0808_create_ass(&scd->ct, NULL, &rtp_addr.st, &scl, NULL);
+		} else {
+			msg_ass = gsm0808_create_ass(&scd->ct, NULL, NULL, NULL, NULL);
+		}
+
+		/* Send assignement message, hoping it will work */
+		osmo_sccp_tx_data_msg(conn->a.scu, conn->a.conn_id, msg_ass);
+
+		/* Signal completion */
 		osmo_signal_dispatch(SS_SCALL, S_SCALL_SUCCESS, &sigdata);
 		break;
+
 	case GSM_PAGING_EXPIRED:
 	case GSM_PAGING_BUSY:
 		DEBUGP(DLSMS, "expired\n");
 		osmo_signal_dispatch(SS_SCALL, S_SCALL_EXPIRED, &sigdata);
 		break;
+
 	default:
 		rc = -EINVAL;
 		break;
 	}
 
+	if (rc)
+		talloc_free(scd);
+
 	return rc;
 }
 
@@ -120,18 +183,33 @@
 
 
 /* initiate a silent call with a given subscriber */
-int gsm_silent_call_start(struct vlr_subscr *vsub, void *data, int type)
+int gsm_silent_call_start(struct vlr_subscr *vsub,
+	struct gsm0808_channel_type *ct,
+	const char *traffic_dst_ip, uint16_t traffic_dst_port,
+	void *data)
 {
 	struct subscr_request *req;
+	struct silent_call_data *scd;
 
-	/* FIXME the VTY command allows selecting a silent call channel type.
-	 * This doesn't apply to the situation after MSCSPLIT with an
-	 * A-interface. */
-	req = subscr_request_conn(vsub, paging_cb_silent, data,
+	scd = talloc_zero(vsub, struct silent_call_data);
+
+	memcpy(&scd->ct, ct, sizeof(struct gsm0808_channel_type));
+
+	if (traffic_dst_ip) {
+		strncpy(scd->traffic_ip, traffic_dst_ip, sizeof(scd->traffic_ip));
+		scd->traffic_port = traffic_dst_port;
+	}
+
+	scd->data = data;
+
+	req = subscr_request_conn(vsub, paging_cb_silent, scd,
 				  "establish silent call",
 				  SGSAP_SERV_IND_CS_CALL);
-	if (!req)
+	if (!req) {
+		talloc_free(scd);
 		return -ENODEV;
+	}
+
 	return 0;
 }
 

-- 
To view, visit https://gerrit.osmocom.org/13242
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-msc
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I82645708dd27864cf33ea9cc993ead0983415602
Gerrit-Change-Number: 13242
Gerrit-PatchSet: 1
Gerrit-Owner: tnt <tnt at 246tNt.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20190313/fa912780/attachment.htm>


More information about the gerrit-log mailing list