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 <t...@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 <t...@246tnt.com>

Reply via email to