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.orgtnt has submitted this change and it was merged. ( 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
---
M include/osmocom/msc/silent_call.h
M src/libmsc/msc_vty.c
M src/libmsc/silent_call.c
3 files changed, 160 insertions(+), 23 deletions(-)
Approvals:
Max: Looks good to me, but someone else must approve
Vadim Yanitskiy: Looks good to me, but someone else must approve
tnt: Looks good to me, approved
Jenkins Builder: Verified
diff --git a/include/osmocom/msc/silent_call.h b/include/osmocom/msc/silent_call.h
index 70324e5..ca36052 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);
+ const 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 ac3946a..6404ee9 100644
--- a/src/libmsc/msc_vty.c
+++ b/src/libmsc/msc_vty.c
@@ -1066,21 +1066,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-65535>]",
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;
+ uint16_t port;
+ int rc, speech;
if (!vsub) {
vty_out(vty, "%% No subscriber found for %s %s%s",
@@ -1088,16 +1102,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..7effba3 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,10 +81,52 @@
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 */
+ /* This is a hack we we can't call ran_conn_communicating
+ * from here because we're in the call back context of
+ * a RAN FSM event but before it actually changes its own
+ * state and it's not ready to accept this.
+ * Of all alternatives considered, making the call in an
+ * 'immediate timer' is the least disruptive and least ugly
+ * way to do it I could find.
+ */
+ 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;
+ return 0;
+
case GSM_PAGING_EXPIRED:
case GSM_PAGING_BUSY:
DEBUGP(DLSMS, "expired\n");
@@ -70,6 +137,8 @@
break;
}
+ talloc_free(scd);
+
return rc;
}
@@ -120,18 +189,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,
+ const 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(scd->ct));
+
+ 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: merged
Gerrit-Change-Id: I82645708dd27864cf33ea9cc993ead0983415602
Gerrit-Change-Number: 13242
Gerrit-PatchSet: 4
Gerrit-Owner: tnt <tnt at 246tNt.com>
Gerrit-Reviewer: Jenkins Builder (1000002)
Gerrit-Reviewer: Max <msuraev at sysmocom.de>
Gerrit-Reviewer: Vadim Yanitskiy <axilirator at gmail.com>
Gerrit-Reviewer: tnt <tnt at 246tNt.com>
Gerrit-CC: Harald Welte <laforge at gnumonks.org>
Gerrit-CC: Pau Espin Pedrol <pespin at sysmocom.de>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20190314/b48395b0/attachment.htm>