<p>laforge <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-sip-connector/+/25675">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  laforge: Looks good to me, but someone else must approve
  neels: Looks good to me, approved
  Jenkins Builder: Verified

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">MNCC v8: Implement Basic Support for Global Call Reference.<br><br>* Add GCR to mncc struct and therefore bump mncc version.<br>* Pass the GCR as a SIP Header to SIP UA and retrieve any such header<br>  from incoming SIP calls, passing the GCR on to MNCC<br><br>Related: #OS5164<br>Depends: osmo-msc I705c860e51637b4537cad65a330ecbaaca96dd5b<br>Change-Id: Id40d7e0fed9356f801b3627c118150055e7232b1<br>---<br>M src/call.h<br>M src/mncc.c<br>M src/mncc_protocol.h<br>M src/sip.c<br>4 files changed, 79 insertions(+), 1 deletion(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/call.h b/src/call.h</span><br><span>index d1732f9..8360711 100644</span><br><span>--- a/src/call.h</span><br><span>+++ b/src/call.h</span><br><span>@@ -31,6 +31,7 @@</span><br><span> </span><br><span>   const char *source;</span><br><span>  const char *dest;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct osmo_gcr_parsed gcr;</span><br><span> };</span><br><span> </span><br><span> enum {</span><br><span>diff --git a/src/mncc.c b/src/mncc.c</span><br><span>index 9d75950..fc99400 100644</span><br><span>--- a/src/mncc.c</span><br><span>+++ b/src/mncc.c</span><br><span>@@ -543,6 +543,7 @@</span><br><span>   leg->conn = conn;</span><br><span>         leg->state = MNCC_CC_INITIAL;</span><br><span>     leg->dir = MNCC_DIR_MO;</span><br><span style="color: hsl(120, 100%, 40%);">+    leg->base.call->gcr = data->gcr;</span><br><span>    memcpy(&leg->called, called, sizeof(leg->called));</span><br><span>         memcpy(&leg->calling, &data->calling, sizeof(leg->calling));</span><br><span>        memcpy(&leg->imsi, data->imsi, sizeof(leg->imsi));</span><br><span>@@ -898,6 +899,7 @@</span><br><span> </span><br><span>    mncc.fields |= MNCC_F_CALLING;</span><br><span>       mncc.calling.plan = GSM48_NPI_ISDN_E164;</span><br><span style="color: hsl(120, 100%, 40%);">+      mncc.gcr = call->gcr;</span><br><span> </span><br><span>         if (call->source && call->source[0] == '+') {</span><br><span>          mncc.calling.type = GSM48_TON_INTERNATIONAL;</span><br><span>diff --git a/src/mncc_protocol.h b/src/mncc_protocol.h</span><br><span>index 5d35191..11969ee 100644</span><br><span>--- a/src/mncc_protocol.h</span><br><span>+++ b/src/mncc_protocol.h</span><br><span>@@ -26,6 +26,7 @@</span><br><span> </span><br><span> #include <osmocom/core/linuxlist.h></span><br><span> #include <osmocom/gsm/mncc.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/gsm29205.h></span><br><span> </span><br><span> #include <stdint.h></span><br><span> #include <netinet/in.h></span><br><span>@@ -159,6 +160,7 @@</span><br><span> </span><br><span>       unsigned char   lchan_type;</span><br><span>  unsigned char   lchan_mode;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct osmo_gcr_parsed gcr;</span><br><span> </span><br><span>      /* A buffer to contain SDP ('\0' terminated) */</span><br><span>      char            sdp[1024];</span><br><span>@@ -170,7 +172,7 @@</span><br><span>     unsigned char   data[0];</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#define MNCC_SOCK_VERSION     7</span><br><span style="color: hsl(120, 100%, 40%);">+#define MNCC_SOCK_VERSION    8</span><br><span> struct gsm_mncc_hello {</span><br><span>         uint32_t        msg_type;</span><br><span>    uint32_t        version;</span><br><span>diff --git a/src/sip.c b/src/sip.c</span><br><span>index f0bc4c3..684ef74 100644</span><br><span>--- a/src/sip.c</span><br><span>+++ b/src/sip.c</span><br><span>@@ -26,6 +26,7 @@</span><br><span> </span><br><span> #include <osmocom/core/utils.h></span><br><span> #include <osmocom/core/socket.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/tlv.h></span><br><span> </span><br><span> #include <sofia-sip/sip_status.h></span><br><span> #include <sofia-sip/su_log.h></span><br><span>@@ -106,6 +107,34 @@</span><br><span>        nua_ack(leg->nua_handle, TAG_END());</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+int _osmo_dec_gcr(struct osmo_gcr_parsed *gcr, const uint8_t *elem, uint8_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint16_t parsed = 1; /* account for length byte right away */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (len < 13)</span><br><span style="color: hsl(120, 100%, 40%);">+              return -EBADMSG;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    gcr->net_len = elem[0];</span><br><span style="color: hsl(120, 100%, 40%);">+    if (gcr->net_len < 3 || gcr->net_len > 5)</span><br><span style="color: hsl(120, 100%, 40%);">+         return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     memcpy(gcr->net, elem + parsed, gcr->net_len);</span><br><span style="color: hsl(120, 100%, 40%);">+  /* +1 for ignored Node ID length field */</span><br><span style="color: hsl(120, 100%, 40%);">+     parsed += (gcr->net_len + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    gcr->node = osmo_load16be(elem + parsed);</span><br><span style="color: hsl(120, 100%, 40%);">+  parsed += 2;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (elem[parsed] != 5) /* see Table B 2.1.9.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+              return -ENOENT;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     parsed++;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   memcpy(gcr->cr, elem + parsed, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return parsed + 5;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static void new_call(struct sip_agent *agent, nua_handle_t *nh,</span><br><span>                   const sip_t *sip)</span><br><span> {</span><br><span>@@ -113,9 +142,20 @@</span><br><span>        struct sip_call_leg *leg;</span><br><span>    const char *from = NULL, *to = NULL;</span><br><span>         char ip_addr[INET6_ADDRSTRLEN];</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t gcr_back[28] = { 0 };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> </span><br><span>  LOGP(DSIP, LOGL_INFO, "Incoming call(%s) handle(%p)\n", sip->sip_call_id->i_id, nh);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+      sip_unknown_t *unknown_header = sip->sip_unknown;</span><br><span style="color: hsl(120, 100%, 40%);">+  while (unknown_header != NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+              if (!strcmp("X-Global-Call-Ref", unknown_header->un_name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     osmo_hexparse(unknown_header->un_value, gcr_back, sizeof(gcr_back));</span><br><span style="color: hsl(120, 100%, 40%);">+                       break;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+             unknown_header = unknown_header->un_next;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  if (!sdp_screen_sdp(sip)) {</span><br><span>          LOGP(DSIP, LOGL_ERROR, "No supported codec.\n");</span><br><span>           nua_respond(nh, SIP_406_NOT_ACCEPTABLE, TAG_END());</span><br><span>@@ -131,6 +171,8 @@</span><br><span>            return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ _osmo_dec_gcr(&call->gcr, gcr_back, sizeof(gcr_back));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>      if (sip->sip_to)</span><br><span>          to = sip->sip_to->a_url->url_user;</span><br><span>  if (sip->sip_from)</span><br><span>@@ -590,10 +632,38 @@</span><br><span>        leg->state = SIP_CC_CONNECTED;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Encode Global Call Reference. */</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t _osmo_enc_gcr(uint8_t *buf, const struct osmo_gcr_parsed *g)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t tmp[2];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!g)</span><br><span style="color: hsl(120, 100%, 40%);">+               return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (g->net_len < 3 || g->net_len > 5)</span><br><span style="color: hsl(120, 100%, 40%);">+             return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   buf = lv_put(buf, g->net_len, g->net);</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_store16be(g->node, &tmp);</span><br><span style="color: hsl(120, 100%, 40%);">+ buf = lv_put(buf, 2, tmp);</span><br><span style="color: hsl(120, 100%, 40%);">+    buf = lv_put(buf, 5, g->cr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Length: LV(Net) + LV(Node) + LV(CRef) - see 3GPP TS ยง3.2.2.115 */</span><br><span style="color: hsl(120, 100%, 40%);">+ return (g->net_len + 1) + (2 + 1) + (5 + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int send_invite(struct sip_agent *agent, struct sip_call_leg *leg,</span><br><span>                    const char *calling_num, const char *called_num)</span><br><span> {</span><br><span>        struct call_leg *other = leg->base.call->initial;</span><br><span style="color: hsl(120, 100%, 40%);">+       char gcr_hex[30];</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t data[15];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   gcr_hex[0] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+    data[0] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t len = _osmo_enc_gcr(data, &leg->base.call->gcr);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (len)</span><br><span style="color: hsl(120, 100%, 40%);">+              osmo_strlcpy(gcr_hex, osmo_hexdump_nospc(data, len*2+1), len*2+1);</span><br><span> </span><br><span>       char *from = talloc_asprintf(leg, "sip:%s@%s:%d",</span><br><span>                          calling_num,</span><br><span>@@ -605,6 +675,8 @@</span><br><span>                           agent->app->sip.remote_port);</span><br><span>  char *sdp = sdp_create_file(leg, other, sdp_sendrecv);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+    char *x_gcr = talloc_asprintf(leg, "X-Global-Call-Ref: %s", gcr_hex);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>    leg->state = SIP_CC_INITIAL;</span><br><span>      leg->dir = SIP_DIR_MT;</span><br><span>    nua_invite(leg->nua_handle,</span><br><span>@@ -612,6 +684,7 @@</span><br><span>                         SIPTAG_TO_STR(to),</span><br><span>                   NUTAG_MEDIA_ENABLE(0),</span><br><span>                       SIPTAG_CONTENT_TYPE_STR("application/sdp"),</span><br><span style="color: hsl(120, 100%, 40%);">+                 SIPTAG_HEADER_STR(x_gcr),</span><br><span>                    SIPTAG_PAYLOAD_STR(sdp),</span><br><span>                     TAG_END());</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-sip-connector/+/25675">change 25675</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-sip-connector/+/25675"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-sip-connector </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Id40d7e0fed9356f801b3627c118150055e7232b1 </div>
<div style="display:none"> Gerrit-Change-Number: 25675 </div>
<div style="display:none"> Gerrit-PatchSet: 4 </div>
<div style="display:none"> Gerrit-Owner: keith <keith@rhizomatica.org> </div>
<div style="display:none"> Gerrit-Assignee: neels <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: dexter <pmaier@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: neels <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-CC: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>