blob: c95763ed15e6a94dd5ca9ffac83813e440b85938 [file] [log] [blame]
James Kuszmaul82f6c042021-01-17 11:30:16 -08001/**
2 * @file rtmp/amf.c Real Time Messaging Protocol (RTMP) -- AMF Commands
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
21int rtmp_command_header_encode(struct mbuf *mb, const char *name, uint64_t tid)
22{
23 int err;
24
25 if (!mb || !name)
26 return EINVAL;
27
28 err = rtmp_amf_encode_string(mb, name);
29 err |= rtmp_amf_encode_number(mb, tid);
30
31 return err;
32}
33
34
35int rtmp_amf_command(const struct rtmp_conn *conn, uint32_t stream_id,
36 const char *command, unsigned body_propc, ...)
37{
38 struct mbuf *mb;
39 va_list ap;
40 int err;
41
42 if (!conn || !command)
43 return EINVAL;
44
45 mb = mbuf_alloc(512);
46 if (!mb)
47 return ENOMEM;
48
49 err = rtmp_amf_encode_string(mb, command);
50 if (err)
51 goto out;
52
53 if (body_propc) {
54 va_start(ap, body_propc);
55 err = rtmp_amf_vencode_object(mb, RTMP_AMF_TYPE_ROOT,
56 body_propc, &ap);
57 va_end(ap);
58 if (err)
59 goto out;
60 }
61
62 err = rtmp_send_amf_command(conn, 0, RTMP_CHUNK_ID_CONN,
63 RTMP_TYPE_AMF0,
64 stream_id, mb->buf, mb->end);
65
66 if (err)
67 goto out;
68
69 out:
70 mem_deref(mb);
71
72 return err;
73}
74
75
76int rtmp_amf_reply(struct rtmp_conn *conn, uint32_t stream_id, bool success,
77 const struct odict *req,
78 unsigned body_propc, ...)
79{
80 struct mbuf *mb;
81 va_list ap;
82 uint64_t tid;
83 int err;
84
85 if (!conn || !req)
86 return EINVAL;
87
88 if (!odict_get_number(req, &tid, "1"))
89 return EPROTO;
90 if (tid == 0)
91 return EPROTO;
92
93 mb = mbuf_alloc(512);
94 if (!mb)
95 return ENOMEM;
96
97 err = rtmp_command_header_encode(mb,
98 success ? "_result" : "_error", tid);
99 if (err)
100 goto out;
101
102 if (body_propc) {
103 va_start(ap, body_propc);
104 err = rtmp_amf_vencode_object(mb, RTMP_AMF_TYPE_ROOT,
105 body_propc, &ap);
106 va_end(ap);
107 if (err)
108 goto out;
109 }
110
111 err = rtmp_send_amf_command(conn, 0, RTMP_CHUNK_ID_CONN,
112 RTMP_TYPE_AMF0,
113 stream_id, mb->buf, mb->end);
114
115 if (err)
116 goto out;
117
118 out:
119 mem_deref(mb);
120
121 return err;
122}
123
124
125int rtmp_amf_data(const struct rtmp_conn *conn, uint32_t stream_id,
126 const char *command, unsigned body_propc, ...)
127{
128 struct mbuf *mb;
129 va_list ap;
130 int err;
131
132 if (!conn || !command)
133 return EINVAL;
134
135 mb = mbuf_alloc(512);
136 if (!mb)
137 return ENOMEM;
138
139 err = rtmp_amf_encode_string(mb, command);
140 if (err)
141 goto out;
142
143 if (body_propc) {
144 va_start(ap, body_propc);
145 err = rtmp_amf_vencode_object(mb, RTMP_AMF_TYPE_ROOT,
146 body_propc, &ap);
147 va_end(ap);
148 if (err)
149 goto out;
150 }
151
152 err = rtmp_send_amf_command(conn, 0, RTMP_CHUNK_ID_CONN,
153 RTMP_TYPE_DATA,
154 stream_id, mb->buf, mb->end);
155
156 if (err)
157 goto out;
158
159 out:
160 mem_deref(mb);
161
162 return err;
163}