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/rtmp/ctrans.c b/src/rtmp/ctrans.c
new file mode 100644
index 0000000..6e56f84
--- /dev/null
+++ b/src/rtmp/ctrans.c
@@ -0,0 +1,138 @@
+/**
+ * @file rtmp/ctrans.c Real Time Messaging Protocol -- AMF Client Transactions
+ *
+ * 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_net.h>
+#include <re_sa.h>
+#include <re_list.h>
+#include <re_tcp.h>
+#include <re_sys.h>
+#include <re_odict.h>
+#include <re_rtmp.h>
+#include "rtmp.h"
+
+
+struct rtmp_ctrans {
+ struct le le;
+ uint64_t tid;
+ rtmp_resp_h *resph;
+ void *arg;
+};
+
+
+static void ctrans_destructor(void *data)
+{
+ struct rtmp_ctrans *ct = data;
+
+ list_unlink(&ct->le);
+}
+
+
+static struct rtmp_ctrans *rtmp_ctrans_find(const struct list *ctransl,
+ uint64_t tid)
+{
+ struct le *le;
+
+ for (le = list_head(ctransl); le; le = le->next) {
+ struct rtmp_ctrans *ct = le->data;
+
+ if (tid == ct->tid)
+ return ct;
+ }
+
+ return NULL;
+}
+
+
+int rtmp_amf_request(struct rtmp_conn *conn, uint32_t stream_id,
+ const char *command,
+ rtmp_resp_h *resph, void *arg, unsigned body_propc, ...)
+{
+ struct rtmp_ctrans *ct = NULL;
+ struct mbuf *mb;
+ va_list ap;
+ int err;
+
+ if (!conn || !command || !resph)
+ return EINVAL;
+
+ mb = mbuf_alloc(512);
+ if (!mb)
+ return ENOMEM;
+
+ ct = mem_zalloc(sizeof(*ct), ctrans_destructor);
+ if (!ct) {
+ err = ENOMEM;
+ goto out;
+ }
+
+ ct->tid = rtmp_conn_assign_tid(conn);
+ ct->resph = resph;
+ ct->arg = arg;
+
+ err = rtmp_command_header_encode(mb, command, ct->tid);
+ if (err)
+ goto out;
+
+ if (body_propc) {
+ va_start(ap, body_propc);
+ err = rtmp_amf_vencode_object(mb, RTMP_AMF_TYPE_ROOT,
+ body_propc, &ap);
+ va_end(ap);
+ if (err)
+ goto out;
+ }
+
+ err = rtmp_send_amf_command(conn, 0, RTMP_CHUNK_ID_CONN,
+ RTMP_TYPE_AMF0,
+ stream_id, mb->buf, mb->end);
+ if (err)
+ goto out;
+
+ list_append(&conn->ctransl, &ct->le, ct);
+
+ out:
+ mem_deref(mb);
+ if (err)
+ mem_deref(ct);
+
+ return err;
+}
+
+
+int rtmp_ctrans_response(const struct list *ctransl,
+ const struct odict *msg)
+{
+ struct rtmp_ctrans *ct;
+ uint64_t tid;
+ bool success;
+ rtmp_resp_h *resph;
+ void *arg;
+
+ if (!ctransl || !msg)
+ return EINVAL;
+
+ success = (0 == str_casecmp(odict_string(msg, "0"), "_result"));
+
+ if (!odict_get_number(msg, &tid, "1"))
+ return EPROTO;
+
+ ct = rtmp_ctrans_find(ctransl, tid);
+ if (!ct)
+ return ENOENT;
+
+ resph = ct->resph;
+ arg = ct->arg;
+
+ mem_deref(ct);
+
+ resph(success, msg, arg);
+
+ return 0;
+}