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/request.c b/src/bfcp/request.c
new file mode 100644
index 0000000..cfe066e
--- /dev/null
+++ b/src/bfcp/request.c
@@ -0,0 +1,257 @@
+/**
+ * @file bfcp/request.c BFCP Request
+ *
+ * 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_tmr.h>
+#include <re_bfcp.h>
+#include "bfcp.h"
+
+
+enum {
+ BFCP_T1 = 500,
+ BFCP_TXC = 4,
+};
+
+
+struct bfcp_ctrans {
+ struct le le;
+ struct sa dst;
+ struct mbuf *mb;
+ bfcp_resp_h *resph;
+ void *arg;
+ uint32_t confid;
+ uint16_t userid;
+ uint16_t tid;
+};
+
+
+static void tmr_handler(void *arg);
+
+
+static void dummy_resp_handler(int err, const struct bfcp_msg *msg, void *arg)
+{
+ (void)err;
+ (void)msg;
+ (void)arg;
+}
+
+
+static void destructor(void *arg)
+{
+ struct bfcp_ctrans *ct = arg;
+
+ list_unlink(&ct->le);
+ mem_deref(ct->mb);
+}
+
+
+static void dispatch(struct bfcp_conn *bc)
+{
+ struct le *le = bc->ctransl.head;
+
+ while (le) {
+ struct bfcp_ctrans *ct = le->data;
+ int err;
+
+ le = le->next;
+
+ err = bfcp_send(bc, &ct->dst, ct->mb);
+ if (err) {
+ ct->resph(err, NULL, ct->arg);
+ mem_deref(ct);
+ continue;
+ }
+
+ tmr_start(&bc->tmr1, BFCP_T1, tmr_handler, bc);
+ bc->txc = 1;
+ break;
+ }
+}
+
+
+static void tmr_handler(void *arg)
+{
+ struct bfcp_conn *bc = arg;
+ struct bfcp_ctrans *ct;
+ uint32_t timeout;
+ int err;
+
+ ct = list_ledata(bc->ctransl.head);
+ if (!ct)
+ return;
+
+ timeout = BFCP_T1<<bc->txc;
+
+ if (++bc->txc > BFCP_TXC) {
+ err = ETIMEDOUT;
+ goto out;
+ }
+
+ err = bfcp_send(bc, &ct->dst, ct->mb);
+ if (err)
+ goto out;
+
+ tmr_start(&bc->tmr1, timeout, tmr_handler, bc);
+ return;
+
+ out:
+ ct->resph(err, NULL, ct->arg);
+ mem_deref(ct);
+ dispatch(bc);
+}
+
+
+bool bfcp_handle_response(struct bfcp_conn *bc, const struct bfcp_msg *msg)
+{
+ struct bfcp_ctrans *ct;
+
+ if (!bc || !msg)
+ return false;
+
+ ct = list_ledata(bc->ctransl.head);
+ if (!ct)
+ return false;
+
+ if (msg->tid != ct->tid)
+ return false;
+
+ if (msg->confid != ct->confid)
+ return false;
+
+ if (msg->userid != ct->userid)
+ return false;
+
+ tmr_cancel(&bc->tmr1);
+
+ ct->resph(0, msg, ct->arg);
+ mem_deref(ct);
+
+ dispatch(bc);
+
+ return true;
+}
+
+
+int bfcp_vrequest(struct bfcp_conn *bc, const struct sa *dst, uint8_t ver,
+ enum bfcp_prim prim, uint32_t confid, uint16_t userid,
+ bfcp_resp_h *resph, void *arg, unsigned attrc, va_list *ap)
+{
+ struct bfcp_ctrans *ct;
+ int err;
+
+ if (!bc || !dst)
+ return EINVAL;
+
+ ct = mem_zalloc(sizeof(*ct), destructor);
+ if (!ct)
+ return ENOMEM;
+
+ if (bc->tid == 0)
+ bc->tid = 1;
+
+ ct->dst = *dst;
+ ct->confid = confid;
+ ct->userid = userid;
+ ct->tid = bc->tid++;
+ ct->resph = resph ? resph : dummy_resp_handler;
+ ct->arg = arg;
+
+ ct->mb = mbuf_alloc(128);
+ if (!ct->mb) {
+ err = ENOMEM;
+ goto out;
+ }
+
+ err = bfcp_msg_vencode(ct->mb, ver, false, prim, confid, ct->tid,
+ userid, attrc, ap);
+ if (err)
+ goto out;
+
+ ct->mb->pos = 0;
+
+ if (!bc->ctransl.head) {
+
+ err = bfcp_send(bc, &ct->dst, ct->mb);
+ if (err)
+ goto out;
+
+ tmr_start(&bc->tmr1, BFCP_T1, tmr_handler, bc);
+ bc->txc = 1;
+ }
+
+ list_append(&bc->ctransl, &ct->le, ct);
+
+ out:
+ if (err)
+ mem_deref(ct);
+
+ return err;
+}
+
+
+/**
+ * Send a BFCP request
+ *
+ * @param bc BFCP connection
+ * @param dst Destination address
+ * @param ver BFCP Version
+ * @param prim BFCP Primitive
+ * @param confid Conference ID
+ * @param userid User ID
+ * @param resph Response handler
+ * @param arg Response handler argument
+ * @param attrc Number of attributes
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int bfcp_request(struct bfcp_conn *bc, const struct sa *dst, uint8_t ver,
+ enum bfcp_prim prim, uint32_t confid, uint16_t userid,
+ bfcp_resp_h *resph, void *arg, unsigned attrc, ...)
+{
+ va_list ap;
+ int err;
+
+ va_start(ap, attrc);
+ err = bfcp_vrequest(bc, dst, ver, prim, confid, userid, resph, arg,
+ attrc, &ap);
+ va_end(ap);
+
+ return err;
+}
+
+
+/**
+ * Send a BFCP notification/subsequent response
+ *
+ * @param bc BFCP connection
+ * @param dst Destination address
+ * @param ver BFCP Version
+ * @param prim BFCP Primitive
+ * @param confid Conference ID
+ * @param userid User ID
+ * @param attrc Number of attributes
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int bfcp_notify(struct bfcp_conn *bc, const struct sa *dst, uint8_t ver,
+ enum bfcp_prim prim, uint32_t confid, uint16_t userid,
+ unsigned attrc, ...)
+{
+ va_list ap;
+ int err;
+
+ va_start(ap, attrc);
+ err = bfcp_vrequest(bc, dst, ver, prim, confid, userid, NULL, NULL,
+ attrc, &ap);
+ va_end(ap);
+
+ return err;
+}