Created
January 8, 2018 10:46
-
-
Save alfredh/f0a9ae4e913300782e8c4a91a8512a49 to your computer and use it in GitHub Desktop.
SR branches
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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