Squashed 'third_party/rawrtc/re/' content from commit f3163ce8b
Change-Id: I6a235e6ac0f03269d951026f9d195da05c40fdab
git-subtree-dir: third_party/rawrtc/re
git-subtree-split: f3163ce8b526a13b35ef71ce4dd6f43585064d8a
diff --git a/src/sip/keepalive.c b/src/sip/keepalive.c
new file mode 100644
index 0000000..1e1594f
--- /dev/null
+++ b/src/sip/keepalive.c
@@ -0,0 +1,115 @@
+/**
+ * @file sip/keepalive.c SIP Keepalive
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+
+#include <string.h>
+#include <re_types.h>
+#include <re_fmt.h>
+#include <re_mem.h>
+#include <re_mbuf.h>
+#include <re_sa.h>
+#include <re_list.h>
+#include <re_sys.h>
+#include <re_uri.h>
+#include <re_udp.h>
+#include <re_msg.h>
+#include <re_sip.h>
+#include "sip.h"
+
+
+static void destructor(void *arg)
+{
+ struct sip_keepalive *ka = arg;
+
+ if (ka->kap)
+ *ka->kap = NULL;
+
+ list_unlink(&ka->le);
+}
+
+
+void sip_keepalive_signal(struct list *kal, int err)
+{
+ struct le *le = list_head(kal);
+
+ while (le) {
+
+ struct sip_keepalive *ka = le->data;
+ sip_keepalive_h *kah = ka->kah;
+ void *arg = ka->arg;
+
+ le = le->next;
+
+ list_unlink(&ka->le);
+ mem_deref(ka);
+
+ kah(err, arg);
+ }
+}
+
+
+uint64_t sip_keepalive_wait(uint32_t interval)
+{
+ return interval * (800 + rand_u16() % 201);
+}
+
+
+/**
+ * Start a keepalive handler on a SIP transport
+ *
+ * @param kap Pointer to allocated keepalive object
+ * @param sip SIP Stack instance
+ * @param msg SIP Message
+ * @param interval Keepalive interval in seconds
+ * @param kah Keepalive handler
+ * @param arg Handler argument
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+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)
+{
+ struct sip_keepalive *ka;
+ int err;
+
+ if (!kap || !sip || !msg || !kah)
+ return EINVAL;
+
+ ka = mem_zalloc(sizeof(*ka), destructor);
+ if (!ka)
+ return ENOMEM;
+
+ ka->kah = kah;
+ ka->arg = arg;
+
+ switch (msg->tp) {
+
+ case SIP_TRANSP_UDP:
+ err = sip_keepalive_udp(ka, sip, (struct udp_sock *)msg->sock,
+ &msg->src, interval);
+ break;
+
+ case SIP_TRANSP_TCP:
+ case SIP_TRANSP_TLS:
+ err = sip_keepalive_tcp(ka, (struct sip_conn *)msg->sock,
+ interval);
+ break;
+
+ default:
+ err = EPROTONOSUPPORT;
+ break;
+ }
+
+ if (err) {
+ mem_deref(ka);
+ }
+ else {
+ ka->kap = kap;
+ *kap = ka;
+ }
+
+ return err;
+}