Add missing includes for code relying on external libraries
[libav.git] / libavformat / rtmpproto.c
CommitLineData
9fd6b843
KS
1/*
2 * RTMP network protocol
3 * Copyright (c) 2009 Kostya Shishkov
4 *
2912e87a 5 * This file is part of Libav.
9fd6b843 6 *
2912e87a 7 * Libav is free software; you can redistribute it and/or
9fd6b843
KS
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
2912e87a 12 * Libav is distributed in the hope that it will be useful,
9fd6b843
KS
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
2912e87a 18 * License along with Libav; if not, write to the Free Software
9fd6b843
KS
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22/**
ba87f080 23 * @file
9fd6b843
KS
24 * RTMP protocol
25 */
26
27#include "libavcodec/bytestream.h"
28#include "libavutil/avstring.h"
3383a53e 29#include "libavutil/intfloat.h"
9fd6b843 30#include "libavutil/lfg.h"
6465562e 31#include "libavutil/opt.h"
9fd6b843
KS
32#include "libavutil/sha.h"
33#include "avformat.h"
e4a9e3cc 34#include "internal.h"
9fd6b843
KS
35
36#include "network.h"
37
38#include "flv.h"
39#include "rtmp.h"
acd554c1 40#include "rtmpcrypt.h"
9fd6b843 41#include "rtmppkt.h"
0589da0a 42#include "url.h"
9fd6b843 43
93f257db
SP
44#if CONFIG_ZLIB
45#include <zlib.h>
46#endif
47
cfac91fe
KS
48//#define DEBUG
49
6465562e 50#define APP_MAX_LENGTH 128
b3b17512 51#define PLAYPATH_MAX_LENGTH 256
55c9320e 52#define TCURL_MAX_LENGTH 512
e64673e4 53#define FLASHVER_MAX_LENGTH 64
6465562e 54
9fd6b843
KS
55/** RTMP protocol handler state */
56typedef enum {
57 STATE_START, ///< client has not done anything yet
58 STATE_HANDSHAKED, ///< client has performed handshake
6bf22e18 59 STATE_FCPUBLISH, ///< client FCPublishing stream (for output)
9fd6b843 60 STATE_PLAYING, ///< client has started receiving multimedia data from server
6bf22e18 61 STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
72b870b9 62 STATE_STOPPED, ///< the broadcast has been stopped
9fd6b843
KS
63} ClientState;
64
f89584ca
SP
65typedef struct TrackedMethod {
66 char *name;
67 int id;
68} TrackedMethod;
69
9fd6b843
KS
70/** protocol handler context */
71typedef struct RTMPContext {
6465562e 72 const AVClass *class;
9fd6b843
KS
73 URLContext* stream; ///< TCP stream used in interactions with RTMP server
74 RTMPPacket prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets
f5ce90f2
JO
75 int in_chunk_size; ///< size of the chunks incoming RTMP packets are divided into
76 int out_chunk_size; ///< size of the chunks outgoing RTMP packets are divided into
b316991b 77 int is_input; ///< input/output flag
b3b17512 78 char *playpath; ///< stream identifier to play (with possible "mp4:" prefix)
b2e495af 79 int live; ///< 0: recorded, -1: live, -2: both
6465562e 80 char *app; ///< name of application
8ee3e187 81 char *conn; ///< append arbitrary AMF data to the Connect message
9fd6b843
KS
82 ClientState state; ///< current state
83 int main_channel_id; ///< an additional channel ID which is used for some invocations
84 uint8_t* flv_data; ///< buffer with data for demuxer
85 int flv_size; ///< current buffer size
86 int flv_off; ///< number of bytes read from current buffer
46743a85 87 int flv_nb_packets; ///< number of flv packets published
6bf22e18 88 RTMPPacket out_pkt; ///< rtmp packet, created from flv a/v or metadata (for output)
bf7c1719
KS
89 uint32_t client_report_size; ///< number of bytes after which client should report to server
90 uint32_t bytes_read; ///< number of bytes read from server
91 uint32_t last_bytes_read; ///< number of bytes read last reported to server
3ffe32eb 92 int skip_bytes; ///< number of bytes to skip from the input FLV stream in the next write call
b14629e5
MS
93 uint8_t flv_header[11]; ///< partial incoming flv packet header
94 int flv_header_bytes; ///< number of initialized bytes in flv_header
704af3e2 95 int nb_invokes; ///< keeps track of invoke messages
55c9320e 96 char* tcurl; ///< url of the target stream
e64673e4 97 char* flashver; ///< version of the flash plugin
635ac8e1
SP
98 char* swfhash; ///< SHA256 hash of the decompressed SWF file (32 bytes)
99 int swfhash_len; ///< length of the SHA256 hash
100 int swfsize; ///< size of the decompressed SWF file
05945db9 101 char* swfurl; ///< url of the swf player
93f257db 102 char* swfverify; ///< URL to player swf file, compute hash/size automatically
635ac8e1 103 char swfverification[42]; ///< hash of the SWF verification
758377a2 104 char* pageurl; ///< url of the web page
00cb52c6 105 char* subscribe; ///< name of live stream to subscribe
c2d38bea 106 int server_bw; ///< server bandwidth
9477c035 107 int client_buffer_time; ///< client buffer time in ms
46743a85 108 int flush_interval; ///< number of packets flushed in the same request (RTMPT only)
acd554c1 109 int encrypted; ///< use an encrypted connection (RTMPE only)
f89584ca
SP
110 TrackedMethod*tracked_methods; ///< tracked methods buffer
111 int nb_tracked_methods; ///< number of tracked methods
112 int tracked_methods_size; ///< size of the tracked methods buffer
9fd6b843
KS
113} RTMPContext;
114
115#define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing
116/** Client key used for digest signing */
117static const uint8_t rtmp_player_key[] = {
118 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
119 'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
120
121 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
122 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
123 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
124};
125
126#define SERVER_KEY_OPEN_PART_LEN 36 ///< length of partial key used for first server digest signing
127/** Key used for RTMP server digest signing */
128static const uint8_t rtmp_server_key[] = {
129 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
130 'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
131 'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
132
133 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
134 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
135 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
136};
137
f89584ca
SP
138static int add_tracked_method(RTMPContext *rt, const char *name, int id)
139{
140 void *ptr;
141
142 if (rt->nb_tracked_methods + 1 > rt->tracked_methods_size) {
143 rt->tracked_methods_size = (rt->nb_tracked_methods + 1) * 2;
144 ptr = av_realloc(rt->tracked_methods,
145 rt->tracked_methods_size * sizeof(*rt->tracked_methods));
146 if (!ptr)
147 return AVERROR(ENOMEM);
148 rt->tracked_methods = ptr;
149 }
150
151 rt->tracked_methods[rt->nb_tracked_methods].name = av_strdup(name);
152 if (!rt->tracked_methods[rt->nb_tracked_methods].name)
153 return AVERROR(ENOMEM);
154 rt->tracked_methods[rt->nb_tracked_methods].id = id;
155 rt->nb_tracked_methods++;
156
157 return 0;
158}
159
160static void del_tracked_method(RTMPContext *rt, int index)
161{
162 memmove(&rt->tracked_methods[index], &rt->tracked_methods[index + 1],
163 sizeof(*rt->tracked_methods) * (rt->nb_tracked_methods - index - 1));
164 rt->nb_tracked_methods--;
165}
166
a8103503
SP
167static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset,
168 char **tracked_method)
169{
170 RTMPContext *rt = s->priv_data;
171 GetByteContext gbc;
172 double pkt_id;
173 int ret;
174 int i;
175
176 bytestream2_init(&gbc, pkt->data + offset, pkt->data_size - offset);
177 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
178 return ret;
179
180 for (i = 0; i < rt->nb_tracked_methods; i++) {
181 if (rt->tracked_methods[i].id != pkt_id)
182 continue;
183
184 *tracked_method = rt->tracked_methods[i].name;
185 del_tracked_method(rt, i);
186 break;
187 }
188
189 return 0;
190}
191
f89584ca
SP
192static void free_tracked_methods(RTMPContext *rt)
193{
194 int i;
195
196 for (i = 0; i < rt->nb_tracked_methods; i ++)
197 av_free(rt->tracked_methods[i].name);
198 av_free(rt->tracked_methods);
199}
200
201static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
202{
203 int ret;
204
205 if (pkt->type == RTMP_PT_INVOKE && track) {
206 GetByteContext gbc;
207 char name[128];
208 double pkt_id;
209 int len;
210
211 bytestream2_init(&gbc, pkt->data, pkt->data_size);
212 if ((ret = ff_amf_read_string(&gbc, name, sizeof(name), &len)) < 0)
213 goto fail;
214
215 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
216 goto fail;
217
218 if ((ret = add_tracked_method(rt, name, pkt_id)) < 0)
219 goto fail;
220 }
221
f5ce90f2 222 ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
f89584ca
SP
223 rt->prev_pkt[1]);
224fail:
225 ff_rtmp_packet_destroy(pkt);
226 return ret;
227}
228
8ee3e187
SP
229static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
230{
05338686 231 char *field, *value;
8ee3e187
SP
232 char type;
233
234 /* The type must be B for Boolean, N for number, S for string, O for
235 * object, or Z for null. For Booleans the data must be either 0 or 1 for
236 * FALSE or TRUE, respectively. Likewise for Objects the data must be
237 * 0 or 1 to end or begin an object, respectively. Data items in subobjects
238 * may be named, by prefixing the type with 'N' and specifying the name
239 * before the value (ie. NB:myFlag:1). This option may be used multiple times
240 * to construct arbitrary AMF sequences. */
241 if (param[0] && param[1] == ':') {
242 type = param[0];
243 value = param + 2;
244 } else if (param[0] == 'N' && param[1] && param[2] == ':') {
245 type = param[1];
05338686
MS
246 field = param + 3;
247 value = strchr(field, ':');
248 if (!value)
249 goto fail;
250 *value = '\0';
251 value++;
8ee3e187
SP
252
253 if (!field || !value)
254 goto fail;
255
256 ff_amf_write_field_name(p, field);
257 } else {
258 goto fail;
259 }
260
261 switch (type) {
262 case 'B':
263 ff_amf_write_bool(p, value[0] != '0');
264 break;
265 case 'S':
266 ff_amf_write_string(p, value);
267 break;
268 case 'N':
269 ff_amf_write_number(p, strtod(value, NULL));
270 break;
271 case 'Z':
272 ff_amf_write_null(p);
273 break;
274 case 'O':
275 if (value[0] != '0')
276 ff_amf_write_object_start(p);
277 else
278 ff_amf_write_object_end(p);
279 break;
280 default:
281 goto fail;
282 break;
283 }
284
285 return 0;
286
287fail:
288 av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
289 return AVERROR(EINVAL);
290}
291
9fd6b843 292/**
49bd8e4b 293 * Generate 'connect' call and send it to the server.
9fd6b843 294 */
f645f1d6 295static int gen_connect(URLContext *s, RTMPContext *rt)
9fd6b843
KS
296{
297 RTMPPacket pkt;
e64673e4 298 uint8_t *p;
f645f1d6
SP
299 int ret;
300
301 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
302 0, 4096)) < 0)
303 return ret;
9fd6b843 304
9fd6b843
KS
305 p = pkt.data;
306
9fd6b843 307 ff_amf_write_string(&p, "connect");
1eef08f9 308 ff_amf_write_number(&p, ++rt->nb_invokes);
9fd6b843
KS
309 ff_amf_write_object_start(&p);
310 ff_amf_write_field_name(&p, "app");
5e9ad759 311 ff_amf_write_string(&p, rt->app);
9fd6b843 312
e64673e4 313 if (!rt->is_input) {
6bf22e18
S
314 ff_amf_write_field_name(&p, "type");
315 ff_amf_write_string(&p, "nonprivate");
316 }
9fd6b843 317 ff_amf_write_field_name(&p, "flashVer");
e64673e4 318 ff_amf_write_string(&p, rt->flashver);
05945db9
SP
319
320 if (rt->swfurl) {
321 ff_amf_write_field_name(&p, "swfUrl");
322 ff_amf_write_string(&p, rt->swfurl);
323 }
324
9fd6b843 325 ff_amf_write_field_name(&p, "tcUrl");
55c9320e 326 ff_amf_write_string(&p, rt->tcurl);
6bf22e18 327 if (rt->is_input) {
c7240611
KS
328 ff_amf_write_field_name(&p, "fpad");
329 ff_amf_write_bool(&p, 0);
330 ff_amf_write_field_name(&p, "capabilities");
331 ff_amf_write_number(&p, 15.0);
faba4a9b
SP
332
333 /* Tell the server we support all the audio codecs except
334 * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
335 * which are unused in the RTMP protocol implementation. */
c7240611 336 ff_amf_write_field_name(&p, "audioCodecs");
faba4a9b 337 ff_amf_write_number(&p, 4071.0);
c7240611
KS
338 ff_amf_write_field_name(&p, "videoCodecs");
339 ff_amf_write_number(&p, 252.0);
340 ff_amf_write_field_name(&p, "videoFunction");
341 ff_amf_write_number(&p, 1.0);
758377a2
SP
342
343 if (rt->pageurl) {
344 ff_amf_write_field_name(&p, "pageUrl");
345 ff_amf_write_string(&p, rt->pageurl);
346 }
6bf22e18 347 }
9fd6b843
KS
348 ff_amf_write_object_end(&p);
349
8ee3e187 350 if (rt->conn) {
05338686 351 char *param = rt->conn;
8ee3e187
SP
352
353 // Write arbitrary AMF data to the Connect message.
8ee3e187 354 while (param != NULL) {
05338686
MS
355 char *sep;
356 param += strspn(param, " ");
357 if (!*param)
358 break;
359 sep = strchr(param, ' ');
360 if (sep)
361 *sep = '\0';
8ee3e187
SP
362 if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
363 // Invalid AMF parameter.
364 ff_rtmp_packet_destroy(&pkt);
365 return ret;
366 }
367
05338686
MS
368 if (sep)
369 param = sep + 1;
370 else
371 break;
8ee3e187
SP
372 }
373 }
374
9fd6b843
KS
375 pkt.data_size = p - pkt.data;
376
f89584ca 377 return rtmp_send_packet(rt, &pkt, 1);
9fd6b843
KS
378}
379
380/**
49bd8e4b 381 * Generate 'releaseStream' call and send it to the server. It should make
6bf22e18
S
382 * the server release some channel for media streams.
383 */
f645f1d6 384static int gen_release_stream(URLContext *s, RTMPContext *rt)
6bf22e18
S
385{
386 RTMPPacket pkt;
387 uint8_t *p;
f645f1d6 388 int ret;
6bf22e18 389
f645f1d6
SP
390 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
391 0, 29 + strlen(rt->playpath))) < 0)
392 return ret;
6bf22e18 393
7f804085 394 av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
6bf22e18
S
395 p = pkt.data;
396 ff_amf_write_string(&p, "releaseStream");
704af3e2 397 ff_amf_write_number(&p, ++rt->nb_invokes);
6bf22e18
S
398 ff_amf_write_null(&p);
399 ff_amf_write_string(&p, rt->playpath);
400
f89584ca 401 return rtmp_send_packet(rt, &pkt, 0);
6bf22e18
S
402}
403
404/**
49bd8e4b 405 * Generate 'FCPublish' call and send it to the server. It should make
6bf22e18
S
406 * the server preapare for receiving media streams.
407 */
f645f1d6 408static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
6bf22e18
S
409{
410 RTMPPacket pkt;
411 uint8_t *p;
f645f1d6 412 int ret;
6bf22e18 413
f645f1d6
SP
414 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
415 0, 25 + strlen(rt->playpath))) < 0)
416 return ret;
6bf22e18 417
7f804085 418 av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
6bf22e18
S
419 p = pkt.data;
420 ff_amf_write_string(&p, "FCPublish");
704af3e2 421 ff_amf_write_number(&p, ++rt->nb_invokes);
6bf22e18
S
422 ff_amf_write_null(&p);
423 ff_amf_write_string(&p, rt->playpath);
424
f89584ca 425 return rtmp_send_packet(rt, &pkt, 0);
6bf22e18
S
426}
427
428/**
49bd8e4b 429 * Generate 'FCUnpublish' call and send it to the server. It should make
6bf22e18
S
430 * the server destroy stream.
431 */
f645f1d6 432static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
6bf22e18
S
433{
434 RTMPPacket pkt;
435 uint8_t *p;
f645f1d6 436 int ret;
6bf22e18 437
f645f1d6
SP
438 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
439 0, 27 + strlen(rt->playpath))) < 0)
440 return ret;
6bf22e18 441
7f804085 442 av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
6bf22e18
S
443 p = pkt.data;
444 ff_amf_write_string(&p, "FCUnpublish");
704af3e2 445 ff_amf_write_number(&p, ++rt->nb_invokes);
6bf22e18
S
446 ff_amf_write_null(&p);
447 ff_amf_write_string(&p, rt->playpath);
448
f89584ca 449 return rtmp_send_packet(rt, &pkt, 0);
6bf22e18
S
450}
451
452/**
49bd8e4b 453 * Generate 'createStream' call and send it to the server. It should make
9fd6b843
KS
454 * the server allocate some channel for media streams.
455 */
f645f1d6 456static int gen_create_stream(URLContext *s, RTMPContext *rt)
9fd6b843
KS
457{
458 RTMPPacket pkt;
459 uint8_t *p;
f645f1d6 460 int ret;
9fd6b843 461
7f804085 462 av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
f645f1d6
SP
463
464 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
465 0, 25)) < 0)
466 return ret;
9fd6b843
KS
467
468 p = pkt.data;
469 ff_amf_write_string(&p, "createStream");
704af3e2 470 ff_amf_write_number(&p, ++rt->nb_invokes);
6bf22e18
S
471 ff_amf_write_null(&p);
472
f89584ca 473 return rtmp_send_packet(rt, &pkt, 1);
6bf22e18
S
474}
475
476
477/**
49bd8e4b 478 * Generate 'deleteStream' call and send it to the server. It should make
6bf22e18
S
479 * the server remove some channel for media streams.
480 */
f645f1d6 481static int gen_delete_stream(URLContext *s, RTMPContext *rt)
6bf22e18
S
482{
483 RTMPPacket pkt;
484 uint8_t *p;
f645f1d6 485 int ret;
6bf22e18 486
7f804085 487 av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
f645f1d6
SP
488
489 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
490 0, 34)) < 0)
491 return ret;
6bf22e18
S
492
493 p = pkt.data;
494 ff_amf_write_string(&p, "deleteStream");
1eef08f9 495 ff_amf_write_number(&p, ++rt->nb_invokes);
9fd6b843 496 ff_amf_write_null(&p);
6bf22e18 497 ff_amf_write_number(&p, rt->main_channel_id);
9fd6b843 498
f89584ca 499 return rtmp_send_packet(rt, &pkt, 0);
9fd6b843
KS
500}
501
502/**
9477c035
SP
503 * Generate client buffer time and send it to the server.
504 */
505static int gen_buffer_time(URLContext *s, RTMPContext *rt)
506{
507 RTMPPacket pkt;
508 uint8_t *p;
509 int ret;
510
511 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
512 1, 10)) < 0)
513 return ret;
514
515 p = pkt.data;
516 bytestream_put_be16(&p, 3);
517 bytestream_put_be32(&p, rt->main_channel_id);
518 bytestream_put_be32(&p, rt->client_buffer_time);
519
f89584ca 520 return rtmp_send_packet(rt, &pkt, 0);
9477c035
SP
521}
522
523/**
49bd8e4b 524 * Generate 'play' call and send it to the server, then ping the server
9fd6b843
KS
525 * to start actual playing.
526 */
f645f1d6 527static int gen_play(URLContext *s, RTMPContext *rt)
9fd6b843
KS
528{
529 RTMPPacket pkt;
530 uint8_t *p;
f645f1d6 531 int ret;
9fd6b843 532
7f804085 533 av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
f645f1d6
SP
534
535 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE,
536 0, 29 + strlen(rt->playpath))) < 0)
537 return ret;
538
9fd6b843
KS
539 pkt.extra = rt->main_channel_id;
540
541 p = pkt.data;
542 ff_amf_write_string(&p, "play");
1eef08f9 543 ff_amf_write_number(&p, ++rt->nb_invokes);
9fd6b843
KS
544 ff_amf_write_null(&p);
545 ff_amf_write_string(&p, rt->playpath);
b2e495af 546 ff_amf_write_number(&p, rt->live);
9fd6b843 547
f89584ca 548 return rtmp_send_packet(rt, &pkt, 1);
9fd6b843
KS
549}
550
551/**
49bd8e4b 552 * Generate 'publish' call and send it to the server.
6bf22e18 553 */
f645f1d6 554static int gen_publish(URLContext *s, RTMPContext *rt)
6bf22e18
S
555{
556 RTMPPacket pkt;
557 uint8_t *p;
f645f1d6 558 int ret;
6bf22e18 559
7f804085 560 av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
f645f1d6
SP
561
562 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
563 0, 30 + strlen(rt->playpath))) < 0)
564 return ret;
565
6bf22e18
S
566 pkt.extra = rt->main_channel_id;
567
568 p = pkt.data;
569 ff_amf_write_string(&p, "publish");
1eef08f9 570 ff_amf_write_number(&p, ++rt->nb_invokes);
6bf22e18
S
571 ff_amf_write_null(&p);
572 ff_amf_write_string(&p, rt->playpath);
573 ff_amf_write_string(&p, "live");
574
f89584ca 575 return rtmp_send_packet(rt, &pkt, 1);
6bf22e18
S
576}
577
578/**
49bd8e4b 579 * Generate ping reply and send it to the server.
9fd6b843 580 */
f645f1d6 581static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
9fd6b843
KS
582{
583 RTMPPacket pkt;
584 uint8_t *p;
f645f1d6
SP
585 int ret;
586
8ea1459b
SP
587 if (ppkt->data_size < 6) {
588 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
589 ppkt->data_size);
590 return AVERROR_INVALIDDATA;
591 }
592
f645f1d6
SP
593 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
594 ppkt->timestamp + 1, 6)) < 0)
595 return ret;
9fd6b843 596
9fd6b843
KS
597 p = pkt.data;
598 bytestream_put_be16(&p, 7);
4aaebf78 599 bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
f645f1d6 600
f89584ca 601 return rtmp_send_packet(rt, &pkt, 0);
9fd6b843
KS
602}
603
bf7c1719 604/**
635ac8e1
SP
605 * Generate SWF verification message and send it to the server.
606 */
607static int gen_swf_verification(URLContext *s, RTMPContext *rt)
608{
609 RTMPPacket pkt;
610 uint8_t *p;
611 int ret;
612
613 av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
614 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
615 0, 44)) < 0)
616 return ret;
617
618 p = pkt.data;
619 bytestream_put_be16(&p, 27);
620 memcpy(p, rt->swfverification, 42);
621
622 return rtmp_send_packet(rt, &pkt, 0);
623}
624
625/**
34d908c0
RS
626 * Generate server bandwidth message and send it to the server.
627 */
f645f1d6 628static int gen_server_bw(URLContext *s, RTMPContext *rt)
34d908c0
RS
629{
630 RTMPPacket pkt;
631 uint8_t *p;
f645f1d6
SP
632 int ret;
633
634 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
635 0, 4)) < 0)
636 return ret;
34d908c0 637
34d908c0 638 p = pkt.data;
c2d38bea 639 bytestream_put_be32(&p, rt->server_bw);
f645f1d6 640
f89584ca 641 return rtmp_send_packet(rt, &pkt, 0);
34d908c0
RS
642}
643
644/**
d55961fa
SP
645 * Generate check bandwidth message and send it to the server.
646 */
f645f1d6 647static int gen_check_bw(URLContext *s, RTMPContext *rt)
d55961fa
SP
648{
649 RTMPPacket pkt;
650 uint8_t *p;
f645f1d6 651 int ret;
d55961fa 652
f645f1d6
SP
653 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
654 0, 21)) < 0)
655 return ret;
d55961fa
SP
656
657 p = pkt.data;
658 ff_amf_write_string(&p, "_checkbw");
8b6a5a79 659 ff_amf_write_number(&p, ++rt->nb_invokes);
d55961fa
SP
660 ff_amf_write_null(&p);
661
fb7e7808 662 return rtmp_send_packet(rt, &pkt, 1);
d55961fa
SP
663}
664
665/**
49bd8e4b 666 * Generate report on bytes read so far and send it to the server.
bf7c1719 667 */
f645f1d6 668static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
bf7c1719
KS
669{
670 RTMPPacket pkt;
671 uint8_t *p;
f645f1d6
SP
672 int ret;
673
674 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
675 ts, 4)) < 0)
676 return ret;
bf7c1719 677
bf7c1719
KS
678 p = pkt.data;
679 bytestream_put_be32(&p, rt->bytes_read);
f645f1d6 680
f89584ca 681 return rtmp_send_packet(rt, &pkt, 0);
bf7c1719
KS
682}
683
00cb52c6
SP
684static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
685 const char *subscribe)
f9e77c17
SP
686{
687 RTMPPacket pkt;
688 uint8_t *p;
689 int ret;
690
691 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
00cb52c6 692 0, 27 + strlen(subscribe))) < 0)
f9e77c17
SP
693 return ret;
694
695 p = pkt.data;
696 ff_amf_write_string(&p, "FCSubscribe");
697 ff_amf_write_number(&p, ++rt->nb_invokes);
698 ff_amf_write_null(&p);
00cb52c6 699 ff_amf_write_string(&p, subscribe);
f9e77c17 700
f89584ca 701 return rtmp_send_packet(rt, &pkt, 1);
f9e77c17
SP
702}
703
3505d557
SP
704int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
705 const uint8_t *key, int keylen, uint8_t *dst)
9fd6b843
KS
706{
707 struct AVSHA *sha;
708 uint8_t hmac_buf[64+32] = {0};
709 int i;
710
711 sha = av_mallocz(av_sha_size);
08e93f5b
SP
712 if (!sha)
713 return AVERROR(ENOMEM);
9fd6b843
KS
714
715 if (keylen < 64) {
716 memcpy(hmac_buf, key, keylen);
717 } else {
718 av_sha_init(sha, 256);
719 av_sha_update(sha,key, keylen);
720 av_sha_final(sha, hmac_buf);
721 }
722 for (i = 0; i < 64; i++)
723 hmac_buf[i] ^= HMAC_IPAD_VAL;
724
725 av_sha_init(sha, 256);
726 av_sha_update(sha, hmac_buf, 64);
727 if (gap <= 0) {
728 av_sha_update(sha, src, len);
729 } else { //skip 32 bytes used for storing digest
730 av_sha_update(sha, src, gap);
731 av_sha_update(sha, src + gap + 32, len - gap - 32);
732 }
733 av_sha_final(sha, hmac_buf + 64);
734
735 for (i = 0; i < 64; i++)
736 hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
737 av_sha_init(sha, 256);
738 av_sha_update(sha, hmac_buf, 64+32);
739 av_sha_final(sha, dst);
740
741 av_free(sha);
08e93f5b
SP
742
743 return 0;
9fd6b843
KS
744}
745
0e31088b
SP
746int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
747 int add_val)
748{
749 int i, digest_pos = 0;
750
751 for (i = 0; i < 4; i++)
752 digest_pos += buf[i + off];
753 digest_pos = digest_pos % mod_val + add_val;
754
755 return digest_pos;
756}
757
9fd6b843 758/**
49bd8e4b 759 * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
9fd6b843
KS
760 * will be stored) into that packet.
761 *
762 * @param buf handshake data (1536 bytes)
acd554c1 763 * @param encrypted use an encrypted connection (RTMPE)
9fd6b843
KS
764 * @return offset to the digest inside input data
765 */
acd554c1 766static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
9fd6b843 767{
0e31088b 768 int ret, digest_pos;
9fd6b843 769
acd554c1
SP
770 if (encrypted)
771 digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
772 else
773 digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
9fd6b843 774
3505d557
SP
775 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
776 rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
777 buf + digest_pos);
08e93f5b
SP
778 if (ret < 0)
779 return ret;
780
9fd6b843
KS
781 return digest_pos;
782}
783
784/**
49bd8e4b 785 * Verify that the received server response has the expected digest value.
9fd6b843
KS
786 *
787 * @param buf handshake data received from the server (1536 bytes)
788 * @param off position to search digest offset from
789 * @return 0 if digest is valid, digest position otherwise
790 */
791static int rtmp_validate_digest(uint8_t *buf, int off)
792{
9fd6b843 793 uint8_t digest[32];
0e31088b 794 int ret, digest_pos;
9fd6b843 795
0e31088b 796 digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
9fd6b843 797
3505d557
SP
798 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
799 rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
800 digest);
08e93f5b
SP
801 if (ret < 0)
802 return ret;
803
9fd6b843
KS
804 if (!memcmp(digest, buf + digest_pos, 32))
805 return digest_pos;
806 return 0;
807}
808
635ac8e1
SP
809static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
810 uint8_t *buf)
811{
812 uint8_t *p;
813 int ret;
814
815 if (rt->swfhash_len != 32) {
816 av_log(s, AV_LOG_ERROR,
817 "Hash of the decompressed SWF file is not 32 bytes long.\n");
818 return AVERROR(EINVAL);
819 }
820
821 p = &rt->swfverification[0];
822 bytestream_put_byte(&p, 1);
823 bytestream_put_byte(&p, 1);
824 bytestream_put_be32(&p, rt->swfsize);
825 bytestream_put_be32(&p, rt->swfsize);
826
827 if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
828 return ret;
829
830 return 0;
831}
832
93f257db
SP
833#if CONFIG_ZLIB
834static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
835 uint8_t **out_data, int64_t *out_size)
836{
837 z_stream zs = { 0 };
838 void *ptr;
839 int size;
840 int ret = 0;
841
842 zs.avail_in = in_size;
843 zs.next_in = in_data;
844 ret = inflateInit(&zs);
845 if (ret != Z_OK)
846 return AVERROR_UNKNOWN;
847
848 do {
849 uint8_t tmp_buf[16384];
850
851 zs.avail_out = sizeof(tmp_buf);
852 zs.next_out = tmp_buf;
853
854 ret = inflate(&zs, Z_NO_FLUSH);
855 if (ret != Z_OK && ret != Z_STREAM_END) {
856 ret = AVERROR_UNKNOWN;
857 goto fail;
858 }
859
860 size = sizeof(tmp_buf) - zs.avail_out;
861 if (!(ptr = av_realloc(*out_data, *out_size + size))) {
862 ret = AVERROR(ENOMEM);
863 goto fail;
864 }
865 *out_data = ptr;
866
867 memcpy(*out_data + *out_size, tmp_buf, size);
868 *out_size += size;
869 } while (zs.avail_out == 0);
870
871fail:
872 inflateEnd(&zs);
873 return ret;
874}
875#endif
876
877static int rtmp_calc_swfhash(URLContext *s)
878{
879 RTMPContext *rt = s->priv_data;
880 uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
881 int64_t in_size, out_size;
882 URLContext *stream;
883 char swfhash[32];
884 int swfsize;
885 int ret = 0;
886
887 /* Get the SWF player file. */
888 if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
889 &s->interrupt_callback, NULL)) < 0) {
890 av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
891 goto fail;
892 }
893
894 if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
895 ret = AVERROR(EIO);
896 goto fail;
897 }
898
899 if (!(in_data = av_malloc(in_size))) {
900 ret = AVERROR(ENOMEM);
901 goto fail;
902 }
903
904 if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
905 goto fail;
906
907 if (in_size < 3) {
908 ret = AVERROR_INVALIDDATA;
909 goto fail;
910 }
911
912 if (!memcmp(in_data, "CWS", 3)) {
913 /* Decompress the SWF player file using Zlib. */
914 if (!(out_data = av_malloc(8))) {
915 ret = AVERROR(ENOMEM);
916 goto fail;
917 }
918 *in_data = 'F'; // magic stuff
919 memcpy(out_data, in_data, 8);
920 out_size = 8;
921
922#if CONFIG_ZLIB
923 if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
924 &out_data, &out_size)) < 0)
925 goto fail;
926#else
927 av_log(s, AV_LOG_ERROR,
928 "Zlib is required for decompressing the SWF player file.\n");
929 ret = AVERROR(EINVAL);
930 goto fail;
931#endif
932 swfsize = out_size;
933 swfdata = out_data;
934 } else {
935 swfsize = in_size;
936 swfdata = in_data;
937 }
938
939 /* Compute the SHA256 hash of the SWF player file. */
940 if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
941 "Genuine Adobe Flash Player 001", 30,
942 swfhash)) < 0)
943 goto fail;
944
945 /* Set SWFVerification parameters. */
946 av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
947 rt->swfsize = swfsize;
948
949fail:
950 av_freep(&in_data);
951 av_freep(&out_data);
952 ffurl_close(stream);
953 return ret;
954}
955
9fd6b843 956/**
49bd8e4b 957 * Perform handshake with the server by means of exchanging pseudorandom data
9fd6b843
KS
958 * signed with HMAC-SHA2 digest.
959 *
960 * @return 0 if handshake succeeds, negative value otherwise
961 */
962static int rtmp_handshake(URLContext *s, RTMPContext *rt)
963{
964 AVLFG rnd;
965 uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
966 3, // unencrypted data
967 0, 0, 0, 0, // client uptime
968 RTMP_CLIENT_VER1,
969 RTMP_CLIENT_VER2,
970 RTMP_CLIENT_VER3,
971 RTMP_CLIENT_VER4,
972 };
973 uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
974 uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
975 int i;
976 int server_pos, client_pos;
acd554c1 977 uint8_t digest[32], signature[32];
acd554c1 978 int ret, type = 0;
9fd6b843 979
7f804085 980 av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
9fd6b843
KS
981
982 av_lfg_init(&rnd, 0xDEADC0DE);
983 // generate handshake packet - 1536 bytes of pseudorandom data
984 for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
985 tosend[i] = av_lfg_get(&rnd) >> 24;
acd554c1 986
f7bfb126 987 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
acd554c1
SP
988 /* When the client wants to use RTMPE, we have to change the command
989 * byte to 0x06 which means to use encrypted data and we have to set
990 * the flash version to at least 9.0.115.0. */
991 tosend[0] = 6;
992 tosend[5] = 128;
993 tosend[6] = 0;
994 tosend[7] = 3;
995 tosend[8] = 2;
996
997 /* Initialize the Diffie-Hellmann context and generate the public key
998 * to send to the server. */
999 if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1000 return ret;
1001 }
1002
f7bfb126 1003 client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
08e93f5b
SP
1004 if (client_pos < 0)
1005 return client_pos;
9fd6b843 1006
bba287fd
SP
1007 if ((ret = ffurl_write(rt->stream, tosend,
1008 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1009 av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1010 return ret;
1011 }
1012
177bcc95
SP
1013 if ((ret = ffurl_read_complete(rt->stream, serverdata,
1014 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
7f804085 1015 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
177bcc95 1016 return ret;
9fd6b843 1017 }
177bcc95
SP
1018
1019 if ((ret = ffurl_read_complete(rt->stream, clientdata,
1020 RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
7f804085 1021 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
177bcc95 1022 return ret;
9fd6b843
KS
1023 }
1024
acd554c1 1025 av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
7f804085 1026 av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
9fd6b843
KS
1027 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1028
e2ee11e8 1029 if (rt->is_input && serverdata[5] >= 3) {
c7240611 1030 server_pos = rtmp_validate_digest(serverdata + 1, 772);
08e93f5b
SP
1031 if (server_pos < 0)
1032 return server_pos;
1033
9fd6b843 1034 if (!server_pos) {
acd554c1 1035 type = 1;
c7240611 1036 server_pos = rtmp_validate_digest(serverdata + 1, 8);
08e93f5b
SP
1037 if (server_pos < 0)
1038 return server_pos;
1039
c7240611 1040 if (!server_pos) {
7f804085 1041 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
a4d3f358 1042 return AVERROR(EIO);
c7240611 1043 }
9fd6b843 1044 }
9fd6b843 1045
635ac8e1
SP
1046 /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1047 * key are the last 32 bytes of the server handshake. */
1048 if (rt->swfsize) {
1049 if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1050 RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1051 return ret;
1052 }
1053
3505d557
SP
1054 ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1055 rtmp_server_key, sizeof(rtmp_server_key),
1056 digest);
08e93f5b
SP
1057 if (ret < 0)
1058 return ret;
1059
3505d557 1060 ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
acd554c1 1061 0, digest, 32, signature);
08e93f5b
SP
1062 if (ret < 0)
1063 return ret;
1064
f7bfb126 1065 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
acd554c1
SP
1066 /* Compute the shared secret key sent by the server and initialize
1067 * the RC4 encryption. */
1068 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1069 tosend + 1, type)) < 0)
1070 return ret;
1071
1072 /* Encrypt the signature received by the server. */
1073 ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1074 }
1075
1076 if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
7f804085 1077 av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
a4d3f358 1078 return AVERROR(EIO);
c7240611 1079 }
9fd6b843 1080
c7240611
KS
1081 for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1082 tosend[i] = av_lfg_get(&rnd) >> 24;
3505d557
SP
1083 ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1084 rtmp_player_key, sizeof(rtmp_player_key),
1085 digest);
08e93f5b
SP
1086 if (ret < 0)
1087 return ret;
1088
3505d557
SP
1089 ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1090 digest, 32,
1091 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
08e93f5b
SP
1092 if (ret < 0)
1093 return ret;
c7240611 1094
f7bfb126 1095 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
acd554c1
SP
1096 /* Encrypt the signature to be send to the server. */
1097 ff_rtmpe_encrypt_sig(rt->stream, tosend +
1098 RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1099 serverdata[0]);
1100 }
1101
c7240611 1102 // write reply back to the server
bba287fd
SP
1103 if ((ret = ffurl_write(rt->stream, tosend,
1104 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1105 return ret;
acd554c1 1106
f7bfb126 1107 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
acd554c1
SP
1108 /* Set RC4 keys for encryption and update the keystreams. */
1109 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1110 return ret;
1111 }
6bf22e18 1112 } else {
f7bfb126 1113 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
acd554c1
SP
1114 /* Compute the shared secret key sent by the server and initialize
1115 * the RC4 encryption. */
1116 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1117 tosend + 1, 1)) < 0)
1118 return ret;
1119
1120 if (serverdata[0] == 9) {
1121 /* Encrypt the signature received by the server. */
1122 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1123 serverdata[0]);
1124 }
1125 }
1126
bba287fd
SP
1127 if ((ret = ffurl_write(rt->stream, serverdata + 1,
1128 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1129 return ret;
acd554c1 1130
f7bfb126 1131 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
acd554c1
SP
1132 /* Set RC4 keys for encryption and update the keystreams. */
1133 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1134 return ret;
1135 }
6bf22e18
S
1136 }
1137
9fd6b843
KS
1138 return 0;
1139}
1140
7be2a7d8
SP
1141static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1142{
1143 RTMPContext *rt = s->priv_data;
1144 int ret;
1145
e49e6b64 1146 if (pkt->data_size < 4) {
7be2a7d8 1147 av_log(s, AV_LOG_ERROR,
e49e6b64 1148 "Too short chunk size change packet (%d)\n",
7be2a7d8 1149 pkt->data_size);
e7ea6883 1150 return AVERROR_INVALIDDATA;
7be2a7d8
SP
1151 }
1152
1153 if (!rt->is_input) {
f5ce90f2
JO
1154 /* Send the same chunk size change packet back to the server,
1155 * setting the outgoing chunk size to the same as the incoming one. */
1156 if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
7be2a7d8
SP
1157 rt->prev_pkt[1])) < 0)
1158 return ret;
f5ce90f2 1159 rt->out_chunk_size = AV_RB32(pkt->data);
7be2a7d8
SP
1160 }
1161
f5ce90f2
JO
1162 rt->in_chunk_size = AV_RB32(pkt->data);
1163 if (rt->in_chunk_size <= 0) {
1164 av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1165 rt->in_chunk_size);
e7ea6883 1166 return AVERROR_INVALIDDATA;
7be2a7d8 1167 }
f5ce90f2
JO
1168 av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1169 rt->in_chunk_size);
7be2a7d8
SP
1170
1171 return 0;
1172}
1173
0ffd5161
SP
1174static int handle_ping(URLContext *s, RTMPPacket *pkt)
1175{
1176 RTMPContext *rt = s->priv_data;
1177 int t, ret;
1178
8ea1459b
SP
1179 if (pkt->data_size < 2) {
1180 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
1181 pkt->data_size);
1182 return AVERROR_INVALIDDATA;
1183 }
1184
0ffd5161
SP
1185 t = AV_RB16(pkt->data);
1186 if (t == 6) {
1187 if ((ret = gen_pong(s, rt, pkt)) < 0)
1188 return ret;
635ac8e1
SP
1189 } else if (t == 26) {
1190 if (rt->swfsize) {
1191 if ((ret = gen_swf_verification(s, rt)) < 0)
1192 return ret;
1193 } else {
1194 av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1195 }
0ffd5161
SP
1196 }
1197
1198 return 0;
1199}
1200
912ecc9a
SP
1201static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
1202{
1203 RTMPContext *rt = s->priv_data;
1204
1205 if (pkt->data_size < 4) {
1206 av_log(s, AV_LOG_ERROR,
1207 "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1208 pkt->data_size);
088a82bb 1209 return AVERROR_INVALIDDATA;
912ecc9a 1210 }
abf77a24
SP
1211
1212 rt->client_report_size = AV_RB32(pkt->data);
1213 if (rt->client_report_size <= 0) {
1214 av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
1215 rt->client_report_size);
1216 return AVERROR_INVALIDDATA;
1217
1218 }
1219 av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
1220 rt->client_report_size >>= 1;
912ecc9a
SP
1221
1222 return 0;
1223}
1224
9b498148
SP
1225static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
1226{
1227 RTMPContext *rt = s->priv_data;
1228
2357f606
SP
1229 if (pkt->data_size < 4) {
1230 av_log(s, AV_LOG_ERROR,
1231 "Too short server bandwidth report packet (%d)\n",
1232 pkt->data_size);
1233 return AVERROR_INVALIDDATA;
1234 }
1235
9b498148
SP
1236 rt->server_bw = AV_RB32(pkt->data);
1237 if (rt->server_bw <= 0) {
1238 av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
1239 rt->server_bw);
be8f9492 1240 return AVERROR_INVALIDDATA;
9b498148
SP
1241 }
1242 av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
1243
1244 return 0;
1245}
1246
3eebc1e1
SP
1247static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1248{
1249 const uint8_t *data_end = pkt->data + pkt->data_size;
fb7e7808
SP
1250 char *tracked_method = NULL;
1251 int level = AV_LOG_ERROR;
3eebc1e1 1252 uint8_t tmpstr[256];
fb7e7808
SP
1253 int ret;
1254
1255 if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1256 return ret;
3eebc1e1
SP
1257
1258 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1259 "description", tmpstr, sizeof(tmpstr))) {
fb7e7808
SP
1260 if (tracked_method && !strcmp(tracked_method, "_checkbw")) {
1261 /* Ignore _checkbw errors. */
1262 level = AV_LOG_WARNING;
1263 ret = 0;
1264 } else
1265 ret = -1;
1266 av_log(s, level, "Server error: %s\n", tmpstr);
3eebc1e1
SP
1267 }
1268
fb7e7808
SP
1269 av_free(tracked_method);
1270 return ret;
3eebc1e1
SP
1271}
1272
5e6001db
SP
1273static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1274{
1275 RTMPContext *rt = s->priv_data;
1276 char *tracked_method = NULL;
5e6001db 1277 int ret = 0;
5e6001db 1278
a8103503 1279 if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
5e6001db
SP
1280 return ret;
1281
5e6001db
SP
1282 if (!tracked_method) {
1283 /* Ignore this reply when the current method is not tracked. */
1284 return ret;
1285 }
1286
1287 if (!memcmp(tracked_method, "connect", 7)) {
1288 if (!rt->is_input) {
1289 if ((ret = gen_release_stream(s, rt)) < 0)
1290 goto fail;
1291
1292 if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1293 goto fail;
1294 } else {
1295 if ((ret = gen_server_bw(s, rt)) < 0)
1296 goto fail;
1297 }
1298
1299 if ((ret = gen_create_stream(s, rt)) < 0)
1300 goto fail;
1301
1302 if (rt->is_input) {
1303 /* Send the FCSubscribe command when the name of live
1304 * stream is defined by the user or if it's a live stream. */
1305 if (rt->subscribe) {
1306 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1307 goto fail;
1308 } else if (rt->live == -1) {
1309 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1310 goto fail;
1311 }
1312 }
1313 } else if (!memcmp(tracked_method, "createStream", 12)) {
1314 //extract a number from the result
1315 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1316 av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
1317 } else {
1318 rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
1319 }
1320
1321 if (!rt->is_input) {
1322 if ((ret = gen_publish(s, rt)) < 0)
1323 goto fail;
1324 } else {
1325 if ((ret = gen_play(s, rt)) < 0)
1326 goto fail;
1327 if ((ret = gen_buffer_time(s, rt)) < 0)
1328 goto fail;
1329 }
1330 }
1331
1332fail:
1333 av_free(tracked_method);
1334 return ret;
1335}
1336
71036a3a 1337static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
9fd6b843 1338{
6d1c9945 1339 RTMPContext *rt = s->priv_data;
71036a3a
SP
1340 const uint8_t *data_end = pkt->data + pkt->data_size;
1341 const uint8_t *ptr = pkt->data + 11;
1342 uint8_t tmpstr[256];
9fd6b843 1343 int i, t;
71036a3a
SP
1344
1345 for (i = 0; i < 2; i++) {
1346 t = ff_amf_tag_size(ptr, data_end);
1347 if (t < 0)
1348 return 1;
1349 ptr += t;
1350 }
1351
1352 t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
1353 if (!t && !strcmp(tmpstr, "error")) {
1354 if (!ff_amf_get_field_value(ptr, data_end,
1355 "description", tmpstr, sizeof(tmpstr)))
1356 av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
1357 return -1;
1358 }
1359
1360 t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
1361 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
1362 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
1363 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
1364 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
1365
1366 return 0;
1367}
1368
1369static int handle_invoke(URLContext *s, RTMPPacket *pkt)
1370{
1371 RTMPContext *rt = s->priv_data;
f89584ca 1372 int ret = 0;
9fd6b843 1373
6d1c9945
SP
1374 //TODO: check for the messages sent for wrong state?
1375 if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
3eebc1e1
SP
1376 if ((ret = handle_invoke_error(s, pkt)) < 0)
1377 return ret;
6d1c9945 1378 } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
5e6001db 1379 if ((ret = handle_invoke_result(s, pkt)) < 0)
f89584ca 1380 return ret;
6d1c9945 1381 } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
71036a3a
SP
1382 if ((ret = handle_invoke_status(s, pkt)) < 0)
1383 return ret;
6d1c9945
SP
1384 } else if (!memcmp(pkt->data, "\002\000\010onBWDone", 11)) {
1385 if ((ret = gen_check_bw(s, rt)) < 0)
1386 return ret;
1387 }
1388
f89584ca 1389 return ret;
6d1c9945
SP
1390}
1391
1392/**
1393 * Parse received packet and possibly perform some action depending on
1394 * the packet contents.
1395 * @return 0 for no errors, negative values for serious errors which prevent
1396 * further communications, positive values for uncritical errors
1397 */
1398static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
1399{
1400 int ret;
1401
1402#ifdef DEBUG
1403 ff_rtmp_packet_dump(s, pkt);
1404#endif
1405
1406 switch (pkt->type) {
fb96c1c5
LB
1407 case RTMP_PT_BYTES_READ:
1408 av_dlog(s, "received bytes read report\n");
1409 break;
6d1c9945
SP
1410 case RTMP_PT_CHUNK_SIZE:
1411 if ((ret = handle_chunk_size(s, pkt)) < 0)
1412 return ret;
1413 break;
1414 case RTMP_PT_PING:
1415 if ((ret = handle_ping(s, pkt)) < 0)
1416 return ret;
1417 break;
1418 case RTMP_PT_CLIENT_BW:
1419 if ((ret = handle_client_bw(s, pkt)) < 0)
1420 return ret;
1421 break;
1422 case RTMP_PT_SERVER_BW:
1423 if ((ret = handle_server_bw(s, pkt)) < 0)
1424 return ret;
1425 break;
1426 case RTMP_PT_INVOKE:
1427 if ((ret = handle_invoke(s, pkt)) < 0)
1428 return ret;
9fd6b843 1429 break;
08e087cc
JO
1430 case RTMP_PT_VIDEO:
1431 case RTMP_PT_AUDIO:
9c9c21ea
SP
1432 case RTMP_PT_METADATA:
1433 /* Audio, Video and Metadata packets are parsed in get_packet() */
08e087cc 1434 break;
9ff930aa
SP
1435 default:
1436 av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
1437 break;
9fd6b843
KS
1438 }
1439 return 0;
1440}
1441
1442/**
49bd8e4b 1443 * Interact with the server by receiving and sending RTMP packets until
9fd6b843
KS
1444 * there is some significant data (media data or expected status notification).
1445 *
1446 * @param s reading context
1d8041b3
SS
1447 * @param for_header non-zero value tells function to work until it
1448 * gets notification from the server that playing has been started,
1449 * otherwise function will work until some media data is received (or
1450 * an error happens)
9fd6b843
KS
1451 * @return 0 for successful operation, negative value in case of error
1452 */
1453static int get_packet(URLContext *s, int for_header)
1454{
1455 RTMPContext *rt = s->priv_data;
1456 int ret;
56e29bf2
S
1457 uint8_t *p;
1458 const uint8_t *next;
1459 uint32_t data_size;
1460 uint32_t ts, cts, pts=0;
9fd6b843 1461
72b870b9
MS
1462 if (rt->state == STATE_STOPPED)
1463 return AVERROR_EOF;
1464
e07c92e4 1465 for (;;) {
271c869c 1466 RTMPPacket rpkt = { 0 };
9fd6b843 1467 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
f5ce90f2 1468 rt->in_chunk_size, rt->prev_pkt[0])) <= 0) {
b381a823 1469 if (ret == 0) {
9fd6b843
KS
1470 return AVERROR(EAGAIN);
1471 } else {
1472 return AVERROR(EIO);
1473 }
1474 }
bf7c1719
KS
1475 rt->bytes_read += ret;
1476 if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
7f804085 1477 av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
f645f1d6
SP
1478 if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
1479 return ret;
bf7c1719
KS
1480 rt->last_bytes_read = rt->bytes_read;
1481 }
9fd6b843
KS
1482
1483 ret = rtmp_parse_result(s, rt, &rpkt);
1484 if (ret < 0) {//serious error in current packet
1485 ff_rtmp_packet_destroy(&rpkt);
f645f1d6 1486 return ret;
9fd6b843 1487 }
72b870b9
MS
1488 if (rt->state == STATE_STOPPED) {
1489 ff_rtmp_packet_destroy(&rpkt);
1490 return AVERROR_EOF;
1491 }
6bf22e18 1492 if (for_header && (rt->state == STATE_PLAYING || rt->state == STATE_PUBLISHING)) {
9fd6b843
KS
1493 ff_rtmp_packet_destroy(&rpkt);
1494 return 0;
1495 }
6bf22e18 1496 if (!rpkt.data_size || !rt->is_input) {
9fd6b843
KS
1497 ff_rtmp_packet_destroy(&rpkt);
1498 continue;
1499 }
1500 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
afbacb93 1501 (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
56e29bf2 1502 ts = rpkt.timestamp;
9fd6b843 1503
9fd6b843
KS
1504 // generate packet header and put data into buffer for FLV demuxer
1505 rt->flv_off = 0;
1506 rt->flv_size = rpkt.data_size + 15;
1507 rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
1508 bytestream_put_byte(&p, rpkt.type);
1509 bytestream_put_be24(&p, rpkt.data_size);
1510 bytestream_put_be24(&p, ts);
1511 bytestream_put_byte(&p, ts >> 24);
1512 bytestream_put_be24(&p, 0);
1513 bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);
1514 bytestream_put_be32(&p, 0);
1515 ff_rtmp_packet_destroy(&rpkt);
1516 return 0;
1517 } else if (rpkt.type == RTMP_PT_METADATA) {
1518 // we got raw FLV data, make it available for FLV demuxer
1519 rt->flv_off = 0;
1520 rt->flv_size = rpkt.data_size;
1521 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
56e29bf2
S
1522 /* rewrite timestamps */
1523 next = rpkt.data;
1524 ts = rpkt.timestamp;
1525 while (next - rpkt.data < rpkt.data_size - 11) {
1526 next++;
1527 data_size = bytestream_get_be24(&next);
1528 p=next;
1529 cts = bytestream_get_be24(&next);
aae9a093 1530 cts |= bytestream_get_byte(&next) << 24;
56e29bf2
S
1531 if (pts==0)
1532 pts=cts;
1533 ts += cts - pts;
1534 pts = cts;
1535 bytestream_put_be24(&p, ts);
1536 bytestream_put_byte(&p, ts >> 24);
1537 next += data_size + 3 + 4;
1538 }
9fd6b843
KS
1539 memcpy(rt->flv_data, rpkt.data, rpkt.data_size);
1540 ff_rtmp_packet_destroy(&rpkt);
1541 return 0;
1542 }
1543 ff_rtmp_packet_destroy(&rpkt);
1544 }
9fd6b843
KS
1545}
1546
1547static int rtmp_close(URLContext *h)
1548{
1549 RTMPContext *rt = h->priv_data;
f645f1d6 1550 int ret = 0;
9fd6b843 1551
e07c92e4 1552 if (!rt->is_input) {
6bf22e18
S
1553 rt->flv_data = NULL;
1554 if (rt->out_pkt.data_size)
1555 ff_rtmp_packet_destroy(&rt->out_pkt);
615c2879 1556 if (rt->state > STATE_FCPUBLISH)
f645f1d6 1557 ret = gen_fcunpublish_stream(h, rt);
6bf22e18 1558 }
615c2879 1559 if (rt->state > STATE_HANDSHAKED)
f645f1d6 1560 ret = gen_delete_stream(h, rt);
6bf22e18 1561
f89584ca 1562 free_tracked_methods(rt);
9fd6b843 1563 av_freep(&rt->flv_data);
e52a9145 1564 ffurl_close(rt->stream);
f645f1d6 1565 return ret;
9fd6b843
KS
1566}
1567
1568/**
49bd8e4b 1569 * Open RTMP connection and verify that the stream can be played.
9fd6b843
KS
1570 *
1571 * URL syntax: rtmp://server[:port][/app][/playpath]
1572 * where 'app' is first one or two directories in the path
1573 * (e.g. /ondemand/, /flash/live/, etc.)
1574 * and 'playpath' is a file name (the rest of the path,
1575 * may be prefixed with "mp4:")
1576 */
1577static int rtmp_open(URLContext *s, const char *uri, int flags)
1578{
7e580505 1579 RTMPContext *rt = s->priv_data;
5e9ad759 1580 char proto[8], hostname[256], path[1024], *fname;
6465562e 1581 char *old_app;
9fd6b843 1582 uint8_t buf[2048];
b316991b 1583 int port;
86991ce2 1584 AVDictionary *opts = NULL;
9fd6b843
KS
1585 int ret;
1586
59d96941 1587 rt->is_input = !(flags & AVIO_FLAG_WRITE);
9fd6b843 1588
f3bfe388 1589 av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
f984dcf6 1590 path, sizeof(path), s->filename);
9fd6b843 1591
86991ce2
SP
1592 if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
1593 if (!strcmp(proto, "rtmpts"))
1594 av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
1595
8e50c57d 1596 /* open the http tunneling connection */
775c4d36 1597 ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
6aedabc9
SP
1598 } else if (!strcmp(proto, "rtmps")) {
1599 /* open the tls connection */
1600 if (port < 0)
1601 port = RTMPS_DEFAULT_PORT;
1602 ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
08cd95e8
SP
1603 } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
1604 if (!strcmp(proto, "rtmpte"))
1605 av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
1606
acd554c1
SP
1607 /* open the encrypted connection */
1608 ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
1609 rt->encrypted = 1;
8e50c57d
SP
1610 } else {
1611 /* open the tcp connection */
1612 if (port < 0)
1613 port = RTMP_DEFAULT_PORT;
1614 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
1615 }
9fd6b843 1616
f645f1d6 1617 if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
86991ce2 1618 &s->interrupt_callback, &opts)) < 0) {
59d96941 1619 av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
9fd6b843 1620 goto fail;
fe523958 1621 }
9fd6b843 1622
93f257db
SP
1623 if (rt->swfverify) {
1624 if ((ret = rtmp_calc_swfhash(s)) < 0)
1625 goto fail;
1626 }
1627
c7240611 1628 rt->state = STATE_START;
f645f1d6 1629 if ((ret = rtmp_handshake(s, rt)) < 0)
02490bf3 1630 goto fail;
9fd6b843 1631
f5ce90f2
JO
1632 rt->out_chunk_size = 128;
1633 rt->in_chunk_size = 128; // Probably overwritten later
c7240611 1634 rt->state = STATE_HANDSHAKED;
6465562e
SP
1635
1636 // Keep the application name when it has been defined by the user.
1637 old_app = rt->app;
1638
1639 rt->app = av_malloc(APP_MAX_LENGTH);
1640 if (!rt->app) {
f645f1d6
SP
1641 ret = AVERROR(ENOMEM);
1642 goto fail;
6465562e
SP
1643 }
1644
c7240611
KS
1645 //extract "app" part from path
1646 if (!strncmp(path, "/ondemand/", 10)) {
1647 fname = path + 10;
1648 memcpy(rt->app, "ondemand", 9);
1649 } else {
4b7304e8
MS
1650 char *next = *path ? path + 1 : path;
1651 char *p = strchr(next, '/');
c7240611 1652 if (!p) {
4b7304e8 1653 fname = next;
c7240611 1654 rt->app[0] = '\0';
9fd6b843 1655 } else {
c6eeb9b7 1656 // make sure we do not mismatch a playpath for an application instance
c7240611
KS
1657 char *c = strchr(p + 1, ':');
1658 fname = strchr(p + 1, '/');
c6eeb9b7 1659 if (!fname || (c && c < fname)) {
c7240611
KS
1660 fname = p + 1;
1661 av_strlcpy(rt->app, path + 1, p - path);
9fd6b843 1662 } else {
c7240611
KS
1663 fname++;
1664 av_strlcpy(rt->app, path + 1, fname - path - 1);
9fd6b843
KS
1665 }
1666 }
c7240611 1667 }
6465562e
SP
1668
1669 if (old_app) {
1670 // The name of application has been defined by the user, override it.
1671 av_free(rt->app);
1672 rt->app = old_app;
1673 }
1674
b3b17512 1675 if (!rt->playpath) {
f862537d
SP
1676 int len = strlen(fname);
1677
b3b17512
SP
1678 rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
1679 if (!rt->playpath) {
f645f1d6
SP
1680 ret = AVERROR(ENOMEM);
1681 goto fail;
b3b17512
SP
1682 }
1683
0a9a2257 1684 if (!strchr(fname, ':') && len >= 4 &&
f862537d
SP
1685 (!strcmp(fname + len - 4, ".f4v") ||
1686 !strcmp(fname + len - 4, ".mp4"))) {
b3b17512 1687 memcpy(rt->playpath, "mp4:", 5);
0a9a2257 1688 } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
f862537d 1689 fname[len - 4] = '\0';
b3b17512
SP
1690 } else {
1691 rt->playpath[0] = 0;
1692 }
1693 strncat(rt->playpath, fname, PLAYPATH_MAX_LENGTH - 5);
c7240611 1694 }
9fd6b843 1695
55c9320e
SP
1696 if (!rt->tcurl) {
1697 rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
08e93f5b
SP
1698 if (!rt->tcurl) {
1699 ret = AVERROR(ENOMEM);
1700 goto fail;
1701 }
55c9320e
SP
1702 ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
1703 port, "/%s", rt->app);
1704 }
1705
e64673e4
SP
1706 if (!rt->flashver) {
1707 rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
08e93f5b
SP
1708 if (!rt->flashver) {
1709 ret = AVERROR(ENOMEM);
1710 goto fail;
1711 }
e64673e4
SP
1712 if (rt->is_input) {
1713 snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
1714 RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
1715 RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
1716 } else {
1717 snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
1718 "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
1719 }
1720 }
1721
bf7c1719
KS
1722 rt->client_report_size = 1048576;
1723 rt->bytes_read = 0;
1724 rt->last_bytes_read = 0;
c2d38bea 1725 rt->server_bw = 2500000;
bf7c1719 1726
7f804085 1727 av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
c7240611 1728 proto, path, rt->app, rt->playpath);
f645f1d6
SP
1729 if ((ret = gen_connect(s, rt)) < 0)
1730 goto fail;
9fd6b843 1731
c7240611
KS
1732 do {
1733 ret = get_packet(s, 1);
1734 } while (ret == EAGAIN);
1735 if (ret < 0)
1736 goto fail;
6bf22e18
S
1737
1738 if (rt->is_input) {
9fd6b843
KS
1739 // generate FLV header for demuxer
1740 rt->flv_size = 13;
1741 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
1742 rt->flv_off = 0;
1743 memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
6bf22e18
S
1744 } else {
1745 rt->flv_size = 0;
1746 rt->flv_data = NULL;
1747 rt->flv_off = 0;
b14629e5 1748 rt->skip_bytes = 13;
9fd6b843
KS
1749 }
1750
5958df34 1751 s->max_packet_size = rt->stream->max_packet_size;
9fd6b843
KS
1752 s->is_streamed = 1;
1753 return 0;
1754
1755fail:
86991ce2 1756 av_dict_free(&opts);
9fd6b843 1757 rtmp_close(s);
f645f1d6 1758 return ret;
9fd6b843
KS
1759}
1760
1761static int rtmp_read(URLContext *s, uint8_t *buf, int size)
1762{
1763 RTMPContext *rt = s->priv_data;
1764 int orig_size = size;
1765 int ret;
1766
1767 while (size > 0) {
1768 int data_left = rt->flv_size - rt->flv_off;
1769
1770 if (data_left >= size) {
1771 memcpy(buf, rt->flv_data + rt->flv_off, size);
1772 rt->flv_off += size;
1773 return orig_size;
1774 }
1775 if (data_left > 0) {
1776 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
1777 buf += data_left;
1778 size -= data_left;
1779 rt->flv_off = rt->flv_size;
e8ccf245 1780 return data_left;
9fd6b843
KS
1781 }
1782 if ((ret = get_packet(s, 0)) < 0)
1783 return ret;
1784 }
1785 return orig_size;
1786}
1787
9ad4c65f 1788static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
9fd6b843 1789{
9ad4c65f 1790 RTMPContext *rt = s->priv_data;
6bf22e18
S
1791 int size_temp = size;
1792 int pktsize, pkttype;
1793 uint32_t ts;
1794 const uint8_t *buf_temp = buf;
7dc747f5 1795 uint8_t c;
f645f1d6 1796 int ret;
6bf22e18 1797
6bf22e18 1798 do {
b14629e5
MS
1799 if (rt->skip_bytes) {
1800 int skip = FFMIN(rt->skip_bytes, size_temp);
1801 buf_temp += skip;
1802 size_temp -= skip;
1803 rt->skip_bytes -= skip;
1804 continue;
1805 }
1806
1807 if (rt->flv_header_bytes < 11) {
1808 const uint8_t *header = rt->flv_header;
1809 int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
1810 bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
1811 rt->flv_header_bytes += copy;
1812 size_temp -= copy;
1813 if (rt->flv_header_bytes < 11)
1814 break;
6bf22e18 1815
b14629e5
MS
1816 pkttype = bytestream_get_byte(&header);
1817 pktsize = bytestream_get_be24(&header);
1818 ts = bytestream_get_be24(&header);
1819 ts |= bytestream_get_byte(&header) << 24;
1820 bytestream_get_be24(&header);
6bf22e18
S
1821 rt->flv_size = pktsize;
1822
1823 //force 12bytes header
1824 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
1825 pkttype == RTMP_PT_NOTIFY) {
1826 if (pkttype == RTMP_PT_NOTIFY)
1827 pktsize += 16;
1828 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
1829 }
1830
1831 //this can be a big packet, it's better to send it right here
f645f1d6
SP
1832 if ((ret = ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL,
1833 pkttype, ts, pktsize)) < 0)
1834 return ret;
1835
6bf22e18
S
1836 rt->out_pkt.extra = rt->main_channel_id;
1837 rt->flv_data = rt->out_pkt.data;
1838
1839 if (pkttype == RTMP_PT_NOTIFY)
1840 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
1841 }
1842
1843 if (rt->flv_size - rt->flv_off > size_temp) {
1844 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
1845 rt->flv_off += size_temp;
a14c7842 1846 size_temp = 0;
6bf22e18
S
1847 } else {
1848 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
a14c7842 1849 size_temp -= rt->flv_size - rt->flv_off;
6bf22e18
S
1850 rt->flv_off += rt->flv_size - rt->flv_off;
1851 }
1852
1853 if (rt->flv_off == rt->flv_size) {
b14629e5
MS
1854 rt->skip_bytes = 4;
1855
f89584ca 1856 if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
bba287fd 1857 return ret;
6bf22e18
S
1858 rt->flv_size = 0;
1859 rt->flv_off = 0;
b14629e5 1860 rt->flv_header_bytes = 0;
46743a85 1861 rt->flv_nb_packets++;
6bf22e18 1862 }
a14c7842 1863 } while (buf_temp - buf < size);
7dc747f5 1864
46743a85
SP
1865 if (rt->flv_nb_packets < rt->flush_interval)
1866 return size;
1867 rt->flv_nb_packets = 0;
1868
7dc747f5
SP
1869 /* set stream into nonblocking mode */
1870 rt->stream->flags |= AVIO_FLAG_NONBLOCK;
1871
1872 /* try to read one byte from the stream */
1873 ret = ffurl_read(rt->stream, &c, 1);
1874
1875 /* switch the stream back into blocking mode */
1876 rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
1877
1878 if (ret == AVERROR(EAGAIN)) {
1879 /* no incoming data to handle */
1880 return size;
1881 } else if (ret < 0) {
1882 return ret;
1883 } else if (ret == 1) {
1884 RTMPPacket rpkt = { 0 };
1885
1886 if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
f5ce90f2 1887 rt->in_chunk_size,
7dc747f5
SP
1888 rt->prev_pkt[0], c)) <= 0)
1889 return ret;
1890
1891 if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
1892 return ret;
1893
1894 ff_rtmp_packet_destroy(&rpkt);
1895 }
1896
6bf22e18 1897 return size;
9fd6b843
KS
1898}
1899
6465562e
SP
1900#define OFFSET(x) offsetof(RTMPContext, x)
1901#define DEC AV_OPT_FLAG_DECODING_PARAM
1902#define ENC AV_OPT_FLAG_ENCODING_PARAM
1903
1904static const AVOption rtmp_options[] = {
1905 {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
8517e9c4 1906 {"rtmp_buffer", "Set buffer time in milliseconds. The default is 3000.", OFFSET(client_buffer_time), AV_OPT_TYPE_INT, {3000}, 0, INT_MAX, DEC|ENC},
8ee3e187 1907 {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
e64673e4 1908 {"rtmp_flashver", "Version of the Flash plugin used to run the SWF player.", OFFSET(flashver), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
46743a85 1909 {"rtmp_flush_interval", "Number of packets flushed in the same request (RTMPT only).", OFFSET(flush_interval), AV_OPT_TYPE_INT, {10}, 0, INT_MAX, ENC},
b2e495af
SP
1910 {"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {-2}, INT_MIN, INT_MAX, DEC, "rtmp_live"},
1911 {"any", "both", 0, AV_OPT_TYPE_CONST, {-2}, 0, 0, DEC, "rtmp_live"},
1912 {"live", "live stream", 0, AV_OPT_TYPE_CONST, {-1}, 0, 0, DEC, "rtmp_live"},
1913 {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {0}, 0, 0, DEC, "rtmp_live"},
758377a2 1914 {"rtmp_pageurl", "URL of the web page in which the media was embedded. By default no value will be sent.", OFFSET(pageurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
b3b17512 1915 {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
00cb52c6 1916 {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
635ac8e1
SP
1917 {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
1918 {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {0}, 0, INT_MAX, DEC},
05945db9 1919 {"rtmp_swfurl", "URL of the SWF player. By default no value will be sent", OFFSET(swfurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
93f257db 1920 {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
63ffa154 1921 {"rtmp_tcurl", "URL of the target stream. Defaults to proto://host[:port]/app.", OFFSET(tcurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
6465562e
SP
1922 { NULL },
1923};
1924
12127b65
SP
1925#define RTMP_PROTOCOL(flavor) \
1926static const AVClass flavor##_class = { \
1927 .class_name = #flavor, \
1928 .item_name = av_default_item_name, \
1929 .option = rtmp_options, \
1930 .version = LIBAVUTIL_VERSION_INT, \
1931}; \
1932 \
1933URLProtocol ff_##flavor##_protocol = { \
1934 .name = #flavor, \
1935 .url_open = rtmp_open, \
1936 .url_read = rtmp_read, \
1937 .url_write = rtmp_write, \
1938 .url_close = rtmp_close, \
1939 .priv_data_size = sizeof(RTMPContext), \
1940 .flags = URL_PROTOCOL_FLAG_NETWORK, \
1941 .priv_data_class= &flavor##_class, \
6465562e
SP
1942};
1943
08cd95e8 1944
12127b65
SP
1945RTMP_PROTOCOL(rtmp)
1946RTMP_PROTOCOL(rtmpe)
1947RTMP_PROTOCOL(rtmps)
1948RTMP_PROTOCOL(rtmpt)
1949RTMP_PROTOCOL(rtmpte)
1950RTMP_PROTOCOL(rtmpts)