blob: 6e56f84b7ac8cac137628e00378e177033a3d4b7 [file] [log] [blame]
James Kuszmaul82f6c042021-01-17 11:30:16 -08001/**
2 * @file rtmp/ctrans.c Real Time Messaging Protocol -- AMF Client Transactions
3 *
4 * Copyright (C) 2010 Creytiv.com
5 */
6#include <string.h>
7#include <re_types.h>
8#include <re_fmt.h>
9#include <re_mem.h>
10#include <re_mbuf.h>
11#include <re_net.h>
12#include <re_sa.h>
13#include <re_list.h>
14#include <re_tcp.h>
15#include <re_sys.h>
16#include <re_odict.h>
17#include <re_rtmp.h>
18#include "rtmp.h"
19
20
21struct rtmp_ctrans {
22 struct le le;
23 uint64_t tid;
24 rtmp_resp_h *resph;
25 void *arg;
26};
27
28
29static void ctrans_destructor(void *data)
30{
31 struct rtmp_ctrans *ct = data;
32
33 list_unlink(&ct->le);
34}
35
36
37static struct rtmp_ctrans *rtmp_ctrans_find(const struct list *ctransl,
38 uint64_t tid)
39{
40 struct le *le;
41
42 for (le = list_head(ctransl); le; le = le->next) {
43 struct rtmp_ctrans *ct = le->data;
44
45 if (tid == ct->tid)
46 return ct;
47 }
48
49 return NULL;
50}
51
52
53int rtmp_amf_request(struct rtmp_conn *conn, uint32_t stream_id,
54 const char *command,
55 rtmp_resp_h *resph, void *arg, unsigned body_propc, ...)
56{
57 struct rtmp_ctrans *ct = NULL;
58 struct mbuf *mb;
59 va_list ap;
60 int err;
61
62 if (!conn || !command || !resph)
63 return EINVAL;
64
65 mb = mbuf_alloc(512);
66 if (!mb)
67 return ENOMEM;
68
69 ct = mem_zalloc(sizeof(*ct), ctrans_destructor);
70 if (!ct) {
71 err = ENOMEM;
72 goto out;
73 }
74
75 ct->tid = rtmp_conn_assign_tid(conn);
76 ct->resph = resph;
77 ct->arg = arg;
78
79 err = rtmp_command_header_encode(mb, command, ct->tid);
80 if (err)
81 goto out;
82
83 if (body_propc) {
84 va_start(ap, body_propc);
85 err = rtmp_amf_vencode_object(mb, RTMP_AMF_TYPE_ROOT,
86 body_propc, &ap);
87 va_end(ap);
88 if (err)
89 goto out;
90 }
91
92 err = rtmp_send_amf_command(conn, 0, RTMP_CHUNK_ID_CONN,
93 RTMP_TYPE_AMF0,
94 stream_id, mb->buf, mb->end);
95 if (err)
96 goto out;
97
98 list_append(&conn->ctransl, &ct->le, ct);
99
100 out:
101 mem_deref(mb);
102 if (err)
103 mem_deref(ct);
104
105 return err;
106}
107
108
109int rtmp_ctrans_response(const struct list *ctransl,
110 const struct odict *msg)
111{
112 struct rtmp_ctrans *ct;
113 uint64_t tid;
114 bool success;
115 rtmp_resp_h *resph;
116 void *arg;
117
118 if (!ctransl || !msg)
119 return EINVAL;
120
121 success = (0 == str_casecmp(odict_string(msg, "0"), "_result"));
122
123 if (!odict_get_number(msg, &tid, "1"))
124 return EPROTO;
125
126 ct = rtmp_ctrans_find(ctransl, tid);
127 if (!ct)
128 return ENOENT;
129
130 resph = ct->resph;
131 arg = ct->arg;
132
133 mem_deref(ct);
134
135 resph(success, msg, arg);
136
137 return 0;
138}