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/bfcp/conn.c b/src/bfcp/conn.c
new file mode 100644
index 0000000..6e4051d
--- /dev/null
+++ b/src/bfcp/conn.c
@@ -0,0 +1,156 @@
+/**
+ * @file bfcp/conn.c BFCP Connection
+ *
+ * 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_list.h>
+#include <re_sa.h>
+#include <re_udp.h>
+#include <re_tmr.h>
+#include <re_bfcp.h>
+#include "bfcp.h"
+
+
+static void destructor(void *arg)
+{
+	struct bfcp_conn *bc = arg;
+
+	list_flush(&bc->ctransl);
+	tmr_cancel(&bc->tmr1);
+	tmr_cancel(&bc->tmr2);
+	mem_deref(bc->us);
+	mem_deref(bc->mb);
+}
+
+
+static bool strans_cmp(const struct bfcp_strans *st,
+		       const struct bfcp_msg *msg)
+{
+	if (st->tid != msg->tid)
+		return false;
+
+	if (st->prim != msg->prim)
+		return false;
+
+	if (st->confid != msg->confid)
+		return false;
+
+	if (st->userid != msg->userid)
+		return false;
+
+	return true;
+}
+
+
+static void udp_recv_handler(const struct sa *src, struct mbuf *mb, void *arg)
+{
+	struct bfcp_conn *bc = arg;
+	struct bfcp_msg *msg;
+	int err;
+
+	err = bfcp_msg_decode(&msg, mb);
+	if (err)
+		return;
+
+	msg->src = *src;
+
+	if (bfcp_handle_response(bc, msg))
+		goto out;
+
+	if (bc->mb && strans_cmp(&bc->st, msg)) {
+		(void)bfcp_send(bc, &msg->src, bc->mb);
+		goto out;
+	}
+
+	if (bc->recvh)
+		bc->recvh(msg, bc->arg);
+
+out:
+	mem_deref(msg);
+}
+
+
+/**
+ * Create BFCP connection
+ *
+ * @param bcp   Pointer to BFCP connection
+ * @param tp    BFCP Transport type
+ * @param laddr Optional listening address/port
+ * @param tls   TLS Context (optional)
+ * @param recvh Receive handler
+ * @param arg   Receive handler argument
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int bfcp_listen(struct bfcp_conn **bcp, enum bfcp_transp tp, struct sa *laddr,
+		struct tls *tls, bfcp_recv_h *recvh, void *arg)
+{
+	struct bfcp_conn *bc;
+	int err;
+	(void)tls;
+
+	if (!bcp)
+		return EINVAL;
+
+	bc = mem_zalloc(sizeof(*bc), destructor);
+	if (!bc)
+		return ENOMEM;
+
+	bc->tp    = tp;
+	bc->recvh = recvh;
+	bc->arg   = arg;
+
+	switch (bc->tp) {
+
+	case BFCP_UDP:
+		err = udp_listen(&bc->us, laddr, udp_recv_handler, bc);
+		if (err)
+			goto out;
+
+		if (laddr) {
+			err = udp_local_get(bc->us, laddr);
+			if (err)
+				goto out;
+		}
+		break;
+
+	default:
+		err = ENOSYS;
+		goto out;
+	}
+
+ out:
+	if (err)
+		mem_deref(bc);
+	else
+		*bcp = bc;
+
+	return err;
+}
+
+
+int bfcp_send(struct bfcp_conn *bc, const struct sa *dst, struct mbuf *mb)
+{
+	if (!bc || !dst || !mb)
+		return EINVAL;
+
+	switch (bc->tp) {
+
+	case BFCP_UDP:
+		return udp_send(bc->us, dst, mb);
+
+	default:
+		return ENOSYS;
+	}
+}
+
+
+void *bfcp_sock(const struct bfcp_conn *bc)
+{
+	return bc ? bc->us : NULL;
+}