Skip to content

Instantly share code, notes, and snippets.

@alfredh
Created January 8, 2018 10:46
Show Gist options
  • Save alfredh/f0a9ae4e913300782e8c4a91a8512a49 to your computer and use it in GitHub Desktop.
Save alfredh/f0a9ae4e913300782e8c4a91a8512a49 to your computer and use it in GitHub Desktop.
SR branches
diff --git a/.travis.yml b/.travis.yml
index 093f30f..1074af5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -19,7 +19,7 @@ addons:
libssl-dev
install:
- - git clone https://github.com/creytiv/re.git
+ - git clone -b sr https://github.com/creytiv/re.git
- git clone https://github.com/creytiv/rem.git
- curl -OL 'https://github.com/alfredh/pytools/raw/master/ccheck.py'
- for p in ${LIBRE} ${LIBREM}; do cd $p && sudo PATH="$PATH" make install && cd - && sudo rm -Rf $p; done
diff --git a/include/baresip.h b/include/baresip.h
index 526354d..8b012fa 100644
--- a/include/baresip.h
+++ b/include/baresip.h
@@ -177,6 +177,7 @@ struct config_sip {
char uuid[64]; /**< Universally Unique Identifier */
char local[64]; /**< Local SIP Address */
char cert[256]; /**< SIP Certificate */
+ uint32_t timer_t1; /**< SIP Transaction Timer T1 [ms] */
};
/** Call config */
diff --git a/src/audio.c b/src/audio.c
index b5ce913..b581697 100644
--- a/src/audio.c
+++ b/src/audio.c
@@ -890,6 +890,15 @@ static int aurx_stream_decode(struct aurx *rx, struct mbuf *mb)
return err;
}
+/* Sync interval in [sec], this value perhaps should be set in config file. */
+#define SYNC_INTERVAL (10.0)
+
+
+static inline int32_t ts_diff(uint32_t x, uint32_t y)
+{
+ return (int32_t)(y - x);
+}
+
/* Handle incoming stream data from the network */
static void stream_recv_handler(const struct rtp_header *hdr,
@@ -898,9 +907,14 @@ static void stream_recv_handler(const struct rtp_header *hdr,
{
struct audio *a = arg;
struct aurx *rx = &a->rx;
+ const struct config_avt *avt = &a->strm->cfg;
bool discard = false;
size_t i;
int wrap;
+ double wall_clock=0;
+ double dur=0;
+ double skew=0;
+ double max_skew=0;
int err;
if (!mb)
@@ -998,11 +1012,52 @@ static void stream_recv_handler(const struct rtp_header *hdr,
break;
}
+ /* Save the last RTP timestamp */
rx->ts_recv.last = hdr->ts;
+ /*
+ * Check for obsolete (old) packets
+ */
+
+ if (hdr->m)
+ rx->ts_recv.is_synced = false;
+
+ if (rx->ts_recv.is_synced) {
+ uint64_t now = tmr_jiffies();
+ int32_t ts_delta;
+
+ ts_delta = ts_diff(rx->ts_recv.ts_rtp_sync, hdr->ts);
+
+ wall_clock = (double)(now - rx->ts_recv.ts_clk_sync) / 1000.0;
+ dur = audio_calc_seconds(ts_delta, rx->ac->crate);
+ skew = wall_clock - dur;
+
+ /* positive skew: the packet arrived too late
+ * negative skew: the packet arrived too early
+ * Max skew is calulated from rx ptime * Jb_max / 1000
+ */
+ /* this might be better if calculated once when stream is
+ * set up and we know the RX ptime, --> store in struct Audio
+ */
+ max_skew = avt->jbuf_del.max * rx->ptime / 1000.0;
+
+ if (skew > max_skew) {
+ warning("audio: packet arrived too late"
+ " (skew %.3f > %.3f sec)\n",
+ skew, (double)max_skew);
+ discard = true;
+ }
+ else if (wall_clock > SYNC_INTERVAL) {
+ rx->ts_recv.is_synced = false;
+ }
+ }
+
#if 0
- re_printf("[time=%.3f] wrap=%d discard=%d\n",
- aurx_calc_seconds(rx), wrap, discard);
+ re_printf("[%s] [wallclock=%.3f] [rtp_time=%.3f] skew=%.3f"
+ " wrap=%d discard=%d (n_discard=%u)\n",
+ hdr->m ? "M" : " ",
+ wall_clock, dur, skew,
+ wrap, discard, a->rx.n_discard);
#endif
if (discard) {
@@ -1012,6 +1067,16 @@ static void stream_recv_handler(const struct rtp_header *hdr,
out:
(void)aurx_stream_decode(&a->rx, mb);
+
+ /* Sync on valid packets */
+ if (!rx->ts_recv.is_synced) {
+
+ rx->ts_recv.ts_rtp_sync = hdr->ts;
+ rx->ts_recv.ts_clk_sync = tmr_jiffies();
+ rx->ts_recv.is_synced = true;
+
+ info("audio: *** synced timestamps ***\n");
+ }
}
diff --git a/src/config.c b/src/config.c
index 1d010e0..b27c37e 100644
--- a/src/config.c
+++ b/src/config.c
@@ -220,6 +220,7 @@ int config_parse_conf(struct config *cfg, const struct conf *conf)
sizeof(cfg->sip.local));
(void)conf_get_str(conf, "sip_certificate", cfg->sip.cert,
sizeof(cfg->sip.cert));
+ conf_get_u32(conf, "sip_timer_t1", &cfg->sip.timer_t1);
/* Call */
(void)conf_get_u32(conf, "call_local_timeout",
diff --git a/src/core.h b/src/core.h
index 6e48e5d..161e994 100644
--- a/src/core.h
+++ b/src/core.h
@@ -490,6 +490,10 @@ struct timestamp_recv {
uint32_t last;
bool is_set;
unsigned num_wraps;
+
+ bool is_synced;
+ uint32_t ts_rtp_sync; /* RTP timestamp when synced */
+ uint64_t ts_clk_sync; /* Time when we synced [ms] */
};
diff --git a/src/ua.c b/src/ua.c
index 0467e35..111ac27 100644
--- a/src/ua.c
+++ b/src/ua.c
@@ -1333,6 +1333,7 @@ int ua_init(const char *software, bool udp, bool tcp, bool tls,
{
struct config *cfg = conf_config();
struct network *net = baresip_network();
+ struct sip_conf sipconf;
uint32_t bsize;
int err;
@@ -1358,6 +1359,18 @@ int ua_init(const char *software, bool udp, bool tcp, bool tls,
goto out;
}
+ /* configure SIP timers */
+
+ sipconf = *sip_conf(uag.sip);
+
+ if (cfg->sip.timer_t1)
+ sipconf.timer_t1 = cfg->sip.timer_t1;
+
+ sip_conf_set(uag.sip, &sipconf);
+
+ debug("ua: using SIP timers T1=%u (milliseconds)\n",
+ sip_conf(uag.sip)->timer_t1);
+
err = ua_add_transp(net);
if (err)
goto out;
diff --git a/include/re_sip.h b/include/re_sip.h
index 9a2af7a..5f9fdb0 100644
--- a/include/re_sip.h
+++ b/include/re_sip.h
@@ -221,6 +221,13 @@ struct sip_contact {
enum sip_transp tp;
};
+/** SIP Configuration */
+struct sip_conf {
+ uint32_t timer_t1; /**< Transaction Timer T1 [ms] */
+ uint32_t timer_t2; /**< Transaction Timer T2 [ms] */
+ uint32_t timer_t4; /**< Transaction Timer T4 [ms] */
+};
+
struct sip;
struct sip_lsnr;
struct sip_request;
@@ -253,6 +260,8 @@ int sip_listen(struct sip_lsnr **lsnrp, struct sip *sip, bool req,
int sip_debug(struct re_printf *pf, const struct sip *sip);
int sip_send(struct sip *sip, void *sock, enum sip_transp tp,
const struct sa *dst, struct mbuf *mb);
+void sip_conf_set(struct sip *sip, const struct sip_conf *conf);
+const struct sip_conf *sip_conf(const struct sip *sip);
/* transport */
@@ -368,3 +377,21 @@ int sip_cseq_decode(struct sip_cseq *cseq, const struct pl *pl);
int sip_keepalive_start(struct sip_keepalive **kap, struct sip *sip,
const struct sip_msg *msg, uint32_t interval,
sip_keepalive_h *kah, void *arg);
+
+
+static inline uint32_t sip_t1(const struct sip *sip)
+{
+ return sip_conf(sip)->timer_t1;
+}
+
+
+static inline uint32_t sip_t2(const struct sip *sip)
+{
+ return sip_conf(sip)->timer_t2;
+}
+
+
+static inline uint32_t sip_t4(const struct sip *sip)
+{
+ return sip_conf(sip)->timer_t4;
+}
diff --git a/src/sip/ctrans.c b/src/sip/ctrans.c
index 0ff3266..224ba4a 100644
--- a/src/sip/ctrans.c
+++ b/src/sip/ctrans.c
@@ -187,15 +187,15 @@ static void retransmit_handler(void *arg)
switch (ct->state) {
case TRYING:
- timeout = MIN(SIP_T1<<ct->txc, SIP_T2);
+ timeout = MIN(sip_t1(ct->sip)<<ct->txc, sip_t2(ct->sip));
break;
case CALLING:
- timeout = SIP_T1<<ct->txc;
+ timeout = sip_t1(ct->sip)<<ct->txc;
break;
case PROCEEDING:
- timeout = SIP_T2;
+ timeout = sip_t2(ct->sip);
break;
default:
@@ -294,7 +294,7 @@ static bool response_handler(const struct sip_msg *msg, void *arg)
break;
}
- tmr_start(&ct->tmr, SIP_T4, tmr_handler, ct);
+ tmr_start(&ct->tmr, sip_t4(ct->sip), tmr_handler, ct);
tmr_cancel(&ct->tmre);
}
break;
@@ -340,10 +340,11 @@ int sip_ctrans_request(struct sip_ctrans **ctp, struct sip *sip,
if (err)
goto out;
- tmr_start(&ct->tmr, 64 * SIP_T1, tmr_handler, ct);
+ tmr_start(&ct->tmr, 64 * sip_t1(sip), tmr_handler, ct);
- if (!sip_transp_reliable(ct->tp))
- tmr_start(&ct->tmre, SIP_T1, retransmit_handler, ct);
+ if (!sip_transp_reliable(ct->tp)) {
+ tmr_start(&ct->tmre, sip_t1(sip), retransmit_handler, ct);
+ }
out:
if (err)
@@ -370,7 +371,7 @@ int sip_ctrans_cancel(struct sip_ctrans *ct)
switch (ct->state) {
case PROCEEDING:
- tmr_start(&ct->tmr, 64 * SIP_T1, tmr_handler, ct);
+ tmr_start(&ct->tmr, 64 * sip_t1(ct->sip), tmr_handler, ct);
break;
default:
diff --git a/src/sip/sip.c b/src/sip/sip.c
index 651628c..211c0dc 100644
--- a/src/sip/sip.c
+++ b/src/sip/sip.c
@@ -20,6 +20,13 @@
#include "sip.h"
+static const struct sip_conf conf_default = {
+ SIP_T1,
+ SIP_T2,
+ SIP_T4
+};
+
+
static void destructor(void *arg)
{
struct sip *sip = arg;
@@ -126,6 +133,7 @@ int sip_alloc(struct sip **sipp, struct dnsc *dnsc, uint32_t ctsz,
sip->dnsc = mem_ref(dnsc);
sip->exith = exith;
sip->arg = arg;
+ sip->conf = conf_default;
out:
if (err)
@@ -215,6 +223,37 @@ int sip_listen(struct sip_lsnr **lsnrp, struct sip *sip, bool req,
}
+/**
+ * Set SIP configuration object
+ *
+ * @param sip SIP Stack instance
+ * @param SIP configuration
+ */
+void sip_conf_set(struct sip *sip, const struct sip_conf *conf)
+{
+ if (!sip || !conf)
+ return;
+
+ sip->conf = *conf;
+}
+
+
+/**
+ * Get SIP configuration object
+ *
+ * @param sip SIP Stack instance
+ *
+ * @return SIP configuration
+ */
+const struct sip_conf *sip_conf(const struct sip *sip)
+{
+ if (sip)
+ return &sip->conf;
+ else
+ return &conf_default;
+}
+
+
/**
* Print debug information about the SIP stack
*
diff --git a/src/sip/sip.h b/src/sip/sip.h
index 912c69b..773f8cf 100644
--- a/src/sip/sip.h
+++ b/src/sip/sip.h
@@ -9,6 +9,7 @@ struct sip {
struct list transpl;
struct list lsnrl;
struct list reql;
+ struct sip_conf conf;
struct hash *ht_ctrans;
struct hash *ht_strans;
struct hash *ht_strans_mrg;
diff --git a/src/sip/strans.c b/src/sip/strans.c
index 13a875c..5810ea2 100644
--- a/src/sip/strans.c
+++ b/src/sip/strans.c
@@ -161,8 +161,8 @@ static void retransmit_handler(void *arg)
st->mb);
st->txc++;
- tmr_start(&st->tmrg, MIN(SIP_T1<<st->txc, SIP_T2), retransmit_handler,
- st);
+ tmr_start(&st->tmrg, MIN(sip_t1(st->sip)<<st->txc, sip_t2(st->sip)),
+ retransmit_handler, st);
}
@@ -188,7 +188,7 @@ static bool ack_handler(struct sip *sip, const struct sip_msg *msg)
break;
}
- tmr_start(&st->tmr, SIP_T4, tmr_handler, st);
+ tmr_start(&st->tmr, sip_t4(sip), tmr_handler, st);
tmr_cancel(&st->tmrg);
st->state = CONFIRMED;
break;
@@ -367,15 +367,15 @@ int sip_strans_reply(struct sip_strans **stp, struct sip *sip,
st->state = PROCEEDING;
}
else if (scode < 300) {
- tmr_start(&st->tmr, 64 * SIP_T1, tmr_handler, st);
+ tmr_start(&st->tmr, 64 * sip_t1(sip), tmr_handler, st);
st->state = ACCEPTED;
}
else {
- tmr_start(&st->tmr, 64 * SIP_T1, tmr_handler, st);
+ tmr_start(&st->tmr, 64 * sip_t1(sip), tmr_handler, st);
st->state = COMPLETED;
if (!sip_transp_reliable(st->msg->tp))
- tmr_start(&st->tmrg, SIP_T1,
+ tmr_start(&st->tmrg, sip_t1(sip),
retransmit_handler, st);
}
}
@@ -385,8 +385,8 @@ int sip_strans_reply(struct sip_strans **stp, struct sip *sip,
}
else {
if (!sip_transp_reliable(st->msg->tp)) {
- tmr_start(&st->tmr, 64 * SIP_T1, tmr_handler,
- st);
+ tmr_start(&st->tmr, 64 * sip_t1(sip),
+ tmr_handler, st);
st->state = COMPLETED;
}
else {
diff --git a/src/sipsess/ack.c b/src/sipsess/ack.c
index 4a9be68..23bf5de 100644
--- a/src/sipsess/ack.c
+++ b/src/sipsess/ack.c
@@ -27,6 +27,7 @@ struct sipsess_ack {
struct mbuf *mb;
enum sip_transp tp;
uint32_t cseq;
+ struct sip *sip;
};
@@ -61,7 +62,7 @@ static int send_handler(enum sip_transp tp, const struct sa *src,
ack->dst = *dst;
ack->tp = tp;
- tmr_start(&ack->tmr, 64 * SIP_T1, tmr_handler, ack);
+ tmr_start(&ack->tmr, 64 * sip_t1(ack->sip), tmr_handler, ack);
return 0;
}
@@ -94,6 +95,7 @@ int sipsess_ack(struct sipsess_sock *sock, struct sip_dialog *dlg,
ack->dlg = mem_ref(dlg);
ack->cseq = cseq;
+ ack->sip = sock->sip;
err = sip_drequestf(&ack->req, sock->sip, false, "ACK", dlg, cseq,
auth, send_handler, resp_handler, ack,
diff --git a/src/sipsess/reply.c b/src/sipsess/reply.c
index 4c3aa6f..7b15998 100644
--- a/src/sipsess/reply.c
+++ b/src/sipsess/reply.c
@@ -72,7 +72,8 @@ static void retransmit_handler(void *arg)
&reply->msg->src, reply->mb);
reply->txc++;
- tmr_start(&reply->tmrg, MIN(SIP_T1<<reply->txc, SIP_T2),
+ tmr_start(&reply->tmrg, MIN(sip_t1(reply->sess->sip)<<reply->txc,
+ sip_t2(reply->sess->sip)),
retransmit_handler, reply);
}
@@ -116,8 +117,8 @@ int sipsess_reply_2xx(struct sipsess *sess, const struct sip_msg *msg,
if (err)
goto out;
- tmr_start(&reply->tmr, 64 * SIP_T1, tmr_handler, reply);
- tmr_start(&reply->tmrg, SIP_T1, retransmit_handler, reply);
+ tmr_start(&reply->tmr, 64 * sip_t1(sess->sip), tmr_handler, reply);
+ tmr_start(&reply->tmrg, sip_t1(sess->sip), retransmit_handler, reply);
if (!mbuf_get_left(msg->mb) && desc) {
reply->awaiting_answer = true;
diff --git a/src/tmr/tmr.c b/src/tmr/tmr.c
index 73083f1..4ce6152 100644
--- a/src/tmr/tmr.c
+++ b/src/tmr/tmr.c
@@ -132,6 +132,17 @@ uint64_t tmr_jiffies(void)
li.LowPart = ft.dwLowDateTime;
li.HighPart = ft.dwHighDateTime;
jfs = li.QuadPart/10/1000;
+#elif HAVE_CLOCK_GETTIME && defined (CLOCK_MONOTONIC)
+
+ struct timespec now;
+
+ if (0 != clock_gettime(CLOCK_MONOTONIC, &now)) {
+ DEBUG_WARNING("jiffies: clock_gettime() failed (%m)\n", errno);
+ return 0;
+ }
+
+ jfs = (long)now.tv_sec * (uint64_t)1000;
+ jfs += now.tv_nsec / (uint64_t)1000000;
#else
struct timeval now;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment