Squashed 'third_party/rawrtc/rew/' content from commit 24c91fd83

Change-Id: Ica2fcc790472ecd5b195d20da982c4e84139cbdd
git-subtree-dir: third_party/rawrtc/rew
git-subtree-split: 24c91fd839b40b11f727c902fa46d20874da33fb
diff --git a/src/trice/rcand.c b/src/trice/rcand.c
new file mode 100644
index 0000000..9516699
--- /dev/null
+++ b/src/trice/rcand.c
@@ -0,0 +1,205 @@
+/**
+ * @file rcand.c  Remote ICE Candidates
+ *
+ * Copyright (C) 2010 - 2015 Creytiv.com
+ */
+#include <string.h>
+#include <re_types.h>
+#include <re_fmt.h>
+#include <re_mem.h>
+#include <re_mbuf.h>
+#include <re_list.h>
+#include <re_tmr.h>
+#include <re_sa.h>
+#include <re_net.h>
+#include <re_stun.h>
+#include <re_ice.h>
+#include <re_trice.h>
+#include "trice.h"
+
+
+#define DEBUG_MODULE "rcand"
+#define DEBUG_LEVEL 5
+#include <re_dbg.h>
+
+
+static void rcand_destructor(void *data)
+{
+	struct ice_rcand *cand = data;
+
+	list_unlink(&cand->le);
+}
+
+
+static int trice_add_rcandidate(struct ice_rcand **candp,
+			       struct list *lst,
+			       unsigned compid, const char *foundation,
+			       int proto,
+			       uint32_t prio, const struct sa *addr,
+			       enum ice_cand_type type,
+			       enum ice_tcptype tcptype)
+{
+	struct ice_rcand *cand;
+	int err = 0;
+
+	if (!lst || !compid || !foundation || !proto || !addr)
+		return EINVAL;
+
+	cand = mem_zalloc(sizeof(*cand), rcand_destructor);
+	if (!cand)
+		return ENOMEM;
+
+	cand->attr.compid = compid;
+	str_ncpy(cand->attr.foundation, foundation,
+		 sizeof(cand->attr.foundation));
+	cand->attr.proto  = proto;
+	cand->attr.prio   = prio;
+	cand->attr.addr   = *addr;
+	cand->attr.type   = type;
+	cand->attr.tcptype = tcptype;
+
+	if (err)
+		goto out;
+
+	list_append(lst, &cand->le, cand);
+
+ out:
+	if (err)
+		mem_deref(cand);
+	else if (candp)
+		*candp = cand;
+
+	return err;
+}
+
+
+/* you can call this at any time */
+int trice_rcand_add(struct ice_rcand **rcandp, struct trice *icem,
+		    unsigned compid, const char *foundation,
+		    int proto, uint32_t prio,
+		    const struct sa *addr, enum ice_cand_type type,
+		    enum ice_tcptype tcptype)
+{
+	struct ice_rcand *rcand;
+	int sa_flags = SA_ADDR;
+	int err = 0;
+
+	if (!icem || !foundation)
+		return EINVAL;
+
+	if (proto == IPPROTO_UDP)
+		sa_flags |= SA_PORT;
+
+	if (proto == IPPROTO_TCP &&
+	    (tcptype == ICE_TCP_PASSIVE || tcptype == ICE_TCP_SO))
+		sa_flags |= SA_PORT;
+
+	if (!sa_isset(addr, sa_flags)) {
+		DEBUG_WARNING("add_remote_candidate: invalid address"
+			      " (%J) for %s.%s\n",
+			      addr, net_proto2name(proto),
+			      ice_tcptype_name(tcptype));
+		return EINVAL;
+	}
+
+	/* avoid duplicates */
+	rcand = trice_rcand_find(icem, compid, proto, addr);
+	if (rcand) {
+
+		if (rcand->attr.type == ICE_CAND_TYPE_PRFLX &&
+		    prio > rcand->attr.prio) {
+
+			rcand->attr.type = type;
+			rcand->attr.prio = prio;
+		}
+
+		goto out;
+	}
+
+	err = trice_add_rcandidate(&rcand, &icem->rcandl,
+				 compid, foundation,
+				 proto, prio, addr, type, tcptype);
+	if (err)
+		goto out;
+
+	if (icem->lrole != ICE_ROLE_UNKNOWN) {
+		/* pair this remote-candidate with all existing
+		 * local-candidates */
+		err = trice_candpair_with_remote(icem, rcand);
+		if (err)
+			goto out;
+
+		/* new pair -- refresh the checklist timer */
+		trice_checklist_refresh(icem);
+	}
+
+ out:
+	if (err)
+		mem_deref(rcand);
+	else if (rcandp)
+		*rcandp = rcand;
+
+	return err;
+}
+
+
+struct ice_rcand *trice_rcand_find(struct trice *icem,
+				   unsigned compid, int proto,
+				   const struct sa *addr)
+{
+	struct list *lst;
+	struct le *le;
+
+	if (!icem)
+		return NULL;
+
+	if (!proto) {
+		DEBUG_WARNING("find_candidate: invalid args\n");
+		return NULL;
+	}
+
+	lst = &icem->rcandl;
+
+	for (le = list_head(lst); le; le = le->next) {
+
+		struct ice_cand_attr *cand = le->data;
+
+		if (compid && cand->compid != compid)
+			continue;
+
+		if (cand->proto != proto)
+			continue;
+
+		if (addr && !sa_cmp(&cand->addr, addr, SA_ALL))
+			continue;
+
+		return (void *)cand;
+	}
+
+	return NULL;
+}
+
+
+int trice_rcands_debug(struct re_printf *pf, const struct list *lst)
+{
+	struct le *le;
+	int err;
+
+	err = re_hprintf(pf, " (%u)\n", list_count(lst));
+
+	for (le = list_head(lst); le && !err; le = le->next) {
+
+		const struct ice_rcand *rcand = le->data;
+
+		err |= re_hprintf(pf, "  {%u} "
+				  "fnd=%-8s prio=%08x %24H",
+				  rcand->attr.compid,
+				  rcand->attr.foundation,
+				  rcand->attr.prio,
+				  trice_cand_print, rcand);
+
+		err |= re_hprintf(pf, "\n");
+	}
+
+	return err;
+}