<p>neels has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-sip-connector/+/16222">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">forward full SDP between MNCC and SIP<br><br>Populate the new 'sdp' field added in MNCC v6, to enable full SDP codec<br>negotiation between osmo-msc and SIP.<br><br>Remove obsoleted code, since osmo-sip-connector now is fully out of the loop of<br>handling audio codecs in any way.<br><br>The only reason to parse or modify SDP is the recently added SIP re-INVITE<br>handling, which needs to set the send/recv modes via 'a=sendrecv',<br>a='sendonly', ... attributes.<br><br>Change-Id: I3df5d06f38ee2d122706a9ebffde7db4f2bd6bae<br>---<br>M src/call.c<br>M src/call.h<br>M src/mncc.c<br>M src/sip.c<br>M src/vty.c<br>5 files changed, 62 insertions(+), 68 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-sip-connector refs/changes/22/16222/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/call.c b/src/call.c</span><br><span>index 9f593ea..487be56 100644</span><br><span>--- a/src/call.c</span><br><span>+++ b/src/call.c</span><br><span>@@ -172,3 +172,13 @@</span><br><span> return "Unknown call type";</span><br><span> }</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void call_leg_update_sdp(struct call_leg *leg, const char *sdp)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ /* If no SDP was received, keep whatever SDP was previously seen. */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!sdp || !*sdp)</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_STRLCPY_ARRAY(leg->sdp, sdp);</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DAPP, LOGL_NOTICE, "call(%u) leg(0x%p) received SDP: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ leg->call->id, leg, leg->sdp);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/call.h b/src/call.h</span><br><span>index 7f67066..d19c9eb 100644</span><br><span>--- a/src/call.h</span><br><span>+++ b/src/call.h</span><br><span>@@ -118,12 +118,6 @@</span><br><span> struct nua_handle_s *nua_handle;</span><br><span> enum sip_cc_state state;</span><br><span> enum sip_dir dir;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* mo field */</span><br><span style="color: hsl(0, 100%, 40%);">- const char *wanted_codec;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* mt field */</span><br><span style="color: hsl(0, 100%, 40%);">- const char *sdp_payload;</span><br><span> };</span><br><span> </span><br><span> enum mncc_cc_state {</span><br><span>@@ -162,6 +156,8 @@</span><br><span> </span><br><span> struct call_leg *call_leg_other(struct call_leg *leg);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+void call_leg_update_sdp(struct call_leg *cl, const char *sdp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> void call_leg_release(struct call_leg *leg);</span><br><span> </span><br><span> </span><br><span>diff --git a/src/mncc.c b/src/mncc.c</span><br><span>index f2e2579..d74ed44 100644</span><br><span>--- a/src/mncc.c</span><br><span>+++ b/src/mncc.c</span><br><span>@@ -184,11 +184,13 @@</span><br><span> mncc.callref = leg->callref;</span><br><span> mncc.ip = ntohl(other->ip);</span><br><span> mncc.port = other->port;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Send payload_type as legacy compatibility, in addition full SDP. */</span><br><span> mncc.payload_type = other->payload_type;</span><br><span style="color: hsl(0, 100%, 40%);">- /*</span><br><span style="color: hsl(0, 100%, 40%);">- * FIXME: mncc.payload_msg_type should already be compatible.. but</span><br><span style="color: hsl(0, 100%, 40%);">- * payload_type should be different..</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Send full SDP info forwarded from SIP, since MNCC protocol version 6: */</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_STRLCPY_ARRAY(mncc.sdp, other->sdp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> struct in_addr net = { .s_addr = other->ip };</span><br><span> inet_ntop(AF_INET, &net, ip_addr, sizeof(ip_addr));</span><br><span> LOGP(DMNCC, LOGL_DEBUG, "SEND rtp_connect: IP=(%s) PORT=(%u)\n", ip_addr, mncc.port);</span><br><span>@@ -396,6 +398,8 @@</span><br><span> return mncc_send(conn, MNCC_REJ_REQ, rtp->callref);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ call_leg_update_sdp(&leg->base, rtp->sdp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* extract information about where the RTP is */</span><br><span> if (rtp->ip != 0 || rtp->port != 0 || rtp->payload_type != 0)</span><br><span> return;</span><br><span>@@ -433,6 +437,8 @@</span><br><span> leg->base.payload_type = rtp->payload_type;</span><br><span> leg->base.payload_msg_type = rtp->payload_msg_type;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ call_leg_update_sdp(&leg->base, rtp->sdp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* TODO.. now we can continue with the call */</span><br><span> struct in_addr net = { .s_addr = leg->base.ip };</span><br><span> inet_ntop(AF_INET, &net, ip_addr, sizeof(ip_addr));</span><br><span>@@ -501,7 +507,6 @@</span><br><span> return mncc_send(conn, MNCC_REJ_REQ, data->callref);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /* TODO.. bearer caps and better audio handling */</span><br><span> if (!continue_setup(conn, data)) {</span><br><span> LOGP(DMNCC, LOGL_ERROR,</span><br><span> "MNCC screening parameters failed leg(%u)\n", data->callref);</span><br><span>@@ -529,6 +534,9 @@</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> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* forward full SDP description of audio codecs */</span><br><span style="color: hsl(120, 100%, 40%);">+ call_leg_update_sdp(&leg->base, data->sdp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> LOGP(DMNCC, LOGL_INFO,</span><br><span> "Created call(%u) with MNCC leg(%u) IMSI(%.16s)\n",</span><br><span> call->id, leg->callref, data->imsi);</span><br><span>@@ -638,6 +646,8 @@</span><br><span> if (!leg)</span><br><span> return;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ call_leg_update_sdp(&leg->base, data->sdp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> LOGP(DMNCC, LOGL_INFO, "leg(%u) is now connected.\n", leg->callref);</span><br><span> stop_cmd_timer(leg, MNCC_SETUP_COMPL_IND);</span><br><span> leg->state = MNCC_CC_CONNECTED;</span><br><span>@@ -672,6 +682,8 @@</span><br><span> if (!leg)</span><br><span> return;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ call_leg_update_sdp(&leg->base, data->sdp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> LOGP(DMNCC, LOGL_DEBUG,</span><br><span> "leg(%u) confirmed. creating RTP socket.\n",</span><br><span> leg->callref);</span><br><span>@@ -690,6 +702,8 @@</span><br><span> if (!leg)</span><br><span> return;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ call_leg_update_sdp(&leg->base, data->sdp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> LOGP(DMNCC, LOGL_DEBUG,</span><br><span> "leg(%u) is alerting.\n", leg->callref);</span><br><span> </span><br><span>@@ -768,6 +782,8 @@</span><br><span> if (!leg)</span><br><span> return;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ call_leg_update_sdp(&leg->base, data->sdp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> LOGP(DMNCC, LOGL_DEBUG, "leg(%u) setup completed\n", leg->callref);</span><br><span> </span><br><span> other_leg = call_leg_other(&leg->base);</span><br><span>@@ -797,6 +813,8 @@</span><br><span> if (!leg)</span><br><span> return;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ call_leg_update_sdp(&leg->base, data->sdp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> LOGP(DMNCC, LOGL_DEBUG, "leg(%u) DTMF key=%c\n", leg->callref, data->keypad);</span><br><span> </span><br><span> other_leg = call_leg_other(&leg->base);</span><br><span>@@ -819,6 +837,8 @@</span><br><span> if (!leg)</span><br><span> return;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ call_leg_update_sdp(&leg->base, data->sdp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> LOGP(DMNCC, LOGL_DEBUG, "leg(%u) DTMF key=%c\n", leg->callref, data->keypad);</span><br><span> </span><br><span> mncc_fill_header(&out_mncc, MNCC_STOP_DTMF_RSP, leg->callref);</span><br><span>@@ -898,12 +918,12 @@</span><br><span> OSMO_STRLCPY_ARRAY(mncc.called.number, call->dest);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /*</span><br><span style="color: hsl(0, 100%, 40%);">- * TODO/FIXME:</span><br><span style="color: hsl(0, 100%, 40%);">- * - Determine/request channel based on offered audio codecs</span><br><span style="color: hsl(0, 100%, 40%);">- * - Screening, redirect?</span><br><span style="color: hsl(0, 100%, 40%);">- * - Synth. the bearer caps based on codecs?</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* The call->initial leg is a SIP call leg that starts an MT call. There was SDP received in the SIP INVITE that</span><br><span style="color: hsl(120, 100%, 40%);">+ * started this call. This here will be the call->remote, always forwarding the SDP that came in on</span><br><span style="color: hsl(120, 100%, 40%);">+ * call->initial. */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (call->initial)</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_STRLCPY_ARRAY(mncc.sdp, call->initial->sdp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> rc = write(conn->fd.fd, &mncc, sizeof(mncc));</span><br><span> if (rc != sizeof(mncc)) {</span><br><span> LOGP(DMNCC, LOGL_ERROR, "Failed to send message leg(%u)\n",</span><br><span>diff --git a/src/sip.c b/src/sip.c</span><br><span>index 5eaa94b..70551c5 100644</span><br><span>--- a/src/sip.c</span><br><span>+++ b/src/sip.c</span><br><span>@@ -43,6 +43,12 @@</span><br><span> static void sip_hold_call(struct call_leg *_leg);</span><br><span> static void sip_retrieve_call(struct call_leg *_leg);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static const char *sip_get_sdp(const sip_t *sip)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!sip || !sip->sip_payload)</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ return sip->sip_payload->pl_data;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span> /* Find a SIP Call leg by given nua_handle */</span><br><span> static struct sip_call_leg *sip_find_leg(nua_handle_t *nh)</span><br><span>@@ -72,17 +78,12 @@</span><br><span> if (!other)</span><br><span> return;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /* Extract SDP for session in progress with matching codec */</span><br><span style="color: hsl(0, 100%, 40%);">- if (status == 183)</span><br><span style="color: hsl(0, 100%, 40%);">- sdp_extract_sdp(leg, sip, false);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> LOGP(DSIP, LOGL_INFO, "leg(%p) is now progressing.\n", leg);</span><br><span> other->ring_call(other);</span><br><span> }</span><br><span> </span><br><span> static void call_connect(struct sip_call_leg *leg, const sip_t *sip)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- /* extract SDP file and if compatible continue */</span><br><span> struct call_leg *other = call_leg_other(&leg->base);</span><br><span> </span><br><span> if (!other) {</span><br><span>@@ -91,13 +92,6 @@</span><br><span> return;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (!sdp_extract_sdp(leg, sip, false)) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DSIP, LOGL_ERROR, "leg(%p) incompatible audio, releasing\n", leg);</span><br><span style="color: hsl(0, 100%, 40%);">- nua_cancel(leg->nua_handle, TAG_END());</span><br><span style="color: hsl(0, 100%, 40%);">- other->release_call(other);</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> LOGP(DSIP, LOGL_INFO, "leg(%p) is now connected(%s).\n", leg, sip->sip_call_id->i_id);</span><br><span> leg->state = SIP_CC_CONNECTED;</span><br><span> other->connect_call(other);</span><br><span>@@ -114,20 +108,8 @@</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(0, 100%, 40%);">- if (!sdp_screen_sdp(sip)) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DSIP, LOGL_ERROR, "No supported codec.\n");</span><br><span style="color: hsl(0, 100%, 40%);">- nua_respond(nh, SIP_406_NOT_ACCEPTABLE, TAG_END());</span><br><span style="color: hsl(0, 100%, 40%);">- nua_handle_destroy(nh);</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> call = call_sip_create();</span><br><span style="color: hsl(0, 100%, 40%);">- if (!call) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DSIP, LOGL_ERROR, "No supported codec.\n");</span><br><span style="color: hsl(0, 100%, 40%);">- nua_respond(nh, SIP_500_INTERNAL_SERVER_ERROR, TAG_END());</span><br><span style="color: hsl(0, 100%, 40%);">- nua_handle_destroy(nh);</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(call);</span><br><span> </span><br><span> if (sip->sip_to)</span><br><span> to = sip->sip_to->a_url->url_user;</span><br><span>@@ -145,27 +127,6 @@</span><br><span> leg->state = SIP_CC_DLG_CNFD;</span><br><span> leg->dir = SIP_DIR_MO;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /*</span><br><span style="color: hsl(0, 100%, 40%);">- * FIXME/TODO.. we need to select the codec at some point. But it is</span><br><span style="color: hsl(0, 100%, 40%);">- * not this place. It starts with the TCH/F vs. TCH/H selection based</span><br><span style="color: hsl(0, 100%, 40%);">- * on the offered codecs, and then RTP_CREATE should have it. So both</span><br><span style="color: hsl(0, 100%, 40%);">- * are GSM related... and do not belong here. Just pick the first codec</span><br><span style="color: hsl(0, 100%, 40%);">- * so the IP address, port and payload type is set.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">- if (!sdp_extract_sdp(leg, sip, true)) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DSIP, LOGL_ERROR, "leg(%p) no audio, releasing\n", leg);</span><br><span style="color: hsl(0, 100%, 40%);">- nua_respond(nh, SIP_406_NOT_ACCEPTABLE, TAG_END());</span><br><span style="color: hsl(0, 100%, 40%);">- nua_handle_destroy(nh);</span><br><span style="color: hsl(0, 100%, 40%);">- call_leg_release(&leg->base);</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- struct in_addr net = { .s_addr = leg->base.ip };</span><br><span style="color: hsl(0, 100%, 40%);">- inet_ntop(AF_INET, &net, ip_addr, sizeof(ip_addr));</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DSIP, LOGL_INFO, "SDP Extracted: IP=(%s) PORT=(%u) PAYLOAD=(%u).\n",</span><br><span style="color: hsl(0, 100%, 40%);">- ip_addr,</span><br><span style="color: hsl(0, 100%, 40%);">- leg->base.port,</span><br><span style="color: hsl(0, 100%, 40%);">- leg->base.payload_type);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> leg->base.release_call = sip_release_call;</span><br><span> leg->base.ring_call = sip_ring_call;</span><br><span> leg->base.connect_call = sip_connect_call;</span><br><span>@@ -175,7 +136,8 @@</span><br><span> leg->agent = agent;</span><br><span> leg->nua_handle = nh;</span><br><span> nua_handle_bind(nh, leg);</span><br><span style="color: hsl(0, 100%, 40%);">- leg->sdp_payload = talloc_strdup(leg, sip->sip_payload->pl_data);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ call_leg_update_sdp(&leg->base, sip_get_sdp(sip));</span><br><span> </span><br><span> app_route_call(call,</span><br><span> talloc_strdup(leg, from),</span><br><span>@@ -218,6 +180,8 @@</span><br><span> inet_ntop(AF_INET, &net, ip_addr, sizeof(ip_addr));</span><br><span> LOGP(DSIP, LOGL_DEBUG, "pre re-INVITE have IP:port (%s:%u)\n", ip_addr, leg->base.port);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ call_leg_update_sdp(&leg->base, sip_get_sdp(sip));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> if (mode == sdp_sendonly) {</span><br><span> /* SIP side places call on HOLD */</span><br><span> sdp = sdp_create_file(leg, other, sdp_recvonly);</span><br><span>@@ -330,6 +294,8 @@</span><br><span> struct sip_call_leg *leg;</span><br><span> leg = (struct sip_call_leg *) hmagic;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ call_leg_update_sdp(&leg->base, sip_get_sdp(sip));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* MT call is moving forward */</span><br><span> </span><br><span> /* The dialogue is now confirmed */</span><br><span>@@ -366,8 +332,10 @@</span><br><span> * respond to the re-INVITE query. */</span><br><span> if (sip->sip_payload && sip->sip_payload->pl_data) {</span><br><span> struct sip_call_leg *leg = sip_find_leg(nh);</span><br><span style="color: hsl(0, 100%, 40%);">- if (leg)</span><br><span style="color: hsl(120, 100%, 40%);">+ if (leg) {</span><br><span style="color: hsl(120, 100%, 40%);">+ call_leg_update_sdp(&leg->base, sip_get_sdp(sip));</span><br><span> sip_handle_reinvite(leg, nh, sip);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> }</span><br><span> } else if (event == nua_r_bye || event == nua_r_cancel) {</span><br><span> /* our bye or hang up is answered */</span><br><span>@@ -393,9 +361,10 @@</span><br><span> </span><br><span> if (status == 100) {</span><br><span> struct sip_call_leg *leg = sip_find_leg(nh);</span><br><span style="color: hsl(0, 100%, 40%);">- if (leg)</span><br><span style="color: hsl(120, 100%, 40%);">+ if (leg) {</span><br><span style="color: hsl(120, 100%, 40%);">+ call_leg_update_sdp(&leg->base, sip_get_sdp(sip));</span><br><span> sip_handle_reinvite(leg, nh, sip);</span><br><span style="color: hsl(0, 100%, 40%);">- else</span><br><span style="color: hsl(120, 100%, 40%);">+ } else</span><br><span> new_call((struct sip_agent *) magic, nh, sip);</span><br><span> }</span><br><span> } else if (event == nua_i_cancel) {</span><br><span>diff --git a/src/vty.c b/src/vty.c</span><br><span>index ea76d46..863f9c1 100644</span><br><span>--- a/src/vty.c</span><br><span>+++ b/src/vty.c</span><br><span>@@ -211,7 +211,6 @@</span><br><span> get_value_string(sip_state_vals, sip->state), VTY_NEWLINE);</span><br><span> vty_out(vty, " SIP dir(%s)%s",</span><br><span> get_value_string(sip_dir_vals, sip->dir), VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out(vty, " SIP wanted_codec(%s)%s", sip->wanted_codec, VTY_NEWLINE);</span><br><span> break;</span><br><span> case CALL_TYPE_MNCC:</span><br><span> mncc = (struct mncc_call_leg *) leg;</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-sip-connector/+/16222">change 16222</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/+/16222"/><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: I3df5d06f38ee2d122706a9ebffde7db4f2bd6bae </div>
<div style="display:none"> Gerrit-Change-Number: 16222 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: neels <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>