FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/rtmpproto.c
Date: 2025-07-28 20:30:09
Exec Total Coverage
Lines: 0 1598 0.0%
Functions: 0 62 0.0%
Branches: 0 888 0.0%

Line Branch Exec Source
1 /*
2 * RTMP network protocol
3 * Copyright (c) 2009 Konstantin Shishkov
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
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 *
12 * FFmpeg is distributed in the hope that it will be useful,
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
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 /**
23 * @file
24 * RTMP protocol
25 */
26
27 #include "config_components.h"
28
29 #include "libavcodec/bytestream.h"
30 #include "libavutil/avstring.h"
31 #include "libavutil/base64.h"
32 #include "libavutil/intfloat.h"
33 #include "libavutil/lfg.h"
34 #include "libavutil/md5.h"
35 #include "libavutil/mem.h"
36 #include "libavutil/opt.h"
37 #include "libavutil/random_seed.h"
38 #include "avformat.h"
39 #include "internal.h"
40
41 #include "network.h"
42
43 #include "flv.h"
44 #include "rtmp.h"
45 #include "rtmpcrypt.h"
46 #include "rtmppkt.h"
47 #include "url.h"
48 #include "version.h"
49
50 #if CONFIG_ZLIB
51 #include <zlib.h>
52 #endif
53
54 #define APP_MAX_LENGTH 1024
55 #define TCURL_MAX_LENGTH 1024
56 #define FLASHVER_MAX_LENGTH 64
57 #define RTMP_PKTDATA_DEFAULT_SIZE 4096
58 #define RTMP_HEADER 11
59
60 /** RTMP protocol handler state */
61 typedef enum {
62 STATE_START, ///< client has not done anything yet
63 STATE_HANDSHAKED, ///< client has performed handshake
64 STATE_FCPUBLISH, ///< client FCPublishing stream (for output)
65 STATE_PLAYING, ///< client has started receiving multimedia data from server
66 STATE_SEEKING, ///< client has started the seek operation. Back on STATE_PLAYING when the time comes
67 STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
68 STATE_RECEIVING, ///< received a publish command (for input)
69 STATE_SENDING, ///< received a play command (for output)
70 STATE_STOPPED, ///< the broadcast has been stopped
71 } ClientState;
72
73 typedef struct TrackedMethod {
74 char *name;
75 int id;
76 } TrackedMethod;
77
78 /** protocol handler context */
79 typedef struct RTMPContext {
80 const AVClass *class;
81 URLContext* stream; ///< TCP stream used in interactions with RTMP server
82 RTMPPacket *prev_pkt[2]; ///< packet history used when reading and sending packets ([0] for reading, [1] for writing)
83 int nb_prev_pkt[2]; ///< number of elements in prev_pkt
84 int in_chunk_size; ///< size of the chunks incoming RTMP packets are divided into
85 int out_chunk_size; ///< size of the chunks outgoing RTMP packets are divided into
86 int is_input; ///< input/output flag
87 char *playpath; ///< stream identifier to play (with possible "mp4:" prefix)
88 int live; ///< 0: recorded, -1: live, -2: both
89 char *app; ///< name of application
90 char *conn; ///< append arbitrary AMF data to the Connect message
91 ClientState state; ///< current state
92 int stream_id; ///< ID assigned by the server for the stream
93 uint8_t* flv_data; ///< buffer with data for demuxer
94 int flv_size; ///< current buffer size
95 int flv_off; ///< number of bytes read from current buffer
96 int flv_nb_packets; ///< number of flv packets published
97 RTMPPacket out_pkt; ///< rtmp packet, created from flv a/v or metadata (for output)
98 uint32_t receive_report_size; ///< number of bytes after which we should report the number of received bytes to the peer
99 uint64_t bytes_read; ///< number of bytes read from server
100 uint64_t last_bytes_read; ///< number of bytes read last reported to server
101 uint32_t last_timestamp; ///< last timestamp received in a packet
102 int skip_bytes; ///< number of bytes to skip from the input FLV stream in the next write call
103 int has_audio; ///< presence of audio data
104 int has_video; ///< presence of video data
105 int received_metadata; ///< Indicates if we have received metadata about the streams
106 uint8_t flv_header[RTMP_HEADER]; ///< partial incoming flv packet header
107 int flv_header_bytes; ///< number of initialized bytes in flv_header
108 int nb_invokes; ///< keeps track of invoke messages
109 char* tcurl; ///< url of the target stream
110 char* flashver; ///< version of the flash plugin
111 char* swfhash; ///< SHA256 hash of the decompressed SWF file (32 bytes)
112 int swfhash_len; ///< length of the SHA256 hash
113 int swfsize; ///< size of the decompressed SWF file
114 char* swfurl; ///< url of the swf player
115 char* swfverify; ///< URL to player swf file, compute hash/size automatically
116 char swfverification[42]; ///< hash of the SWF verification
117 char* pageurl; ///< url of the web page
118 char* subscribe; ///< name of live stream to subscribe
119 int max_sent_unacked; ///< max unacked sent bytes
120 int client_buffer_time; ///< client buffer time in ms
121 int flush_interval; ///< number of packets flushed in the same request (RTMPT only)
122 int encrypted; ///< use an encrypted connection (RTMPE only)
123 TrackedMethod*tracked_methods; ///< tracked methods buffer
124 int nb_tracked_methods; ///< number of tracked methods
125 int tracked_methods_size; ///< size of the tracked methods buffer
126 int listen; ///< listen mode flag
127 int listen_timeout; ///< listen timeout to wait for new connections
128 int nb_streamid; ///< The next stream id to return on createStream calls
129 double duration; ///< Duration of the stream in seconds as returned by the server (only valid if non-zero)
130 int tcp_nodelay; ///< Use TCP_NODELAY to disable Nagle's algorithm if set to 1
131 char *enhanced_codecs; ///< codec list in enhanced rtmp
132 char username[50];
133 char password[50];
134 char auth_params[500];
135 int do_reconnect;
136 int auth_tried;
137 } RTMPContext;
138
139 #define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing
140 /** Client key used for digest signing */
141 static const uint8_t rtmp_player_key[] = {
142 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
143 'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
144
145 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
146 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
147 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
148 };
149
150 #define SERVER_KEY_OPEN_PART_LEN 36 ///< length of partial key used for first server digest signing
151 /** Key used for RTMP server digest signing */
152 static const uint8_t rtmp_server_key[] = {
153 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
154 'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
155 'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
156
157 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
158 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
159 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
160 };
161
162 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt);
163 static int handle_window_ack_size(URLContext *s, RTMPPacket *pkt);
164 static int handle_set_peer_bw(URLContext *s, RTMPPacket *pkt);
165
166 static int add_tracked_method(RTMPContext *rt, const char *name, int id)
167 {
168 int err;
169
170 if (rt->nb_tracked_methods + 1 > rt->tracked_methods_size) {
171 rt->tracked_methods_size = (rt->nb_tracked_methods + 1) * 2;
172 if ((err = av_reallocp_array(&rt->tracked_methods, rt->tracked_methods_size,
173 sizeof(*rt->tracked_methods))) < 0) {
174 rt->nb_tracked_methods = 0;
175 rt->tracked_methods_size = 0;
176 return err;
177 }
178 }
179
180 rt->tracked_methods[rt->nb_tracked_methods].name = av_strdup(name);
181 if (!rt->tracked_methods[rt->nb_tracked_methods].name)
182 return AVERROR(ENOMEM);
183 rt->tracked_methods[rt->nb_tracked_methods].id = id;
184 rt->nb_tracked_methods++;
185
186 return 0;
187 }
188
189 static void del_tracked_method(RTMPContext *rt, int index)
190 {
191 memmove(&rt->tracked_methods[index], &rt->tracked_methods[index + 1],
192 sizeof(*rt->tracked_methods) * (rt->nb_tracked_methods - index - 1));
193 rt->nb_tracked_methods--;
194 }
195
196 static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset,
197 char **tracked_method)
198 {
199 RTMPContext *rt = s->priv_data;
200 GetByteContext gbc;
201 double pkt_id;
202 int ret;
203 int i;
204
205 bytestream2_init(&gbc, pkt->data + offset, pkt->size - offset);
206 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
207 return ret;
208
209 for (i = 0; i < rt->nb_tracked_methods; i++) {
210 if (rt->tracked_methods[i].id != pkt_id)
211 continue;
212
213 *tracked_method = rt->tracked_methods[i].name;
214 del_tracked_method(rt, i);
215 break;
216 }
217
218 return 0;
219 }
220
221 static void free_tracked_methods(RTMPContext *rt)
222 {
223 int i;
224
225 for (i = 0; i < rt->nb_tracked_methods; i ++)
226 av_freep(&rt->tracked_methods[i].name);
227 av_freep(&rt->tracked_methods);
228 rt->tracked_methods_size = 0;
229 rt->nb_tracked_methods = 0;
230 }
231
232 static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
233 {
234 int ret;
235
236 if (pkt->type == RTMP_PT_INVOKE && track) {
237 GetByteContext gbc;
238 char name[128];
239 double pkt_id;
240 int len;
241
242 bytestream2_init(&gbc, pkt->data, pkt->size);
243 if ((ret = ff_amf_read_string(&gbc, name, sizeof(name), &len)) < 0)
244 goto fail;
245
246 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
247 goto fail;
248
249 if ((ret = add_tracked_method(rt, name, pkt_id)) < 0)
250 goto fail;
251 }
252
253 ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
254 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
255 fail:
256 ff_rtmp_packet_destroy(pkt);
257 return ret;
258 }
259
260 static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
261 {
262 char *field, *value;
263 char type;
264
265 /* The type must be B for Boolean, N for number, S for string, O for
266 * object, or Z for null. For Booleans the data must be either 0 or 1 for
267 * FALSE or TRUE, respectively. Likewise for Objects the data must be
268 * 0 or 1 to end or begin an object, respectively. Data items in subobjects
269 * may be named, by prefixing the type with 'N' and specifying the name
270 * before the value (ie. NB:myFlag:1). This option may be used multiple times
271 * to construct arbitrary AMF sequences. */
272 if (param[0] && param[1] == ':') {
273 type = param[0];
274 value = param + 2;
275 } else if (param[0] == 'N' && param[1] && param[2] == ':') {
276 type = param[1];
277 field = param + 3;
278 value = strchr(field, ':');
279 if (!value)
280 goto fail;
281 *value = '\0';
282 value++;
283
284 ff_amf_write_field_name(p, field);
285 } else {
286 goto fail;
287 }
288
289 switch (type) {
290 case 'B':
291 ff_amf_write_bool(p, value[0] != '0');
292 break;
293 case 'S':
294 ff_amf_write_string(p, value);
295 break;
296 case 'N':
297 ff_amf_write_number(p, strtod(value, NULL));
298 break;
299 case 'Z':
300 ff_amf_write_null(p);
301 break;
302 case 'O':
303 if (value[0] != '0')
304 ff_amf_write_object_start(p);
305 else
306 ff_amf_write_object_end(p);
307 break;
308 default:
309 goto fail;
310 break;
311 }
312
313 return 0;
314
315 fail:
316 av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
317 return AVERROR(EINVAL);
318 }
319
320 /**
321 * Generate 'connect' call and send it to the server.
322 */
323 static int gen_connect(URLContext *s, RTMPContext *rt)
324 {
325 RTMPPacket pkt;
326 uint8_t *p;
327 int ret;
328
329 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
330 0, 4096 + APP_MAX_LENGTH)) < 0)
331 return ret;
332
333 p = pkt.data;
334
335 ff_amf_write_string(&p, "connect");
336 ff_amf_write_number(&p, ++rt->nb_invokes);
337 ff_amf_write_object_start(&p);
338 ff_amf_write_field_name(&p, "app");
339 ff_amf_write_string2(&p, rt->app, rt->auth_params);
340
341 if (rt->enhanced_codecs) {
342 uint32_t list_len = 0;
343 char *fourcc_data = rt->enhanced_codecs;
344 int fourcc_str_len = strlen(fourcc_data);
345
346 // check the string, fourcc + ',' + ... + end fourcc correct length should be (4+1)*n+4
347 if ((fourcc_str_len + 1) % 5 != 0) {
348 av_log(s, AV_LOG_ERROR, "Malformed rtmp_enhanched_codecs, "
349 "should be of the form hvc1[,av01][,vp09][,...]\n");
350 ff_rtmp_packet_destroy(&pkt);
351 return AVERROR(EINVAL);
352 }
353
354 list_len = (fourcc_str_len + 1) / 5;
355 ff_amf_write_field_name(&p, "fourCcList");
356 ff_amf_write_array_start(&p, list_len);
357
358 while(fourcc_data - rt->enhanced_codecs < fourcc_str_len) {
359 unsigned char fourcc[5];
360 if (!strncmp(fourcc_data, "ac-3", 4) ||
361 !strncmp(fourcc_data, "av01", 4) ||
362 !strncmp(fourcc_data, "avc1", 4) ||
363 !strncmp(fourcc_data, "ec-3", 4) ||
364 !strncmp(fourcc_data, "fLaC", 4) ||
365 !strncmp(fourcc_data, "hvc1", 4) ||
366 !strncmp(fourcc_data, ".mp3", 4) ||
367 !strncmp(fourcc_data, "mp4a", 4) ||
368 !strncmp(fourcc_data, "Opus", 4) ||
369 !strncmp(fourcc_data, "vp09", 4)) {
370 av_strlcpy(fourcc, fourcc_data, sizeof(fourcc));
371 ff_amf_write_string(&p, fourcc);
372 } else {
373 av_log(s, AV_LOG_ERROR, "Unsupported codec fourcc, %.*s\n", 4, fourcc_data);
374 ff_rtmp_packet_destroy(&pkt);
375 return AVERROR_PATCHWELCOME;
376 }
377
378 fourcc_data += 5;
379 }
380 }
381
382 if (!rt->is_input) {
383 ff_amf_write_field_name(&p, "type");
384 ff_amf_write_string(&p, "nonprivate");
385 }
386 ff_amf_write_field_name(&p, "flashVer");
387 ff_amf_write_string(&p, rt->flashver);
388
389 if (rt->swfurl || rt->swfverify) {
390 ff_amf_write_field_name(&p, "swfUrl");
391 if (rt->swfurl)
392 ff_amf_write_string(&p, rt->swfurl);
393 else
394 ff_amf_write_string(&p, rt->swfverify);
395 }
396
397 ff_amf_write_field_name(&p, "tcUrl");
398 ff_amf_write_string2(&p, rt->tcurl, rt->auth_params);
399 if (rt->is_input) {
400 ff_amf_write_field_name(&p, "fpad");
401 ff_amf_write_bool(&p, 0);
402 ff_amf_write_field_name(&p, "capabilities");
403 ff_amf_write_number(&p, 15.0);
404
405 /* Tell the server we support all the audio codecs except
406 * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
407 * which are unused in the RTMP protocol implementation. */
408 ff_amf_write_field_name(&p, "audioCodecs");
409 ff_amf_write_number(&p, 4071.0);
410 ff_amf_write_field_name(&p, "videoCodecs");
411 ff_amf_write_number(&p, 252.0);
412 ff_amf_write_field_name(&p, "videoFunction");
413 ff_amf_write_number(&p, 1.0);
414
415 if (rt->pageurl) {
416 ff_amf_write_field_name(&p, "pageUrl");
417 ff_amf_write_string(&p, rt->pageurl);
418 }
419 }
420 ff_amf_write_object_end(&p);
421
422 if (rt->conn) {
423 char *param = rt->conn;
424
425 // Write arbitrary AMF data to the Connect message.
426 while (param) {
427 char *sep;
428 param += strspn(param, " ");
429 if (!*param)
430 break;
431 sep = strchr(param, ' ');
432 if (sep)
433 *sep = '\0';
434 if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
435 // Invalid AMF parameter.
436 ff_rtmp_packet_destroy(&pkt);
437 return ret;
438 }
439
440 if (sep)
441 param = sep + 1;
442 else
443 break;
444 }
445 }
446
447 pkt.size = p - pkt.data;
448
449 return rtmp_send_packet(rt, &pkt, 1);
450 }
451
452
453 #define RTMP_CTRL_ABORT_MESSAGE (2)
454
455 static int read_connect(URLContext *s, RTMPContext *rt)
456 {
457 RTMPPacket pkt = { 0 };
458 uint8_t *p;
459 const uint8_t *cp;
460 int ret;
461 char command[64];
462 int stringlen;
463 double seqnum;
464 uint8_t tmpstr[256];
465 GetByteContext gbc;
466
467 // handle RTMP Protocol Control Messages
468 for (;;) {
469 if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
470 &rt->prev_pkt[0], &rt->nb_prev_pkt[0])) < 0)
471 return ret;
472 #ifdef DEBUG
473 ff_rtmp_packet_dump(s, &pkt);
474 #endif
475 if (pkt.type == RTMP_PT_CHUNK_SIZE) {
476 if ((ret = handle_chunk_size(s, &pkt)) < 0) {
477 ff_rtmp_packet_destroy(&pkt);
478 return ret;
479 }
480 } else if (pkt.type == RTMP_CTRL_ABORT_MESSAGE) {
481 av_log(s, AV_LOG_ERROR, "received abort message\n");
482 ff_rtmp_packet_destroy(&pkt);
483 return AVERROR_UNKNOWN;
484 } else if (pkt.type == RTMP_PT_BYTES_READ) {
485 av_log(s, AV_LOG_TRACE, "received acknowledgement\n");
486 } else if (pkt.type == RTMP_PT_WINDOW_ACK_SIZE) {
487 if ((ret = handle_window_ack_size(s, &pkt)) < 0) {
488 ff_rtmp_packet_destroy(&pkt);
489 return ret;
490 }
491 } else if (pkt.type == RTMP_PT_SET_PEER_BW) {
492 if ((ret = handle_set_peer_bw(s, &pkt)) < 0) {
493 ff_rtmp_packet_destroy(&pkt);
494 return ret;
495 }
496 } else if (pkt.type == RTMP_PT_INVOKE) {
497 // received RTMP Command Message
498 break;
499 } else {
500 av_log(s, AV_LOG_ERROR, "Unknown control message type (%d)\n", pkt.type);
501 }
502 ff_rtmp_packet_destroy(&pkt);
503 }
504
505 cp = pkt.data;
506 bytestream2_init(&gbc, cp, pkt.size);
507 if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) {
508 av_log(s, AV_LOG_ERROR, "Unable to read command string\n");
509 ff_rtmp_packet_destroy(&pkt);
510 return AVERROR_INVALIDDATA;
511 }
512 if (strcmp(command, "connect")) {
513 av_log(s, AV_LOG_ERROR, "Expecting connect, got %s\n", command);
514 ff_rtmp_packet_destroy(&pkt);
515 return AVERROR_INVALIDDATA;
516 }
517 ret = ff_amf_read_number(&gbc, &seqnum);
518 if (ret)
519 av_log(s, AV_LOG_WARNING, "SeqNum not found\n");
520 /* Here one could parse an AMF Object with data as flashVers and others. */
521 ret = ff_amf_get_field_value(gbc.buffer,
522 gbc.buffer + bytestream2_get_bytes_left(&gbc),
523 "app", tmpstr, sizeof(tmpstr));
524 if (ret)
525 av_log(s, AV_LOG_WARNING, "App field not found in connect\n");
526 if (!ret && strcmp(tmpstr, rt->app))
527 av_log(s, AV_LOG_WARNING, "App field don't match up: %s <-> %s\n",
528 tmpstr, rt->app);
529 ff_rtmp_packet_destroy(&pkt);
530
531 // Send Window Acknowledgement Size (as defined in specification)
532 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
533 RTMP_PT_WINDOW_ACK_SIZE, 0, 4)) < 0)
534 return ret;
535 p = pkt.data;
536 // Inform the peer about how often we want acknowledgements about what
537 // we send. (We don't check for the acknowledgements currently.)
538 bytestream_put_be32(&p, rt->max_sent_unacked);
539 pkt.size = p - pkt.data;
540 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
541 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
542 ff_rtmp_packet_destroy(&pkt);
543 if (ret < 0)
544 return ret;
545 // Set Peer Bandwidth
546 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
547 RTMP_PT_SET_PEER_BW, 0, 5)) < 0)
548 return ret;
549 p = pkt.data;
550 // Tell the peer to only send this many bytes unless it gets acknowledgements.
551 // This could be any arbitrary value we want here.
552 bytestream_put_be32(&p, rt->max_sent_unacked);
553 bytestream_put_byte(&p, 2); // dynamic
554 pkt.size = p - pkt.data;
555 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
556 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
557 ff_rtmp_packet_destroy(&pkt);
558 if (ret < 0)
559 return ret;
560
561 // User control
562 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
563 RTMP_PT_USER_CONTROL, 0, 6)) < 0)
564 return ret;
565
566 p = pkt.data;
567 bytestream_put_be16(&p, 0); // 0 -> Stream Begin
568 bytestream_put_be32(&p, 0); // Stream 0
569 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
570 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
571 ff_rtmp_packet_destroy(&pkt);
572 if (ret < 0)
573 return ret;
574
575 // Chunk size
576 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
577 RTMP_PT_CHUNK_SIZE, 0, 4)) < 0)
578 return ret;
579
580 p = pkt.data;
581 bytestream_put_be32(&p, rt->out_chunk_size);
582 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
583 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
584 ff_rtmp_packet_destroy(&pkt);
585 if (ret < 0)
586 return ret;
587
588 // Send _result NetConnection.Connect.Success to connect
589 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
590 RTMP_PT_INVOKE, 0,
591 RTMP_PKTDATA_DEFAULT_SIZE)) < 0)
592 return ret;
593
594 p = pkt.data;
595 ff_amf_write_string(&p, "_result");
596 ff_amf_write_number(&p, seqnum);
597
598 ff_amf_write_object_start(&p);
599 ff_amf_write_field_name(&p, "fmsVer");
600 ff_amf_write_string(&p, "FMS/3,0,1,123");
601 ff_amf_write_field_name(&p, "capabilities");
602 ff_amf_write_number(&p, 31);
603 ff_amf_write_object_end(&p);
604
605 ff_amf_write_object_start(&p);
606 ff_amf_write_field_name(&p, "level");
607 ff_amf_write_string(&p, "status");
608 ff_amf_write_field_name(&p, "code");
609 ff_amf_write_string(&p, "NetConnection.Connect.Success");
610 ff_amf_write_field_name(&p, "description");
611 ff_amf_write_string(&p, "Connection succeeded.");
612 ff_amf_write_field_name(&p, "objectEncoding");
613 ff_amf_write_number(&p, 0);
614 ff_amf_write_object_end(&p);
615
616 pkt.size = p - pkt.data;
617 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
618 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
619 ff_rtmp_packet_destroy(&pkt);
620 if (ret < 0)
621 return ret;
622
623 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
624 RTMP_PT_INVOKE, 0, 30)) < 0)
625 return ret;
626 p = pkt.data;
627 ff_amf_write_string(&p, "onBWDone");
628 ff_amf_write_number(&p, 0);
629 ff_amf_write_null(&p);
630 ff_amf_write_number(&p, 8192);
631 pkt.size = p - pkt.data;
632 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
633 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
634 ff_rtmp_packet_destroy(&pkt);
635
636 return ret;
637 }
638
639 /**
640 * Generate 'releaseStream' call and send it to the server. It should make
641 * the server release some channel for media streams.
642 */
643 static int gen_release_stream(URLContext *s, RTMPContext *rt)
644 {
645 RTMPPacket pkt;
646 uint8_t *p;
647 int ret;
648
649 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
650 0, 29 + strlen(rt->playpath))) < 0)
651 return ret;
652
653 av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
654 p = pkt.data;
655 ff_amf_write_string(&p, "releaseStream");
656 ff_amf_write_number(&p, ++rt->nb_invokes);
657 ff_amf_write_null(&p);
658 ff_amf_write_string(&p, rt->playpath);
659
660 return rtmp_send_packet(rt, &pkt, 1);
661 }
662
663 /**
664 * Generate 'FCPublish' call and send it to the server. It should make
665 * the server prepare for receiving media streams.
666 */
667 static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
668 {
669 RTMPPacket pkt;
670 uint8_t *p;
671 int ret;
672
673 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
674 0, 25 + strlen(rt->playpath))) < 0)
675 return ret;
676
677 av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
678 p = pkt.data;
679 ff_amf_write_string(&p, "FCPublish");
680 ff_amf_write_number(&p, ++rt->nb_invokes);
681 ff_amf_write_null(&p);
682 ff_amf_write_string(&p, rt->playpath);
683
684 return rtmp_send_packet(rt, &pkt, 1);
685 }
686
687 /**
688 * Generate 'FCUnpublish' call and send it to the server. It should make
689 * the server destroy stream.
690 */
691 static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
692 {
693 RTMPPacket pkt;
694 uint8_t *p;
695 int ret;
696
697 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
698 0, 27 + strlen(rt->playpath))) < 0)
699 return ret;
700
701 av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
702 p = pkt.data;
703 ff_amf_write_string(&p, "FCUnpublish");
704 ff_amf_write_number(&p, ++rt->nb_invokes);
705 ff_amf_write_null(&p);
706 ff_amf_write_string(&p, rt->playpath);
707
708 return rtmp_send_packet(rt, &pkt, 0);
709 }
710
711 /**
712 * Generate 'createStream' call and send it to the server. It should make
713 * the server allocate some channel for media streams.
714 */
715 static int gen_create_stream(URLContext *s, RTMPContext *rt)
716 {
717 RTMPPacket pkt;
718 uint8_t *p;
719 int ret;
720
721 av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
722
723 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
724 0, 25)) < 0)
725 return ret;
726
727 p = pkt.data;
728 ff_amf_write_string(&p, "createStream");
729 ff_amf_write_number(&p, ++rt->nb_invokes);
730 ff_amf_write_null(&p);
731
732 return rtmp_send_packet(rt, &pkt, 1);
733 }
734
735
736 /**
737 * Generate 'deleteStream' call and send it to the server. It should make
738 * the server remove some channel for media streams.
739 */
740 static int gen_delete_stream(URLContext *s, RTMPContext *rt)
741 {
742 RTMPPacket pkt;
743 uint8_t *p;
744 int ret;
745
746 av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
747
748 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
749 0, 34)) < 0)
750 return ret;
751
752 p = pkt.data;
753 ff_amf_write_string(&p, "deleteStream");
754 ff_amf_write_number(&p, ++rt->nb_invokes);
755 ff_amf_write_null(&p);
756 ff_amf_write_number(&p, rt->stream_id);
757
758 return rtmp_send_packet(rt, &pkt, 0);
759 }
760
761 /**
762 * Generate 'getStreamLength' call and send it to the server. If the server
763 * knows the duration of the selected stream, it will reply with the duration
764 * in seconds.
765 */
766 static int gen_get_stream_length(URLContext *s, RTMPContext *rt)
767 {
768 RTMPPacket pkt;
769 uint8_t *p;
770 int ret;
771
772 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
773 0, 31 + strlen(rt->playpath))) < 0)
774 return ret;
775
776 p = pkt.data;
777 ff_amf_write_string(&p, "getStreamLength");
778 ff_amf_write_number(&p, ++rt->nb_invokes);
779 ff_amf_write_null(&p);
780 ff_amf_write_string(&p, rt->playpath);
781
782 return rtmp_send_packet(rt, &pkt, 1);
783 }
784
785 /**
786 * Generate client buffer time and send it to the server.
787 */
788 static int gen_buffer_time(URLContext *s, RTMPContext *rt)
789 {
790 RTMPPacket pkt;
791 uint8_t *p;
792 int ret;
793
794 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_USER_CONTROL,
795 1, 10)) < 0)
796 return ret;
797
798 p = pkt.data;
799 bytestream_put_be16(&p, 3); // SetBuffer Length
800 bytestream_put_be32(&p, rt->stream_id);
801 bytestream_put_be32(&p, rt->client_buffer_time);
802
803 return rtmp_send_packet(rt, &pkt, 0);
804 }
805
806 /**
807 * Generate 'play' call and send it to the server, then ping the server
808 * to start actual playing.
809 */
810 static int gen_play(URLContext *s, RTMPContext *rt)
811 {
812 RTMPPacket pkt;
813 uint8_t *p;
814 int ret;
815
816 av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
817
818 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
819 0, 29 + strlen(rt->playpath))) < 0)
820 return ret;
821
822 pkt.extra = rt->stream_id;
823
824 p = pkt.data;
825 ff_amf_write_string(&p, "play");
826 ff_amf_write_number(&p, ++rt->nb_invokes);
827 ff_amf_write_null(&p);
828 ff_amf_write_string(&p, rt->playpath);
829 ff_amf_write_number(&p, rt->live * 1000);
830
831 return rtmp_send_packet(rt, &pkt, 1);
832 }
833
834 static int gen_seek(URLContext *s, RTMPContext *rt, int64_t timestamp)
835 {
836 RTMPPacket pkt;
837 uint8_t *p;
838 int ret;
839
840 av_log(s, AV_LOG_DEBUG, "Sending seek command for timestamp %"PRId64"\n",
841 timestamp);
842
843 if ((ret = ff_rtmp_packet_create(&pkt, 3, RTMP_PT_INVOKE, 0, 26)) < 0)
844 return ret;
845
846 pkt.extra = rt->stream_id;
847
848 p = pkt.data;
849 ff_amf_write_string(&p, "seek");
850 ff_amf_write_number(&p, 0); //no tracking back responses
851 ff_amf_write_null(&p); //as usual, the first null param
852 ff_amf_write_number(&p, timestamp); //where we want to jump
853
854 return rtmp_send_packet(rt, &pkt, 1);
855 }
856
857 /**
858 * Generate a pause packet that either pauses or unpauses the current stream.
859 */
860 static int gen_pause(URLContext *s, RTMPContext *rt, int pause, uint32_t timestamp)
861 {
862 RTMPPacket pkt;
863 uint8_t *p;
864 int ret;
865
866 av_log(s, AV_LOG_DEBUG, "Sending pause command for timestamp %d\n",
867 timestamp);
868
869 if ((ret = ff_rtmp_packet_create(&pkt, 3, RTMP_PT_INVOKE, 0, 29)) < 0)
870 return ret;
871
872 pkt.extra = rt->stream_id;
873
874 p = pkt.data;
875 ff_amf_write_string(&p, "pause");
876 ff_amf_write_number(&p, 0); //no tracking back responses
877 ff_amf_write_null(&p); //as usual, the first null param
878 ff_amf_write_bool(&p, pause); // pause or unpause
879 ff_amf_write_number(&p, timestamp); //where we pause the stream
880
881 return rtmp_send_packet(rt, &pkt, 1);
882 }
883
884 /**
885 * Generate 'publish' call and send it to the server.
886 */
887 static int gen_publish(URLContext *s, RTMPContext *rt)
888 {
889 RTMPPacket pkt;
890 uint8_t *p;
891 int ret;
892
893 av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
894
895 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
896 0, 30 + strlen(rt->playpath))) < 0)
897 return ret;
898
899 pkt.extra = rt->stream_id;
900
901 p = pkt.data;
902 ff_amf_write_string(&p, "publish");
903 ff_amf_write_number(&p, ++rt->nb_invokes);
904 ff_amf_write_null(&p);
905 ff_amf_write_string(&p, rt->playpath);
906 ff_amf_write_string(&p, "live");
907
908 return rtmp_send_packet(rt, &pkt, 1);
909 }
910
911 /**
912 * Generate ping reply and send it to the server.
913 */
914 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
915 {
916 RTMPPacket pkt;
917 uint8_t *p;
918 int ret;
919
920 if (ppkt->size < 6) {
921 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
922 ppkt->size);
923 return AVERROR_INVALIDDATA;
924 }
925
926 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,RTMP_PT_USER_CONTROL,
927 ppkt->timestamp + 1, 6)) < 0)
928 return ret;
929
930 p = pkt.data;
931 bytestream_put_be16(&p, 7); // PingResponse
932 bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
933
934 return rtmp_send_packet(rt, &pkt, 0);
935 }
936
937 /**
938 * Generate SWF verification message and send it to the server.
939 */
940 static int gen_swf_verification(URLContext *s, RTMPContext *rt)
941 {
942 RTMPPacket pkt;
943 uint8_t *p;
944 int ret;
945
946 av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
947 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_USER_CONTROL,
948 0, 44)) < 0)
949 return ret;
950
951 p = pkt.data;
952 bytestream_put_be16(&p, 27);
953 memcpy(p, rt->swfverification, 42);
954
955 return rtmp_send_packet(rt, &pkt, 0);
956 }
957
958 /**
959 * Generate window acknowledgement size message and send it to the server.
960 */
961 static int gen_window_ack_size(URLContext *s, RTMPContext *rt)
962 {
963 RTMPPacket pkt;
964 uint8_t *p;
965 int ret;
966
967 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_WINDOW_ACK_SIZE,
968 0, 4)) < 0)
969 return ret;
970
971 p = pkt.data;
972 bytestream_put_be32(&p, rt->max_sent_unacked);
973
974 return rtmp_send_packet(rt, &pkt, 0);
975 }
976
977 /**
978 * Generate check bandwidth message and send it to the server.
979 */
980 static int gen_check_bw(URLContext *s, RTMPContext *rt)
981 {
982 RTMPPacket pkt;
983 uint8_t *p;
984 int ret;
985
986 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
987 0, 21)) < 0)
988 return ret;
989
990 p = pkt.data;
991 ff_amf_write_string(&p, "_checkbw");
992 ff_amf_write_number(&p, ++rt->nb_invokes);
993 ff_amf_write_null(&p);
994
995 return rtmp_send_packet(rt, &pkt, 1);
996 }
997
998 /**
999 * Generate report on bytes read so far and send it to the server.
1000 */
1001 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
1002 {
1003 RTMPPacket pkt;
1004 uint8_t *p;
1005 int ret;
1006
1007 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
1008 ts, 4)) < 0)
1009 return ret;
1010
1011 p = pkt.data;
1012 bytestream_put_be32(&p, rt->bytes_read);
1013
1014 return rtmp_send_packet(rt, &pkt, 0);
1015 }
1016
1017 static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
1018 const char *subscribe)
1019 {
1020 RTMPPacket pkt;
1021 uint8_t *p;
1022 int ret;
1023
1024 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
1025 0, 27 + strlen(subscribe))) < 0)
1026 return ret;
1027
1028 p = pkt.data;
1029 ff_amf_write_string(&p, "FCSubscribe");
1030 ff_amf_write_number(&p, ++rt->nb_invokes);
1031 ff_amf_write_null(&p);
1032 ff_amf_write_string(&p, subscribe);
1033
1034 return rtmp_send_packet(rt, &pkt, 1);
1035 }
1036
1037 /**
1038 * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
1039 * will be stored) into that packet.
1040 *
1041 * @param buf handshake data (1536 bytes)
1042 * @param encrypted use an encrypted connection (RTMPE)
1043 * @return offset to the digest inside input data
1044 */
1045 static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
1046 {
1047 int ret, digest_pos;
1048
1049 if (encrypted)
1050 digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
1051 else
1052 digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
1053
1054 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
1055 rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
1056 buf + digest_pos);
1057 if (ret < 0)
1058 return ret;
1059
1060 return digest_pos;
1061 }
1062
1063 /**
1064 * Verify that the received server response has the expected digest value.
1065 *
1066 * @param buf handshake data received from the server (1536 bytes)
1067 * @param off position to search digest offset from
1068 * @return 0 if digest is valid, digest position otherwise
1069 */
1070 static int rtmp_validate_digest(uint8_t *buf, int off)
1071 {
1072 uint8_t digest[32];
1073 int ret, digest_pos;
1074
1075 digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
1076
1077 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
1078 rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
1079 digest);
1080 if (ret < 0)
1081 return ret;
1082
1083 if (!memcmp(digest, buf + digest_pos, 32))
1084 return digest_pos;
1085 return 0;
1086 }
1087
1088 static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
1089 uint8_t *buf)
1090 {
1091 uint8_t *p;
1092 int ret;
1093
1094 if (rt->swfhash_len != 32) {
1095 av_log(s, AV_LOG_ERROR,
1096 "Hash of the decompressed SWF file is not 32 bytes long.\n");
1097 return AVERROR(EINVAL);
1098 }
1099
1100 p = &rt->swfverification[0];
1101 bytestream_put_byte(&p, 1);
1102 bytestream_put_byte(&p, 1);
1103 bytestream_put_be32(&p, rt->swfsize);
1104 bytestream_put_be32(&p, rt->swfsize);
1105
1106 if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
1107 return ret;
1108
1109 return 0;
1110 }
1111
1112 #if CONFIG_ZLIB
1113 static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
1114 uint8_t **out_data, int64_t *out_size)
1115 {
1116 z_stream zs = { 0 };
1117 void *ptr;
1118 int size;
1119 int ret = 0;
1120
1121 zs.avail_in = in_size;
1122 zs.next_in = in_data;
1123 ret = inflateInit(&zs);
1124 if (ret != Z_OK)
1125 return AVERROR_UNKNOWN;
1126
1127 do {
1128 uint8_t tmp_buf[16384];
1129
1130 zs.avail_out = sizeof(tmp_buf);
1131 zs.next_out = tmp_buf;
1132
1133 ret = inflate(&zs, Z_NO_FLUSH);
1134 if (ret != Z_OK && ret != Z_STREAM_END) {
1135 ret = AVERROR_UNKNOWN;
1136 goto fail;
1137 }
1138
1139 size = sizeof(tmp_buf) - zs.avail_out;
1140 if (!(ptr = av_realloc(*out_data, *out_size + size))) {
1141 ret = AVERROR(ENOMEM);
1142 goto fail;
1143 }
1144 *out_data = ptr;
1145
1146 memcpy(*out_data + *out_size, tmp_buf, size);
1147 *out_size += size;
1148 } while (zs.avail_out == 0);
1149
1150 fail:
1151 inflateEnd(&zs);
1152 return ret;
1153 }
1154 #endif
1155
1156 static int rtmp_calc_swfhash(URLContext *s)
1157 {
1158 RTMPContext *rt = s->priv_data;
1159 uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
1160 int64_t in_size;
1161 URLContext *stream = NULL;
1162 char swfhash[32];
1163 int swfsize;
1164 int ret = 0;
1165
1166 /* Get the SWF player file. */
1167 if ((ret = ffurl_open_whitelist(&stream, rt->swfverify, AVIO_FLAG_READ,
1168 &s->interrupt_callback, NULL,
1169 s->protocol_whitelist, s->protocol_blacklist, s)) < 0) {
1170 av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1171 goto fail;
1172 }
1173
1174 if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
1175 ret = AVERROR(EIO);
1176 goto fail;
1177 }
1178
1179 if (!(in_data = av_malloc(in_size))) {
1180 ret = AVERROR(ENOMEM);
1181 goto fail;
1182 }
1183
1184 if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
1185 goto fail;
1186
1187 if (in_size < 3) {
1188 ret = AVERROR_INVALIDDATA;
1189 goto fail;
1190 }
1191
1192 if (!memcmp(in_data, "CWS", 3)) {
1193 #if CONFIG_ZLIB
1194 int64_t out_size;
1195 /* Decompress the SWF player file using Zlib. */
1196 if (!(out_data = av_malloc(8))) {
1197 ret = AVERROR(ENOMEM);
1198 goto fail;
1199 }
1200 *in_data = 'F'; // magic stuff
1201 memcpy(out_data, in_data, 8);
1202 out_size = 8;
1203
1204 if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1205 &out_data, &out_size)) < 0)
1206 goto fail;
1207 swfsize = out_size;
1208 swfdata = out_data;
1209 #else
1210 av_log(s, AV_LOG_ERROR,
1211 "Zlib is required for decompressing the SWF player file.\n");
1212 ret = AVERROR(EINVAL);
1213 goto fail;
1214 #endif
1215 } else {
1216 swfsize = in_size;
1217 swfdata = in_data;
1218 }
1219
1220 /* Compute the SHA256 hash of the SWF player file. */
1221 if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
1222 "Genuine Adobe Flash Player 001", 30,
1223 swfhash)) < 0)
1224 goto fail;
1225
1226 /* Set SWFVerification parameters. */
1227 av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
1228 rt->swfsize = swfsize;
1229
1230 fail:
1231 av_freep(&in_data);
1232 av_freep(&out_data);
1233 ffurl_close(stream);
1234 return ret;
1235 }
1236
1237 /**
1238 * Perform handshake with the server by means of exchanging pseudorandom data
1239 * signed with HMAC-SHA2 digest.
1240 *
1241 * @return 0 if handshake succeeds, negative value otherwise
1242 */
1243 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
1244 {
1245 AVLFG rnd;
1246 uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
1247 3, // unencrypted data
1248 0, 0, 0, 0, // client uptime
1249 RTMP_CLIENT_VER1,
1250 RTMP_CLIENT_VER2,
1251 RTMP_CLIENT_VER3,
1252 RTMP_CLIENT_VER4,
1253 };
1254 uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1255 uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1256 int i;
1257 int server_pos, client_pos;
1258 uint8_t digest[32], signature[32];
1259 int ret;
1260 #if CONFIG_FFRTMPCRYPT_PROTOCOL
1261 int type = 0;
1262 #endif
1263
1264 av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1265
1266 av_lfg_init(&rnd, 0xDEADC0DE);
1267 // generate handshake packet - 1536 bytes of pseudorandom data
1268 for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1269 tosend[i] = av_lfg_get(&rnd) >> 24;
1270
1271 #if CONFIG_FFRTMPCRYPT_PROTOCOL
1272 if (rt->encrypted) {
1273 /* When the client wants to use RTMPE, we have to change the command
1274 * byte to 0x06 which means to use encrypted data and we have to set
1275 * the flash version to at least 9.0.115.0. */
1276 tosend[0] = 6;
1277 tosend[5] = 128;
1278 tosend[6] = 0;
1279 tosend[7] = 3;
1280 tosend[8] = 2;
1281
1282 /* Initialize the Diffie-Hellmann context and generate the public key
1283 * to send to the server. */
1284 if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1285 return ret;
1286 }
1287 #endif
1288
1289 client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1290 if (client_pos < 0)
1291 return client_pos;
1292
1293 if ((ret = ffurl_write(rt->stream, tosend,
1294 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1295 av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1296 return ret;
1297 }
1298
1299 if ((ret = ffurl_read_complete(rt->stream, serverdata,
1300 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1301 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1302 return ret;
1303 }
1304
1305 if ((ret = ffurl_read_complete(rt->stream, clientdata,
1306 RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
1307 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1308 return ret;
1309 }
1310
1311 av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1312 av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1313 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1314
1315 if (rt->is_input && serverdata[5] >= 3) {
1316 server_pos = rtmp_validate_digest(serverdata + 1, 772);
1317 if (server_pos < 0)
1318 return server_pos;
1319
1320 if (!server_pos) {
1321 #if CONFIG_FFRTMPCRYPT_PROTOCOL
1322 type = 1;
1323 #endif
1324 server_pos = rtmp_validate_digest(serverdata + 1, 8);
1325 if (server_pos < 0)
1326 return server_pos;
1327
1328 if (!server_pos) {
1329 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1330 return AVERROR(EIO);
1331 }
1332 }
1333
1334 /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1335 * key are the last 32 bytes of the server handshake. */
1336 if (rt->swfsize) {
1337 if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1338 RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1339 return ret;
1340 }
1341
1342 ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1343 rtmp_server_key, sizeof(rtmp_server_key),
1344 digest);
1345 if (ret < 0)
1346 return ret;
1347
1348 ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1349 0, digest, 32, signature);
1350 if (ret < 0)
1351 return ret;
1352
1353 #if CONFIG_FFRTMPCRYPT_PROTOCOL
1354 if (rt->encrypted) {
1355 /* Compute the shared secret key sent by the server and initialize
1356 * the RC4 encryption. */
1357 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1358 tosend + 1, type)) < 0)
1359 return ret;
1360
1361 /* Encrypt the signature received by the server. */
1362 ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1363 }
1364 #endif
1365
1366 if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1367 av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1368 return AVERROR(EIO);
1369 }
1370
1371 for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1372 tosend[i] = av_lfg_get(&rnd) >> 24;
1373 ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1374 rtmp_player_key, sizeof(rtmp_player_key),
1375 digest);
1376 if (ret < 0)
1377 return ret;
1378
1379 ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1380 digest, 32,
1381 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1382 if (ret < 0)
1383 return ret;
1384
1385 #if CONFIG_FFRTMPCRYPT_PROTOCOL
1386 if (rt->encrypted) {
1387 /* Encrypt the signature to be send to the server. */
1388 ff_rtmpe_encrypt_sig(rt->stream, tosend +
1389 RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1390 serverdata[0]);
1391 }
1392 #endif
1393
1394 // write reply back to the server
1395 if ((ret = ffurl_write(rt->stream, tosend,
1396 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1397 return ret;
1398
1399 #if CONFIG_FFRTMPCRYPT_PROTOCOL
1400 if (rt->encrypted) {
1401 /* Set RC4 keys for encryption and update the keystreams. */
1402 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1403 return ret;
1404 }
1405 #endif
1406 } else {
1407 #if CONFIG_FFRTMPCRYPT_PROTOCOL
1408 if (rt->encrypted) {
1409 /* Compute the shared secret key sent by the server and initialize
1410 * the RC4 encryption. */
1411 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1412 tosend + 1, 1)) < 0)
1413 return ret;
1414
1415 if (serverdata[0] == 9) {
1416 /* Encrypt the signature received by the server. */
1417 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1418 serverdata[0]);
1419 }
1420 }
1421 #endif
1422
1423 if ((ret = ffurl_write(rt->stream, serverdata + 1,
1424 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1425 return ret;
1426
1427 #if CONFIG_FFRTMPCRYPT_PROTOCOL
1428 if (rt->encrypted) {
1429 /* Set RC4 keys for encryption and update the keystreams. */
1430 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1431 return ret;
1432 }
1433 #endif
1434 }
1435
1436 return 0;
1437 }
1438
1439 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1440 uint32_t *second_int, char *arraydata,
1441 int size)
1442 {
1443 int inoutsize;
1444
1445 inoutsize = ffurl_read_complete(rt->stream, arraydata,
1446 RTMP_HANDSHAKE_PACKET_SIZE);
1447 if (inoutsize <= 0)
1448 return AVERROR(EIO);
1449 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1450 av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1451 " not following standard\n", (int)inoutsize);
1452 return AVERROR(EINVAL);
1453 }
1454
1455 *first_int = AV_RB32(arraydata);
1456 *second_int = AV_RB32(arraydata + 4);
1457 return 0;
1458 }
1459
1460 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1461 uint32_t second_int, char *arraydata, int size)
1462 {
1463 int inoutsize;
1464
1465 AV_WB32(arraydata, first_int);
1466 AV_WB32(arraydata + 4, second_int);
1467 inoutsize = ffurl_write(rt->stream, arraydata,
1468 RTMP_HANDSHAKE_PACKET_SIZE);
1469 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1470 av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1471 return AVERROR(EIO);
1472 }
1473
1474 return 0;
1475 }
1476
1477 /**
1478 * rtmp handshake server side
1479 */
1480 static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
1481 {
1482 uint8_t buffer[RTMP_HANDSHAKE_PACKET_SIZE];
1483 uint32_t hs_epoch;
1484 uint32_t hs_my_epoch;
1485 uint8_t hs_c1[RTMP_HANDSHAKE_PACKET_SIZE];
1486 uint8_t hs_s1[RTMP_HANDSHAKE_PACKET_SIZE];
1487 uint32_t zeroes;
1488 uint32_t temp = 0;
1489 int randomidx = 0;
1490 int inoutsize = 0;
1491 int ret;
1492
1493 inoutsize = ffurl_read_complete(rt->stream, buffer, 1); // Receive C0
1494 if (inoutsize <= 0) {
1495 av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1496 return AVERROR(EIO);
1497 }
1498 // Check Version
1499 if (buffer[0] != 3) {
1500 av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1501 return AVERROR(EIO);
1502 }
1503 if (ffurl_write(rt->stream, buffer, 1) <= 0) { // Send S0
1504 av_log(s, AV_LOG_ERROR,
1505 "Unable to write answer - RTMP S0\n");
1506 return AVERROR(EIO);
1507 }
1508 /* Receive C1 */
1509 ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1510 RTMP_HANDSHAKE_PACKET_SIZE);
1511 if (ret) {
1512 av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1513 return ret;
1514 }
1515 /* Send S1 */
1516 /* By now same epoch will be sent */
1517 hs_my_epoch = hs_epoch;
1518 /* Generate random */
1519 for (randomidx = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1520 randomidx += 4)
1521 AV_WB32(hs_s1 + randomidx, av_get_random_seed());
1522
1523 ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1524 RTMP_HANDSHAKE_PACKET_SIZE);
1525 if (ret) {
1526 av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1527 return ret;
1528 }
1529 /* Send S2 */
1530 ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1531 RTMP_HANDSHAKE_PACKET_SIZE);
1532 if (ret) {
1533 av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1534 return ret;
1535 }
1536 /* Receive C2 */
1537 ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1538 RTMP_HANDSHAKE_PACKET_SIZE);
1539 if (ret) {
1540 av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1541 return ret;
1542 }
1543 if (temp != hs_my_epoch)
1544 av_log(s, AV_LOG_WARNING,
1545 "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1546 if (memcmp(buffer + 8, hs_s1 + 8,
1547 RTMP_HANDSHAKE_PACKET_SIZE - 8))
1548 av_log(s, AV_LOG_WARNING,
1549 "Erroneous C2 Message random does not match up\n");
1550
1551 return 0;
1552 }
1553
1554 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1555 {
1556 RTMPContext *rt = s->priv_data;
1557 int ret;
1558
1559 if (pkt->size < 4) {
1560 av_log(s, AV_LOG_ERROR,
1561 "Too short chunk size change packet (%d)\n",
1562 pkt->size);
1563 return AVERROR_INVALIDDATA;
1564 }
1565
1566 if (!rt->is_input) {
1567 /* Send the same chunk size change packet back to the server,
1568 * setting the outgoing chunk size to the same as the incoming one. */
1569 if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1570 &rt->prev_pkt[1], &rt->nb_prev_pkt[1])) < 0)
1571 return ret;
1572 rt->out_chunk_size = AV_RB32(pkt->data);
1573 }
1574
1575 rt->in_chunk_size = AV_RB32(pkt->data);
1576 if (rt->in_chunk_size <= 0) {
1577 av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1578 rt->in_chunk_size);
1579 return AVERROR_INVALIDDATA;
1580 }
1581 av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1582 rt->in_chunk_size);
1583
1584 return 0;
1585 }
1586
1587 static int handle_user_control(URLContext *s, RTMPPacket *pkt)
1588 {
1589 RTMPContext *rt = s->priv_data;
1590 int t, ret;
1591
1592 if (pkt->size < 2) {
1593 av_log(s, AV_LOG_ERROR, "Too short user control packet (%d)\n",
1594 pkt->size);
1595 return AVERROR_INVALIDDATA;
1596 }
1597
1598 t = AV_RB16(pkt->data);
1599 if (t == 6) { // PingRequest
1600 if ((ret = gen_pong(s, rt, pkt)) < 0)
1601 return ret;
1602 } else if (t == 26) {
1603 if (rt->swfsize) {
1604 if ((ret = gen_swf_verification(s, rt)) < 0)
1605 return ret;
1606 } else {
1607 av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1608 }
1609 }
1610
1611 return 0;
1612 }
1613
1614 static int handle_set_peer_bw(URLContext *s, RTMPPacket *pkt)
1615 {
1616 RTMPContext *rt = s->priv_data;
1617
1618 if (pkt->size < 4) {
1619 av_log(s, AV_LOG_ERROR,
1620 "Peer bandwidth packet is less than 4 bytes long (%d)\n",
1621 pkt->size);
1622 return AVERROR_INVALIDDATA;
1623 }
1624
1625 // We currently don't check how much the peer has acknowledged of
1626 // what we have sent. To do that properly, we should call
1627 // gen_window_ack_size here, to tell the peer that we want an
1628 // acknowledgement with (at least) that interval.
1629 rt->max_sent_unacked = AV_RB32(pkt->data);
1630 if (rt->max_sent_unacked <= 0) {
1631 av_log(s, AV_LOG_ERROR, "Incorrect set peer bandwidth %d\n",
1632 rt->max_sent_unacked);
1633 return AVERROR_INVALIDDATA;
1634
1635 }
1636 av_log(s, AV_LOG_DEBUG, "Max sent, unacked = %d\n", rt->max_sent_unacked);
1637
1638 return 0;
1639 }
1640
1641 static int handle_window_ack_size(URLContext *s, RTMPPacket *pkt)
1642 {
1643 RTMPContext *rt = s->priv_data;
1644
1645 if (pkt->size < 4) {
1646 av_log(s, AV_LOG_ERROR,
1647 "Too short window acknowledgement size packet (%d)\n",
1648 pkt->size);
1649 return AVERROR_INVALIDDATA;
1650 }
1651
1652 rt->receive_report_size = AV_RB32(pkt->data);
1653 if (rt->receive_report_size <= 0) {
1654 av_log(s, AV_LOG_ERROR, "Incorrect window acknowledgement size %d\n",
1655 rt->receive_report_size);
1656 return AVERROR_INVALIDDATA;
1657 }
1658 av_log(s, AV_LOG_DEBUG, "Window acknowledgement size = %d\n", rt->receive_report_size);
1659 // Send an Acknowledgement packet after receiving half the maximum
1660 // size, to make sure the peer can keep on sending without waiting
1661 // for acknowledgements.
1662 rt->receive_report_size >>= 1;
1663
1664 return 0;
1665 }
1666
1667 static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt,
1668 const char *opaque, const char *challenge)
1669 {
1670 uint8_t hash[16];
1671 char hashstr[AV_BASE64_SIZE(sizeof(hash))], challenge2[10];
1672 struct AVMD5 *md5 = av_md5_alloc();
1673 if (!md5)
1674 return AVERROR(ENOMEM);
1675
1676 snprintf(challenge2, sizeof(challenge2), "%08x", av_get_random_seed());
1677
1678 av_md5_init(md5);
1679 av_md5_update(md5, user, strlen(user));
1680 av_md5_update(md5, salt, strlen(salt));
1681 av_md5_update(md5, rt->password, strlen(rt->password));
1682 av_md5_final(md5, hash);
1683 av_base64_encode(hashstr, sizeof(hashstr), hash,
1684 sizeof(hash));
1685 av_md5_init(md5);
1686 av_md5_update(md5, hashstr, strlen(hashstr));
1687 if (opaque)
1688 av_md5_update(md5, opaque, strlen(opaque));
1689 else if (challenge)
1690 av_md5_update(md5, challenge, strlen(challenge));
1691 av_md5_update(md5, challenge2, strlen(challenge2));
1692 av_md5_final(md5, hash);
1693 av_base64_encode(hashstr, sizeof(hashstr), hash,
1694 sizeof(hash));
1695 snprintf(rt->auth_params, sizeof(rt->auth_params),
1696 "?authmod=%s&user=%s&challenge=%s&response=%s",
1697 "adobe", user, challenge2, hashstr);
1698 if (opaque)
1699 av_strlcatf(rt->auth_params, sizeof(rt->auth_params),
1700 "&opaque=%s", opaque);
1701
1702 av_free(md5);
1703 return 0;
1704 }
1705
1706 static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
1707 {
1708 uint8_t hash[16];
1709 char hashstr1[33], hashstr2[33];
1710 const char *realm = "live";
1711 const char *method = "publish";
1712 const char *qop = "auth";
1713 const char *nc = "00000001";
1714 char cnonce[10];
1715 struct AVMD5 *md5 = av_md5_alloc();
1716 if (!md5)
1717 return AVERROR(ENOMEM);
1718
1719 snprintf(cnonce, sizeof(cnonce), "%08x", av_get_random_seed());
1720
1721 av_md5_init(md5);
1722 av_md5_update(md5, user, strlen(user));
1723 av_md5_update(md5, ":", 1);
1724 av_md5_update(md5, realm, strlen(realm));
1725 av_md5_update(md5, ":", 1);
1726 av_md5_update(md5, rt->password, strlen(rt->password));
1727 av_md5_final(md5, hash);
1728 ff_data_to_hex(hashstr1, hash, 16, 1);
1729
1730 av_md5_init(md5);
1731 av_md5_update(md5, method, strlen(method));
1732 av_md5_update(md5, ":/", 2);
1733 av_md5_update(md5, rt->app, strlen(rt->app));
1734 if (!strchr(rt->app, '/'))
1735 av_md5_update(md5, "/_definst_", strlen("/_definst_"));
1736 av_md5_final(md5, hash);
1737 ff_data_to_hex(hashstr2, hash, 16, 1);
1738
1739 av_md5_init(md5);
1740 av_md5_update(md5, hashstr1, strlen(hashstr1));
1741 av_md5_update(md5, ":", 1);
1742 if (nonce)
1743 av_md5_update(md5, nonce, strlen(nonce));
1744 av_md5_update(md5, ":", 1);
1745 av_md5_update(md5, nc, strlen(nc));
1746 av_md5_update(md5, ":", 1);
1747 av_md5_update(md5, cnonce, strlen(cnonce));
1748 av_md5_update(md5, ":", 1);
1749 av_md5_update(md5, qop, strlen(qop));
1750 av_md5_update(md5, ":", 1);
1751 av_md5_update(md5, hashstr2, strlen(hashstr2));
1752 av_md5_final(md5, hash);
1753 ff_data_to_hex(hashstr1, hash, 16, 1);
1754
1755 snprintf(rt->auth_params, sizeof(rt->auth_params),
1756 "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1757 "llnw", user, nonce, cnonce, nc, hashstr1);
1758
1759 av_free(md5);
1760 return 0;
1761 }
1762
1763 static int handle_connect_error(URLContext *s, const char *desc)
1764 {
1765 RTMPContext *rt = s->priv_data;
1766 char buf[300], *ptr, authmod[15];
1767 int i = 0, ret = 0;
1768 const char *user = "", *salt = "", *opaque = NULL,
1769 *challenge = NULL, *cptr = NULL, *nonce = NULL;
1770
1771 if (!(cptr = strstr(desc, "authmod=adobe")) &&
1772 !(cptr = strstr(desc, "authmod=llnw"))) {
1773 av_log(s, AV_LOG_ERROR,
1774 "Unknown connect error (unsupported authentication method?)\n");
1775 return AVERROR_UNKNOWN;
1776 }
1777 cptr += strlen("authmod=");
1778 while (*cptr && *cptr != ' ' && i < sizeof(authmod) - 1)
1779 authmod[i++] = *cptr++;
1780 authmod[i] = '\0';
1781
1782 if (!rt->username[0] || !rt->password[0]) {
1783 av_log(s, AV_LOG_ERROR, "No credentials set\n");
1784 return AVERROR_UNKNOWN;
1785 }
1786
1787 if (strstr(desc, "?reason=authfailed")) {
1788 av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1789 return AVERROR_UNKNOWN;
1790 } else if (strstr(desc, "?reason=nosuchuser")) {
1791 av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1792 return AVERROR_UNKNOWN;
1793 }
1794
1795 if (rt->auth_tried) {
1796 av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1797 return AVERROR_UNKNOWN;
1798 }
1799
1800 rt->auth_params[0] = '\0';
1801
1802 if (strstr(desc, "code=403 need auth")) {
1803 snprintf(rt->auth_params, sizeof(rt->auth_params),
1804 "?authmod=%s&user=%s", authmod, rt->username);
1805 return 0;
1806 }
1807
1808 if (!(cptr = strstr(desc, "?reason=needauth"))) {
1809 av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1810 return AVERROR_UNKNOWN;
1811 }
1812
1813 av_strlcpy(buf, cptr + 1, sizeof(buf));
1814 ptr = buf;
1815
1816 while (ptr) {
1817 char *next = strchr(ptr, '&');
1818 char *value = strchr(ptr, '=');
1819 if (next)
1820 *next++ = '\0';
1821 if (value) {
1822 *value++ = '\0';
1823 if (!strcmp(ptr, "user")) {
1824 user = value;
1825 } else if (!strcmp(ptr, "salt")) {
1826 salt = value;
1827 } else if (!strcmp(ptr, "opaque")) {
1828 opaque = value;
1829 } else if (!strcmp(ptr, "challenge")) {
1830 challenge = value;
1831 } else if (!strcmp(ptr, "nonce")) {
1832 nonce = value;
1833 } else {
1834 av_log(s, AV_LOG_INFO, "Ignoring unsupported var %s\n", ptr);
1835 }
1836 } else {
1837 av_log(s, AV_LOG_WARNING, "Variable %s has NULL value\n", ptr);
1838 }
1839 ptr = next;
1840 }
1841
1842 if (!strcmp(authmod, "adobe")) {
1843 if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1844 return ret;
1845 } else {
1846 if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1847 return ret;
1848 }
1849
1850 rt->auth_tried = 1;
1851 return 0;
1852 }
1853
1854 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1855 {
1856 RTMPContext *rt = s->priv_data;
1857 const uint8_t *data_end = pkt->data + pkt->size;
1858 char *tracked_method = NULL;
1859 int level = AV_LOG_ERROR;
1860 uint8_t tmpstr[256];
1861 int ret;
1862
1863 if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1864 return ret;
1865
1866 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1867 "description", tmpstr, sizeof(tmpstr))) {
1868 if (tracked_method && (!strcmp(tracked_method, "_checkbw") ||
1869 !strcmp(tracked_method, "releaseStream") ||
1870 !strcmp(tracked_method, "FCSubscribe") ||
1871 !strcmp(tracked_method, "FCPublish"))) {
1872 /* Gracefully ignore Adobe-specific historical artifact errors. */
1873 level = AV_LOG_WARNING;
1874 ret = 0;
1875 } else if (tracked_method && !strcmp(tracked_method, "getStreamLength")) {
1876 level = rt->live ? AV_LOG_DEBUG : AV_LOG_WARNING;
1877 ret = 0;
1878 } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1879 ret = handle_connect_error(s, tmpstr);
1880 if (!ret) {
1881 rt->do_reconnect = 1;
1882 level = AV_LOG_VERBOSE;
1883 }
1884 } else
1885 ret = AVERROR_UNKNOWN;
1886 av_log(s, level, "Server error: %s\n", tmpstr);
1887 }
1888
1889 av_free(tracked_method);
1890 return ret;
1891 }
1892
1893 static int write_begin(URLContext *s)
1894 {
1895 RTMPContext *rt = s->priv_data;
1896 PutByteContext pbc;
1897 RTMPPacket spkt = { 0 };
1898 int ret;
1899
1900 // Send Stream Begin 1
1901 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1902 RTMP_PT_USER_CONTROL, 0, 6)) < 0) {
1903 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1904 return ret;
1905 }
1906
1907 bytestream2_init_writer(&pbc, spkt.data, spkt.size);
1908 bytestream2_put_be16(&pbc, 0); // 0 -> Stream Begin
1909 bytestream2_put_be32(&pbc, rt->nb_streamid);
1910
1911 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1912 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1913
1914 ff_rtmp_packet_destroy(&spkt);
1915
1916 return ret;
1917 }
1918
1919 static int write_status(URLContext *s, RTMPPacket *pkt,
1920 const char *status, const char *description, const char *details)
1921 {
1922 RTMPContext *rt = s->priv_data;
1923 RTMPPacket spkt = { 0 };
1924 uint8_t *pp;
1925 int ret;
1926
1927 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1928 RTMP_PT_INVOKE, 0,
1929 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1930 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1931 return ret;
1932 }
1933
1934 pp = spkt.data;
1935 spkt.extra = pkt->extra;
1936 ff_amf_write_string(&pp, "onStatus");
1937 ff_amf_write_number(&pp, 0);
1938 ff_amf_write_null(&pp);
1939
1940 ff_amf_write_object_start(&pp);
1941 ff_amf_write_field_name(&pp, "level");
1942 ff_amf_write_string(&pp, "status");
1943 ff_amf_write_field_name(&pp, "code");
1944 ff_amf_write_string(&pp, status);
1945 ff_amf_write_field_name(&pp, "description");
1946 ff_amf_write_string(&pp, description);
1947 if (details) {
1948 ff_amf_write_field_name(&pp, "details");
1949 ff_amf_write_string(&pp, details);
1950 }
1951 ff_amf_write_object_end(&pp);
1952
1953 spkt.size = pp - spkt.data;
1954 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1955 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1956 ff_rtmp_packet_destroy(&spkt);
1957
1958 return ret;
1959 }
1960
1961 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1962 {
1963 RTMPContext *rt = s->priv_data;
1964 double seqnum;
1965 char filename[128];
1966 char command[64];
1967 int stringlen;
1968 char *pchar;
1969 const uint8_t *p = pkt->data;
1970 uint8_t *pp = NULL;
1971 RTMPPacket spkt = { 0 };
1972 GetByteContext gbc;
1973 int ret;
1974
1975 bytestream2_init(&gbc, p, pkt->size);
1976 if (ff_amf_read_string(&gbc, command, sizeof(command),
1977 &stringlen)) {
1978 av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1979 return AVERROR_INVALIDDATA;
1980 }
1981
1982 ret = ff_amf_read_number(&gbc, &seqnum);
1983 if (ret)
1984 return ret;
1985 ret = ff_amf_read_null(&gbc);
1986 if (ret)
1987 return ret;
1988 if (!strcmp(command, "FCPublish") ||
1989 !strcmp(command, "publish")) {
1990 ret = ff_amf_read_string(&gbc, filename,
1991 sizeof(filename), &stringlen);
1992 if (ret) {
1993 if (ret == AVERROR(EINVAL))
1994 av_log(s, AV_LOG_ERROR, "Unable to parse stream name - name too long?\n");
1995 else
1996 av_log(s, AV_LOG_ERROR, "Unable to parse stream name\n");
1997 return ret;
1998 }
1999 // check with url
2000 if (s->filename) {
2001 pchar = strrchr(s->filename, '/');
2002 if (!pchar) {
2003 av_log(s, AV_LOG_WARNING,
2004 "Unable to find / in url %s, bad format\n",
2005 s->filename);
2006 pchar = s->filename;
2007 }
2008 pchar++;
2009 if (strcmp(pchar, filename))
2010 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
2011 " %s\n", filename, pchar);
2012 }
2013 rt->state = STATE_RECEIVING;
2014 }
2015
2016 if (!strcmp(command, "FCPublish")) {
2017 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
2018 RTMP_PT_INVOKE, 0,
2019 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
2020 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
2021 return ret;
2022 }
2023 pp = spkt.data;
2024 ff_amf_write_string(&pp, "onFCPublish");
2025 } else if (!strcmp(command, "publish")) {
2026 char statusmsg[sizeof(filename) + 32];
2027 snprintf(statusmsg, sizeof(statusmsg), "%s is now published", filename);
2028 ret = write_begin(s);
2029 if (ret < 0)
2030 return ret;
2031
2032 // Send onStatus(NetStream.Publish.Start)
2033 return write_status(s, pkt, "NetStream.Publish.Start",
2034 statusmsg, filename);
2035 } else if (!strcmp(command, "play")) {
2036 ret = write_begin(s);
2037 if (ret < 0)
2038 return ret;
2039 rt->state = STATE_SENDING;
2040 return write_status(s, pkt, "NetStream.Play.Start",
2041 "playing stream", NULL);
2042 } else {
2043 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
2044 RTMP_PT_INVOKE, 0,
2045 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
2046 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
2047 return ret;
2048 }
2049 pp = spkt.data;
2050 ff_amf_write_string(&pp, "_result");
2051 ff_amf_write_number(&pp, seqnum);
2052 ff_amf_write_null(&pp);
2053 if (!strcmp(command, "createStream")) {
2054 rt->nb_streamid++;
2055 if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
2056 rt->nb_streamid++; /* Values 0 and 2 are reserved */
2057 ff_amf_write_number(&pp, rt->nb_streamid);
2058 /* By now we don't control which streams are removed in
2059 * deleteStream. There is no stream creation control
2060 * if a client creates more than 2^32 - 2 streams. */
2061 }
2062 }
2063 spkt.size = pp - spkt.data;
2064 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
2065 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
2066 ff_rtmp_packet_destroy(&spkt);
2067 return ret;
2068 }
2069
2070 /**
2071 * Read the AMF_NUMBER response ("_result") to a function call
2072 * (e.g. createStream()). This response should be made up of the AMF_STRING
2073 * "result", a NULL object and then the response encoded as AMF_NUMBER. On a
2074 * successful response, we will return set the value to number (otherwise number
2075 * will not be changed).
2076 *
2077 * @return 0 if reading the value succeeds, negative value otherwise
2078 */
2079 static int read_number_result(RTMPPacket *pkt, double *number)
2080 {
2081 // We only need to fit "_result" in this.
2082 uint8_t strbuffer[8];
2083 int stringlen;
2084 double numbuffer;
2085 GetByteContext gbc;
2086
2087 bytestream2_init(&gbc, pkt->data, pkt->size);
2088
2089 // Value 1/4: "_result" as AMF_STRING
2090 if (ff_amf_read_string(&gbc, strbuffer, sizeof(strbuffer), &stringlen))
2091 return AVERROR_INVALIDDATA;
2092 if (strcmp(strbuffer, "_result"))
2093 return AVERROR_INVALIDDATA;
2094 // Value 2/4: The callee reference number
2095 if (ff_amf_read_number(&gbc, &numbuffer))
2096 return AVERROR_INVALIDDATA;
2097 // Value 3/4: Null
2098 if (ff_amf_read_null(&gbc))
2099 return AVERROR_INVALIDDATA;
2100 // Value 4/4: The response as AMF_NUMBER
2101 if (ff_amf_read_number(&gbc, &numbuffer))
2102 return AVERROR_INVALIDDATA;
2103 else
2104 *number = numbuffer;
2105
2106 return 0;
2107 }
2108
2109 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
2110 {
2111 RTMPContext *rt = s->priv_data;
2112 char *tracked_method = NULL;
2113 int ret = 0;
2114
2115 if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
2116 return ret;
2117
2118 if (!tracked_method) {
2119 /* Ignore this reply when the current method is not tracked. */
2120 return ret;
2121 }
2122
2123 if (!strcmp(tracked_method, "connect")) {
2124 if (!rt->is_input) {
2125 if ((ret = gen_release_stream(s, rt)) < 0)
2126 goto fail;
2127
2128 if ((ret = gen_fcpublish_stream(s, rt)) < 0)
2129 goto fail;
2130 } else {
2131 if ((ret = gen_window_ack_size(s, rt)) < 0)
2132 goto fail;
2133 }
2134
2135 if ((ret = gen_create_stream(s, rt)) < 0)
2136 goto fail;
2137
2138 if (rt->is_input) {
2139 /* Send the FCSubscribe command when the name of live
2140 * stream is defined by the user or if it's a live stream. */
2141 if (rt->subscribe) {
2142 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
2143 goto fail;
2144 } else if (rt->live == -1) {
2145 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
2146 goto fail;
2147 }
2148 }
2149 } else if (!strcmp(tracked_method, "createStream")) {
2150 double stream_id;
2151 if (read_number_result(pkt, &stream_id)) {
2152 av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
2153 } else {
2154 rt->stream_id = stream_id;
2155 }
2156
2157 if (!rt->is_input) {
2158 if ((ret = gen_publish(s, rt)) < 0)
2159 goto fail;
2160 } else {
2161 if (rt->live != -1) {
2162 if ((ret = gen_get_stream_length(s, rt)) < 0)
2163 goto fail;
2164 }
2165 if ((ret = gen_play(s, rt)) < 0)
2166 goto fail;
2167 if ((ret = gen_buffer_time(s, rt)) < 0)
2168 goto fail;
2169 }
2170 } else if (!strcmp(tracked_method, "getStreamLength")) {
2171 if (read_number_result(pkt, &rt->duration)) {
2172 av_log(s, AV_LOG_WARNING, "Unexpected reply on getStreamLength()\n");
2173 }
2174 }
2175
2176 fail:
2177 av_free(tracked_method);
2178 return ret;
2179 }
2180
2181 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
2182 {
2183 RTMPContext *rt = s->priv_data;
2184 const uint8_t *data_end = pkt->data + pkt->size;
2185 const uint8_t *ptr = pkt->data + RTMP_HEADER;
2186 uint8_t tmpstr[256];
2187 int i, t;
2188
2189 for (i = 0; i < 2; i++) {
2190 t = ff_amf_tag_size(ptr, data_end);
2191 if (t < 0)
2192 return 1;
2193 ptr += t;
2194 }
2195
2196 t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
2197 if (!t && !strcmp(tmpstr, "error")) {
2198 t = ff_amf_get_field_value(ptr, data_end,
2199 "description", tmpstr, sizeof(tmpstr));
2200 if (t || !tmpstr[0])
2201 t = ff_amf_get_field_value(ptr, data_end, "code",
2202 tmpstr, sizeof(tmpstr));
2203 if (!t)
2204 av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
2205 return -1;
2206 }
2207
2208 t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
2209 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
2210 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
2211 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
2212 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
2213 if (!t && !strcmp(tmpstr, "NetStream.Seek.Notify")) rt->state = STATE_PLAYING;
2214
2215 return 0;
2216 }
2217
2218 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
2219 {
2220 RTMPContext *rt = s->priv_data;
2221 int ret = 0;
2222
2223 //TODO: check for the messages sent for wrong state?
2224 if (ff_amf_match_string(pkt->data, pkt->size, "_error")) {
2225 if ((ret = handle_invoke_error(s, pkt)) < 0)
2226 return ret;
2227 } else if (ff_amf_match_string(pkt->data, pkt->size, "_result")) {
2228 if ((ret = handle_invoke_result(s, pkt)) < 0)
2229 return ret;
2230 } else if (ff_amf_match_string(pkt->data, pkt->size, "onStatus")) {
2231 if ((ret = handle_invoke_status(s, pkt)) < 0)
2232 return ret;
2233 } else if (ff_amf_match_string(pkt->data, pkt->size, "onBWDone")) {
2234 if ((ret = gen_check_bw(s, rt)) < 0)
2235 return ret;
2236 } else if (ff_amf_match_string(pkt->data, pkt->size, "releaseStream") ||
2237 ff_amf_match_string(pkt->data, pkt->size, "FCPublish") ||
2238 ff_amf_match_string(pkt->data, pkt->size, "publish") ||
2239 ff_amf_match_string(pkt->data, pkt->size, "play") ||
2240 ff_amf_match_string(pkt->data, pkt->size, "_checkbw") ||
2241 ff_amf_match_string(pkt->data, pkt->size, "createStream")) {
2242 if ((ret = send_invoke_response(s, pkt)) < 0)
2243 return ret;
2244 }
2245
2246 return ret;
2247 }
2248
2249 static int update_offset(RTMPContext *rt, int size)
2250 {
2251 int old_flv_size;
2252
2253 // generate packet header and put data into buffer for FLV demuxer
2254 if (rt->flv_off < rt->flv_size) {
2255 // There is old unread data in the buffer, thus append at the end
2256 old_flv_size = rt->flv_size;
2257 rt->flv_size += size;
2258 } else {
2259 // All data has been read, write the new data at the start of the buffer
2260 old_flv_size = 0;
2261 rt->flv_size = size;
2262 rt->flv_off = 0;
2263 }
2264
2265 return old_flv_size;
2266 }
2267
2268 static int append_flv_data(RTMPContext *rt, RTMPPacket *pkt, int skip)
2269 {
2270 int old_flv_size, ret;
2271 PutByteContext pbc;
2272 const uint8_t *data = pkt->data + skip;
2273 const int size = pkt->size - skip;
2274 uint32_t ts = pkt->timestamp;
2275
2276 if (pkt->type == RTMP_PT_AUDIO) {
2277 rt->has_audio = 1;
2278 } else if (pkt->type == RTMP_PT_VIDEO) {
2279 rt->has_video = 1;
2280 }
2281
2282 old_flv_size = update_offset(rt, size + 15);
2283
2284 if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) {
2285 rt->flv_size = rt->flv_off = 0;
2286 return ret;
2287 }
2288 bytestream2_init_writer(&pbc, rt->flv_data, rt->flv_size);
2289 bytestream2_skip_p(&pbc, old_flv_size);
2290 bytestream2_put_byte(&pbc, pkt->type);
2291 bytestream2_put_be24(&pbc, size);
2292 bytestream2_put_be24(&pbc, ts);
2293 bytestream2_put_byte(&pbc, ts >> 24);
2294 bytestream2_put_be24(&pbc, 0);
2295 bytestream2_put_buffer(&pbc, data, size);
2296 bytestream2_put_be32(&pbc, size + RTMP_HEADER);
2297
2298 return 0;
2299 }
2300
2301 static int handle_notify(URLContext *s, RTMPPacket *pkt)
2302 {
2303 RTMPContext *rt = s->priv_data;
2304 uint8_t commandbuffer[64];
2305 char statusmsg[128];
2306 int stringlen, ret, skip = 0;
2307 GetByteContext gbc;
2308
2309 bytestream2_init(&gbc, pkt->data, pkt->size);
2310 if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2311 &stringlen))
2312 return AVERROR_INVALIDDATA;
2313
2314 if (!strcmp(commandbuffer, "onMetaData")) {
2315 // metadata properties should be stored in a mixed array
2316 if (bytestream2_get_byte(&gbc) == AMF_DATA_TYPE_MIXEDARRAY) {
2317 // We have found a metaData Array so flv can determine the streams
2318 // from this.
2319 rt->received_metadata = 1;
2320 // skip 32-bit max array index
2321 bytestream2_skip(&gbc, 4);
2322 while (bytestream2_get_bytes_left(&gbc) > 3) {
2323 if (ff_amf_get_string(&gbc, statusmsg, sizeof(statusmsg),
2324 &stringlen))
2325 return AVERROR_INVALIDDATA;
2326 // We do not care about the content of the property (yet).
2327 stringlen = ff_amf_tag_size(gbc.buffer, gbc.buffer_end);
2328 if (stringlen < 0)
2329 return AVERROR_INVALIDDATA;
2330 bytestream2_skip(&gbc, stringlen);
2331
2332 // The presence of the following properties indicates that the
2333 // respective streams are present.
2334 if (!strcmp(statusmsg, "videocodecid")) {
2335 rt->has_video = 1;
2336 }
2337 if (!strcmp(statusmsg, "audiocodecid")) {
2338 rt->has_audio = 1;
2339 }
2340 }
2341 if (bytestream2_get_be24(&gbc) != AMF_END_OF_OBJECT)
2342 return AVERROR_INVALIDDATA;
2343 }
2344 }
2345
2346 // Skip the @setDataFrame string and validate it is a notification
2347 if (!strcmp(commandbuffer, "@setDataFrame")) {
2348 skip = gbc.buffer - pkt->data;
2349 ret = ff_amf_read_string(&gbc, statusmsg,
2350 sizeof(statusmsg), &stringlen);
2351 if (ret < 0)
2352 return AVERROR_INVALIDDATA;
2353 }
2354
2355 return append_flv_data(rt, pkt, skip);
2356 }
2357
2358 /**
2359 * Parse received packet and possibly perform some action depending on
2360 * the packet contents.
2361 * @return 0 for no errors, negative values for serious errors which prevent
2362 * further communications, positive values for uncritical errors
2363 */
2364 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
2365 {
2366 int ret;
2367
2368 #ifdef DEBUG
2369 ff_rtmp_packet_dump(s, pkt);
2370 #endif
2371
2372 switch (pkt->type) {
2373 case RTMP_PT_BYTES_READ:
2374 av_log(s, AV_LOG_TRACE, "received bytes read report\n");
2375 break;
2376 case RTMP_PT_CHUNK_SIZE:
2377 if ((ret = handle_chunk_size(s, pkt)) < 0)
2378 return ret;
2379 break;
2380 case RTMP_PT_USER_CONTROL:
2381 if ((ret = handle_user_control(s, pkt)) < 0)
2382 return ret;
2383 break;
2384 case RTMP_PT_SET_PEER_BW:
2385 if ((ret = handle_set_peer_bw(s, pkt)) < 0)
2386 return ret;
2387 break;
2388 case RTMP_PT_WINDOW_ACK_SIZE:
2389 if ((ret = handle_window_ack_size(s, pkt)) < 0)
2390 return ret;
2391 break;
2392 case RTMP_PT_INVOKE:
2393 if ((ret = handle_invoke(s, pkt)) < 0)
2394 return ret;
2395 break;
2396 case RTMP_PT_VIDEO:
2397 case RTMP_PT_AUDIO:
2398 case RTMP_PT_METADATA:
2399 case RTMP_PT_NOTIFY:
2400 /* Audio, Video and Metadata packets are parsed in get_packet() */
2401 break;
2402 default:
2403 av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2404 break;
2405 }
2406 return 0;
2407 }
2408
2409 static int handle_metadata(RTMPContext *rt, RTMPPacket *pkt)
2410 {
2411 int ret, old_flv_size, type;
2412 const uint8_t *next;
2413 uint8_t *p;
2414 uint32_t size;
2415 uint32_t ts, cts, pts = 0;
2416
2417 old_flv_size = update_offset(rt, pkt->size);
2418
2419 if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) {
2420 rt->flv_size = rt->flv_off = 0;
2421 return ret;
2422 }
2423
2424 next = pkt->data;
2425 p = rt->flv_data + old_flv_size;
2426
2427 /* copy data while rewriting timestamps */
2428 ts = pkt->timestamp;
2429
2430 while (next - pkt->data < pkt->size - RTMP_HEADER) {
2431 type = bytestream_get_byte(&next);
2432 size = bytestream_get_be24(&next);
2433 cts = bytestream_get_be24(&next);
2434 cts |= bytestream_get_byte(&next) << 24;
2435 if (!pts)
2436 pts = cts;
2437 ts += cts - pts;
2438 pts = cts;
2439 if (size + 3 + 4 > pkt->data + pkt->size - next)
2440 break;
2441 bytestream_put_byte(&p, type);
2442 bytestream_put_be24(&p, size);
2443 bytestream_put_be24(&p, ts);
2444 bytestream_put_byte(&p, ts >> 24);
2445 memcpy(p, next, size + 3 + 4);
2446 p += size + 3;
2447 bytestream_put_be32(&p, size + RTMP_HEADER);
2448 next += size + 3 + 4;
2449 }
2450 if (p != rt->flv_data + rt->flv_size) {
2451 av_log(rt, AV_LOG_WARNING, "Incomplete flv packets in "
2452 "RTMP_PT_METADATA packet\n");
2453 rt->flv_size = p - rt->flv_data;
2454 }
2455
2456 return 0;
2457 }
2458
2459 /**
2460 * Interact with the server by receiving and sending RTMP packets until
2461 * there is some significant data (media data or expected status notification).
2462 *
2463 * @param s reading context
2464 * @param for_header non-zero value tells function to work until it
2465 * gets notification from the server that playing has been started,
2466 * otherwise function will work until some media data is received (or
2467 * an error happens)
2468 * @return 0 for successful operation, negative value in case of error
2469 */
2470 static int get_packet(URLContext *s, int for_header)
2471 {
2472 RTMPContext *rt = s->priv_data;
2473 int ret;
2474
2475 if (rt->state == STATE_STOPPED)
2476 return AVERROR_EOF;
2477
2478 for (;;) {
2479 RTMPPacket rpkt = { 0 };
2480 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2481 rt->in_chunk_size, &rt->prev_pkt[0],
2482 &rt->nb_prev_pkt[0])) <= 0) {
2483 if (ret == 0) {
2484 return AVERROR(EAGAIN);
2485 } else {
2486 return AVERROR(EIO);
2487 }
2488 }
2489
2490 // Track timestamp for later use
2491 rt->last_timestamp = rpkt.timestamp;
2492
2493 rt->bytes_read += ret;
2494 if (rt->bytes_read - rt->last_bytes_read > rt->receive_report_size) {
2495 av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2496 if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0) {
2497 ff_rtmp_packet_destroy(&rpkt);
2498 return ret;
2499 }
2500 rt->last_bytes_read = rt->bytes_read;
2501 }
2502
2503 ret = rtmp_parse_result(s, rt, &rpkt);
2504
2505 // At this point we must check if we are in the seek state and continue
2506 // with the next packet. handle_invoke will get us out of this state
2507 // when the right message is encountered
2508 if (rt->state == STATE_SEEKING) {
2509 ff_rtmp_packet_destroy(&rpkt);
2510 // We continue, let the natural flow of things happen:
2511 // AVERROR(EAGAIN) or handle_invoke gets us out of here
2512 continue;
2513 }
2514
2515 if (ret < 0) {//serious error in current packet
2516 ff_rtmp_packet_destroy(&rpkt);
2517 return ret;
2518 }
2519 if (rt->do_reconnect && for_header) {
2520 ff_rtmp_packet_destroy(&rpkt);
2521 return 0;
2522 }
2523 if (rt->state == STATE_STOPPED) {
2524 ff_rtmp_packet_destroy(&rpkt);
2525 return AVERROR_EOF;
2526 }
2527 if (for_header && (rt->state == STATE_PLAYING ||
2528 rt->state == STATE_PUBLISHING ||
2529 rt->state == STATE_SENDING ||
2530 rt->state == STATE_RECEIVING)) {
2531 ff_rtmp_packet_destroy(&rpkt);
2532 return 0;
2533 }
2534 if (!rpkt.size || !rt->is_input) {
2535 ff_rtmp_packet_destroy(&rpkt);
2536 continue;
2537 }
2538 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO) {
2539 ret = append_flv_data(rt, &rpkt, 0);
2540 ff_rtmp_packet_destroy(&rpkt);
2541 return ret;
2542 } else if (rpkt.type == RTMP_PT_NOTIFY) {
2543 ret = handle_notify(s, &rpkt);
2544 ff_rtmp_packet_destroy(&rpkt);
2545 return ret;
2546 } else if (rpkt.type == RTMP_PT_METADATA) {
2547 ret = handle_metadata(rt, &rpkt);
2548 ff_rtmp_packet_destroy(&rpkt);
2549 return ret;
2550 }
2551 ff_rtmp_packet_destroy(&rpkt);
2552 }
2553 }
2554
2555 static int rtmp_close(URLContext *h)
2556 {
2557 RTMPContext *rt = h->priv_data;
2558 int ret = 0, i, j;
2559
2560 if (!rt->is_input) {
2561 rt->flv_data = NULL;
2562 if (rt->out_pkt.size)
2563 ff_rtmp_packet_destroy(&rt->out_pkt);
2564 if (rt->state > STATE_FCPUBLISH)
2565 ret = gen_fcunpublish_stream(h, rt);
2566 }
2567 if (rt->state > STATE_HANDSHAKED)
2568 ret = gen_delete_stream(h, rt);
2569 for (i = 0; i < 2; i++) {
2570 for (j = 0; j < rt->nb_prev_pkt[i]; j++)
2571 ff_rtmp_packet_destroy(&rt->prev_pkt[i][j]);
2572 av_freep(&rt->prev_pkt[i]);
2573 }
2574
2575 free_tracked_methods(rt);
2576 av_freep(&rt->flv_data);
2577 ffurl_closep(&rt->stream);
2578 return ret;
2579 }
2580
2581 /**
2582 * Insert a fake onMetadata packet into the FLV stream to notify the FLV
2583 * demuxer about the duration of the stream.
2584 *
2585 * This should only be done if there was no real onMetadata packet sent by the
2586 * server at the start of the stream and if we were able to retrieve a valid
2587 * duration via a getStreamLength call.
2588 *
2589 * @return 0 for successful operation, negative value in case of error
2590 */
2591 static int inject_fake_duration_metadata(RTMPContext *rt)
2592 {
2593 // We need to insert the metadata packet directly after the FLV
2594 // header, i.e. we need to move all other already read data by the
2595 // size of our fake metadata packet.
2596
2597 uint8_t* p;
2598 // Keep old flv_data pointer
2599 uint8_t* old_flv_data = rt->flv_data;
2600 // Allocate a new flv_data pointer with enough space for the additional package
2601 if (!(rt->flv_data = av_malloc(rt->flv_size + 55))) {
2602 rt->flv_data = old_flv_data;
2603 return AVERROR(ENOMEM);
2604 }
2605
2606 // Copy FLV header
2607 memcpy(rt->flv_data, old_flv_data, 13);
2608 // Copy remaining packets
2609 memcpy(rt->flv_data + 13 + 55, old_flv_data + 13, rt->flv_size - 13);
2610 // Increase the size by the injected packet
2611 rt->flv_size += 55;
2612 // Delete the old FLV data
2613 av_freep(&old_flv_data);
2614
2615 p = rt->flv_data + 13;
2616 bytestream_put_byte(&p, FLV_TAG_TYPE_META);
2617 bytestream_put_be24(&p, 40); // size of data part (sum of all parts below)
2618 bytestream_put_be24(&p, 0); // timestamp
2619 bytestream_put_be32(&p, 0); // reserved
2620
2621 // first event name as a string
2622 bytestream_put_byte(&p, AMF_DATA_TYPE_STRING);
2623 // "onMetaData" as AMF string
2624 bytestream_put_be16(&p, 10);
2625 bytestream_put_buffer(&p, "onMetaData", 10);
2626
2627 // mixed array (hash) with size and string/type/data tuples
2628 bytestream_put_byte(&p, AMF_DATA_TYPE_MIXEDARRAY);
2629 bytestream_put_be32(&p, 1); // metadata_count
2630
2631 // "duration" as AMF string
2632 bytestream_put_be16(&p, 8);
2633 bytestream_put_buffer(&p, "duration", 8);
2634 bytestream_put_byte(&p, AMF_DATA_TYPE_NUMBER);
2635 bytestream_put_be64(&p, av_double2int(rt->duration));
2636
2637 // Finalise object
2638 bytestream_put_be16(&p, 0); // Empty string
2639 bytestream_put_byte(&p, AMF_END_OF_OBJECT);
2640 bytestream_put_be32(&p, 40 + RTMP_HEADER); // size of data part (sum of all parts above)
2641
2642 return 0;
2643 }
2644
2645 /**
2646 * Open RTMP connection and verify that the stream can be played.
2647 *
2648 * URL syntax: rtmp://server[:port][/app][/playpath]
2649 * where 'app' is first one or two directories in the path
2650 * (e.g. /ondemand/, /flash/live/, etc.)
2651 * and 'playpath' is a file name (the rest of the path,
2652 * may be prefixed with "mp4:")
2653 */
2654 static int rtmp_open(URLContext *s, const char *uri, int flags, AVDictionary **opts)
2655 {
2656 RTMPContext *rt = s->priv_data;
2657 char proto[8], hostname[256], path[1024], auth[100], *fname;
2658 char *old_app, *qmark, *n, fname_buffer[1024];
2659 uint8_t buf[2048];
2660 int port;
2661 int ret;
2662
2663 if (rt->listen_timeout > 0)
2664 rt->listen = 1;
2665
2666 rt->is_input = !(flags & AVIO_FLAG_WRITE);
2667
2668 av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2669 hostname, sizeof(hostname), &port,
2670 path, sizeof(path), s->filename);
2671
2672 n = strchr(path, ' ');
2673 if (n) {
2674 av_log(s, AV_LOG_WARNING,
2675 "Detected librtmp style URL parameters, these aren't supported "
2676 "by the libavformat internal RTMP handler currently enabled. "
2677 "See the documentation for the correct way to pass parameters.\n");
2678 *n = '\0'; // Trim not supported part
2679 }
2680
2681 if (auth[0]) {
2682 char *ptr = strchr(auth, ':');
2683 if (ptr) {
2684 *ptr = '\0';
2685 av_strlcpy(rt->username, auth, sizeof(rt->username));
2686 av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2687 }
2688 }
2689
2690 if (rt->listen && strcmp(proto, "rtmp")) {
2691 av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2692 proto);
2693 return AVERROR(EINVAL);
2694 }
2695 if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2696 if (!strcmp(proto, "rtmpts"))
2697 av_dict_set(opts, "ffrtmphttp_tls", "1", AV_DICT_MATCH_CASE);
2698
2699 /* open the http tunneling connection */
2700 ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2701 } else if (!strcmp(proto, "rtmps")) {
2702 /* open the tls connection */
2703 if (port < 0)
2704 port = RTMPS_DEFAULT_PORT;
2705 ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2706 } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2707 if (!strcmp(proto, "rtmpte"))
2708 av_dict_set(opts, "ffrtmpcrypt_tunneling", "1", 1);
2709
2710 /* open the encrypted connection */
2711 ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2712 rt->encrypted = 1;
2713 } else {
2714 /* open the tcp connection */
2715 if (port < 0)
2716 port = RTMP_DEFAULT_PORT;
2717 if (rt->listen)
2718 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2719 "?listen&listen_timeout=%d&tcp_nodelay=%d",
2720 rt->listen_timeout * 1000, rt->tcp_nodelay);
2721 else
2722 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, "?tcp_nodelay=%d", rt->tcp_nodelay);
2723 }
2724
2725 reconnect:
2726 if ((ret = ffurl_open_whitelist(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2727 &s->interrupt_callback, opts,
2728 s->protocol_whitelist, s->protocol_blacklist, s)) < 0) {
2729 av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2730 goto fail;
2731 }
2732
2733 if (rt->swfverify) {
2734 if ((ret = rtmp_calc_swfhash(s)) < 0)
2735 goto fail;
2736 }
2737
2738 rt->state = STATE_START;
2739 if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2740 goto fail;
2741 if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2742 goto fail;
2743
2744 rt->out_chunk_size = 128;
2745 rt->in_chunk_size = 128; // Probably overwritten later
2746 rt->state = STATE_HANDSHAKED;
2747
2748 // Keep the application name when it has been defined by the user.
2749 old_app = rt->app;
2750
2751 rt->app = av_malloc(APP_MAX_LENGTH);
2752 if (!rt->app) {
2753 ret = AVERROR(ENOMEM);
2754 goto fail;
2755 }
2756
2757 //extract "app" part from path
2758 qmark = strchr(path, '?');
2759 if (qmark && strstr(qmark, "slist=")) {
2760 char* amp;
2761 // After slist we have the playpath, the full path is used as app
2762 av_strlcpy(rt->app, path + 1, APP_MAX_LENGTH);
2763 fname = strstr(path, "slist=") + 6;
2764 // Strip any further query parameters from fname
2765 amp = strchr(fname, '&');
2766 if (amp) {
2767 av_strlcpy(fname_buffer, fname, FFMIN(amp - fname + 1,
2768 sizeof(fname_buffer)));
2769 fname = fname_buffer;
2770 }
2771 } else if (!strncmp(path, "/ondemand/", 10)) {
2772 fname = path + 10;
2773 memcpy(rt->app, "ondemand", 9);
2774 } else {
2775 char *next = *path ? path + 1 : path;
2776 char *p = strchr(next, '/');
2777 if (!p) {
2778 if (old_app) {
2779 // If name of application has been defined by the user, assume that
2780 // playpath is provided in the URL
2781 fname = next;
2782 } else {
2783 fname = NULL;
2784 av_strlcpy(rt->app, next, APP_MAX_LENGTH);
2785 }
2786 } else {
2787 // make sure we do not mismatch a playpath for an application instance
2788 char *c = strchr(p + 1, ':');
2789 fname = strchr(p + 1, '/');
2790 if (!fname || (c && c < fname)) {
2791 fname = p + 1;
2792 av_strlcpy(rt->app, path + 1, FFMIN(p - path, APP_MAX_LENGTH));
2793 } else {
2794 fname++;
2795 av_strlcpy(rt->app, path + 1, FFMIN(fname - path - 1, APP_MAX_LENGTH));
2796 }
2797 }
2798 }
2799
2800 if (old_app) {
2801 // The name of application has been defined by the user, override it.
2802 if (strlen(old_app) >= APP_MAX_LENGTH) {
2803 ret = AVERROR(EINVAL);
2804 goto fail;
2805 }
2806 av_free(rt->app);
2807 rt->app = old_app;
2808 }
2809
2810 if (!rt->playpath) {
2811 int max_len = 1;
2812 if (fname)
2813 max_len = strlen(fname) + 5; // add prefix "mp4:"
2814 rt->playpath = av_malloc(max_len);
2815 if (!rt->playpath) {
2816 ret = AVERROR(ENOMEM);
2817 goto fail;
2818 }
2819
2820 if (fname) {
2821 int len = strlen(fname);
2822 if (!strchr(fname, ':') && len >= 4 &&
2823 (!strcmp(fname + len - 4, ".f4v") ||
2824 !strcmp(fname + len - 4, ".mp4"))) {
2825 memcpy(rt->playpath, "mp4:", 5);
2826 } else {
2827 if (len >= 4 && !strcmp(fname + len - 4, ".flv"))
2828 fname[len - 4] = '\0';
2829 rt->playpath[0] = 0;
2830 }
2831 av_strlcat(rt->playpath, fname, max_len);
2832 } else {
2833 rt->playpath[0] = '\0';
2834 }
2835 }
2836
2837 if (!rt->tcurl) {
2838 rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2839 if (!rt->tcurl) {
2840 ret = AVERROR(ENOMEM);
2841 goto fail;
2842 }
2843 ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2844 port, "/%s", rt->app);
2845 }
2846
2847 if (!rt->flashver) {
2848 rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2849 if (!rt->flashver) {
2850 ret = AVERROR(ENOMEM);
2851 goto fail;
2852 }
2853 if (rt->is_input) {
2854 snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2855 RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2856 RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2857 } else {
2858 snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2859 "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2860 }
2861 }
2862
2863 rt->receive_report_size = 1048576;
2864 rt->bytes_read = 0;
2865 rt->has_audio = 0;
2866 rt->has_video = 0;
2867 rt->received_metadata = 0;
2868 rt->last_bytes_read = 0;
2869 rt->max_sent_unacked = 2500000;
2870 rt->duration = 0;
2871
2872 av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2873 proto, path, rt->app, rt->playpath);
2874 if (!rt->listen) {
2875 if ((ret = gen_connect(s, rt)) < 0)
2876 goto fail;
2877 } else {
2878 if ((ret = read_connect(s, s->priv_data)) < 0)
2879 goto fail;
2880 }
2881
2882 do {
2883 ret = get_packet(s, 1);
2884 } while (ret == AVERROR(EAGAIN));
2885 if (ret < 0)
2886 goto fail;
2887
2888 if (rt->do_reconnect) {
2889 int i;
2890 ffurl_closep(&rt->stream);
2891 rt->do_reconnect = 0;
2892 rt->nb_invokes = 0;
2893 for (i = 0; i < 2; i++)
2894 memset(rt->prev_pkt[i], 0,
2895 sizeof(**rt->prev_pkt) * rt->nb_prev_pkt[i]);
2896 free_tracked_methods(rt);
2897 goto reconnect;
2898 }
2899
2900 if (rt->is_input) {
2901 // generate FLV header for demuxer
2902 rt->flv_size = 13;
2903 if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0)
2904 goto fail;
2905 rt->flv_off = 0;
2906 memcpy(rt->flv_data, "FLV\1\0\0\0\0\011\0\0\0\0", rt->flv_size);
2907
2908 // Read packets until we reach the first A/V packet or read metadata.
2909 // If there was a metadata package in front of the A/V packets, we can
2910 // build the FLV header from this. If we do not receive any metadata,
2911 // the FLV decoder will allocate the needed streams when their first
2912 // audio or video packet arrives.
2913 while (!rt->has_audio && !rt->has_video && !rt->received_metadata) {
2914 if ((ret = get_packet(s, 0)) < 0)
2915 goto fail;
2916 }
2917
2918 // Either after we have read the metadata or (if there is none) the
2919 // first packet of an A/V stream, we have a better knowledge about the
2920 // streams, so set the FLV header accordingly.
2921 if (rt->has_audio) {
2922 rt->flv_data[4] |= FLV_HEADER_FLAG_HASAUDIO;
2923 }
2924 if (rt->has_video) {
2925 rt->flv_data[4] |= FLV_HEADER_FLAG_HASVIDEO;
2926 }
2927
2928 // If we received the first packet of an A/V stream and no metadata but
2929 // the server returned a valid duration, create a fake metadata packet
2930 // to inform the FLV decoder about the duration.
2931 if (!rt->received_metadata && rt->duration > 0) {
2932 if ((ret = inject_fake_duration_metadata(rt)) < 0)
2933 goto fail;
2934 }
2935 } else {
2936 rt->flv_size = 0;
2937 rt->flv_data = NULL;
2938 rt->flv_off = 0;
2939 rt->skip_bytes = 13;
2940 }
2941
2942 s->max_packet_size = rt->stream->max_packet_size;
2943 s->is_streamed = 1;
2944 return 0;
2945
2946 fail:
2947 rtmp_close(s);
2948 return ret;
2949 }
2950
2951 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2952 {
2953 RTMPContext *rt = s->priv_data;
2954 int orig_size = size;
2955 int ret;
2956
2957 while (size > 0) {
2958 int data_left = rt->flv_size - rt->flv_off;
2959
2960 if (data_left >= size) {
2961 memcpy(buf, rt->flv_data + rt->flv_off, size);
2962 rt->flv_off += size;
2963 return orig_size;
2964 }
2965 if (data_left > 0) {
2966 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2967 buf += data_left;
2968 size -= data_left;
2969 rt->flv_off = rt->flv_size;
2970 return data_left;
2971 }
2972 if ((ret = get_packet(s, 0)) < 0)
2973 return ret;
2974 }
2975 return orig_size;
2976 }
2977
2978 static int64_t rtmp_seek(void *opaque, int stream_index, int64_t timestamp,
2979 int flags)
2980 {
2981 URLContext *s = opaque;
2982 RTMPContext *rt = s->priv_data;
2983 int ret;
2984 av_log(s, AV_LOG_DEBUG,
2985 "Seek on stream index %d at timestamp %"PRId64" with flags %08x\n",
2986 stream_index, timestamp, flags);
2987 if ((ret = gen_seek(s, rt, timestamp)) < 0) {
2988 av_log(s, AV_LOG_ERROR,
2989 "Unable to send seek command on stream index %d at timestamp "
2990 "%"PRId64" with flags %08x\n",
2991 stream_index, timestamp, flags);
2992 return ret;
2993 }
2994 rt->flv_off = rt->flv_size;
2995 rt->state = STATE_SEEKING;
2996 return timestamp;
2997 }
2998
2999 static int rtmp_pause(void *opaque, int pause)
3000 {
3001 URLContext *s = opaque;
3002 RTMPContext *rt = s->priv_data;
3003 int ret;
3004 av_log(s, AV_LOG_DEBUG, "Pause at timestamp %d\n",
3005 rt->last_timestamp);
3006 if ((ret = gen_pause(s, rt, pause, rt->last_timestamp)) < 0) {
3007 av_log(s, AV_LOG_ERROR, "Unable to send pause command at timestamp %d\n",
3008 rt->last_timestamp);
3009 return ret;
3010 }
3011 return 0;
3012 }
3013
3014 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
3015 {
3016 RTMPContext *rt = s->priv_data;
3017 int size_temp = size;
3018 int pktsize, pkttype, copy;
3019 uint32_t ts;
3020 const uint8_t *buf_temp = buf;
3021 uint8_t c;
3022 int ret;
3023
3024 do {
3025 if (rt->skip_bytes) {
3026 int skip = FFMIN(rt->skip_bytes, size_temp);
3027 buf_temp += skip;
3028 size_temp -= skip;
3029 rt->skip_bytes -= skip;
3030 continue;
3031 }
3032
3033 if (rt->flv_header_bytes < RTMP_HEADER) {
3034 const uint8_t *header = rt->flv_header;
3035 int channel = RTMP_AUDIO_CHANNEL;
3036
3037 copy = FFMIN(RTMP_HEADER - rt->flv_header_bytes, size_temp);
3038 bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
3039 rt->flv_header_bytes += copy;
3040 size_temp -= copy;
3041 if (rt->flv_header_bytes < RTMP_HEADER)
3042 break;
3043
3044 pkttype = bytestream_get_byte(&header);
3045 pktsize = bytestream_get_be24(&header);
3046 ts = bytestream_get_be24(&header);
3047 ts |= bytestream_get_byte(&header) << 24;
3048 bytestream_get_be24(&header);
3049 rt->flv_size = pktsize;
3050
3051 if (pkttype == RTMP_PT_VIDEO)
3052 channel = RTMP_VIDEO_CHANNEL;
3053
3054 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
3055 pkttype == RTMP_PT_NOTIFY) {
3056 if ((ret = ff_rtmp_check_alloc_array(&rt->prev_pkt[1],
3057 &rt->nb_prev_pkt[1],
3058 channel)) < 0)
3059 return ret;
3060 // Force sending a full 12 bytes header by clearing the
3061 // channel id, to make it not match a potential earlier
3062 // packet in the same channel.
3063 rt->prev_pkt[1][channel].channel_id = 0;
3064 }
3065
3066 //this can be a big packet, it's better to send it right here
3067 if ((ret = ff_rtmp_packet_create(&rt->out_pkt, channel,
3068 pkttype, ts, pktsize)) < 0)
3069 return ret;
3070
3071 // If rt->listen, then we're running as a a server and should
3072 // use the ID that we've sent in Stream Begin and in the
3073 // _result to createStream.
3074 // Otherwise, we're running as a client and should use the ID
3075 // that we've received in the createStream from the server.
3076 rt->out_pkt.extra = (rt->listen) ? rt->nb_streamid : rt->stream_id;
3077 rt->flv_data = rt->out_pkt.data;
3078 }
3079
3080 copy = FFMIN(rt->flv_size - rt->flv_off, size_temp);
3081 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, copy);
3082 rt->flv_off += copy;
3083 size_temp -= copy;
3084
3085 if (rt->flv_off == rt->flv_size) {
3086 rt->skip_bytes = 4;
3087
3088 if (rt->out_pkt.type == RTMP_PT_NOTIFY) {
3089 // For onMetaData and |RtmpSampleAccess packets, we want
3090 // @setDataFrame prepended to the packet before it gets sent.
3091 // However, not all RTMP_PT_NOTIFY packets (e.g., onTextData
3092 // and onCuePoint).
3093 uint8_t commandbuffer[64];
3094 int stringlen = 0;
3095 GetByteContext gbc;
3096
3097 bytestream2_init(&gbc, rt->flv_data, rt->flv_size);
3098 if (!ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
3099 &stringlen)) {
3100 if (!strcmp(commandbuffer, "onMetaData") ||
3101 !strcmp(commandbuffer, "|RtmpSampleAccess")) {
3102 uint8_t *ptr;
3103 if ((ret = av_reallocp(&rt->out_pkt.data, rt->out_pkt.size + 16)) < 0) {
3104 rt->flv_size = rt->flv_off = rt->flv_header_bytes = 0;
3105 return ret;
3106 }
3107 memmove(rt->out_pkt.data + 16, rt->out_pkt.data, rt->out_pkt.size);
3108 rt->out_pkt.size += 16;
3109 ptr = rt->out_pkt.data;
3110 ff_amf_write_string(&ptr, "@setDataFrame");
3111 }
3112 }
3113 }
3114
3115 if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
3116 return ret;
3117 rt->flv_size = 0;
3118 rt->flv_off = 0;
3119 rt->flv_header_bytes = 0;
3120 rt->flv_nb_packets++;
3121 }
3122 } while (buf_temp - buf < size);
3123
3124 if (rt->flv_nb_packets < rt->flush_interval)
3125 return size;
3126 rt->flv_nb_packets = 0;
3127
3128 /* set stream into nonblocking mode */
3129 rt->stream->flags |= AVIO_FLAG_NONBLOCK;
3130
3131 /* try to read one byte from the stream */
3132 ret = ffurl_read(rt->stream, &c, 1);
3133
3134 /* switch the stream back into blocking mode */
3135 rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
3136
3137 if (ret == AVERROR(EAGAIN)) {
3138 /* no incoming data to handle */
3139 return size;
3140 } else if (ret < 0) {
3141 return ret;
3142 } else if (ret == 1) {
3143 RTMPPacket rpkt = { 0 };
3144
3145 if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
3146 rt->in_chunk_size,
3147 &rt->prev_pkt[0],
3148 &rt->nb_prev_pkt[0], c)) <= 0)
3149 return ret;
3150
3151 if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
3152 return ret;
3153
3154 ff_rtmp_packet_destroy(&rpkt);
3155 }
3156
3157 return size;
3158 }
3159
3160 #define OFFSET(x) offsetof(RTMPContext, x)
3161 #define DEC AV_OPT_FLAG_DECODING_PARAM
3162 #define ENC AV_OPT_FLAG_ENCODING_PARAM
3163
3164 static const AVOption rtmp_options[] = {
3165 {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
3166 {"rtmp_buffer", "Set buffer time in milliseconds. The default is 3000.", OFFSET(client_buffer_time), AV_OPT_TYPE_INT, {.i64 = 3000}, 0, INT_MAX, DEC|ENC},
3167 {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
3168 {"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},
3169 {"rtmp_flush_interval", "Number of packets flushed in the same request (RTMPT only).", OFFSET(flush_interval), AV_OPT_TYPE_INT, {.i64 = 10}, 0, INT_MAX, ENC},
3170 {"rtmp_enhanced_codecs", "Specify the codec(s) to use in an enhanced rtmp live stream", OFFSET(enhanced_codecs), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, ENC},
3171 {"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {.i64 = -2}, INT_MIN, INT_MAX, DEC, .unit = "rtmp_live"},
3172 {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, .unit = "rtmp_live"},
3173 {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, .unit = "rtmp_live"},
3174 {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, .unit = "rtmp_live"},
3175 {"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},
3176 {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
3177 {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
3178 {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
3179 {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
3180 {"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},
3181 {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
3182 {"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},
3183 {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, .unit = "rtmp_listen" },
3184 {"listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, .unit = "rtmp_listen" },
3185 {"tcp_nodelay", "Use TCP_NODELAY to disable Nagle's algorithm", OFFSET(tcp_nodelay), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC|ENC},
3186 {"timeout", "Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies -rtmp_listen 1", OFFSET(listen_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC, .unit = "rtmp_listen" },
3187 { NULL },
3188 };
3189
3190 #define RTMP_PROTOCOL_0(flavor)
3191 #define RTMP_PROTOCOL_1(flavor) \
3192 static const AVClass flavor##_class = { \
3193 .class_name = #flavor, \
3194 .item_name = av_default_item_name, \
3195 .option = rtmp_options, \
3196 .version = LIBAVUTIL_VERSION_INT, \
3197 }; \
3198 \
3199 const URLProtocol ff_##flavor##_protocol = { \
3200 .name = #flavor, \
3201 .url_open2 = rtmp_open, \
3202 .url_read = rtmp_read, \
3203 .url_read_seek = rtmp_seek, \
3204 .url_read_pause = rtmp_pause, \
3205 .url_write = rtmp_write, \
3206 .url_close = rtmp_close, \
3207 .priv_data_size = sizeof(RTMPContext), \
3208 .flags = URL_PROTOCOL_FLAG_NETWORK, \
3209 .priv_data_class= &flavor##_class, \
3210 };
3211 #define RTMP_PROTOCOL_2(flavor, enabled) \
3212 RTMP_PROTOCOL_ ## enabled(flavor)
3213 #define RTMP_PROTOCOL_3(flavor, config) \
3214 RTMP_PROTOCOL_2(flavor, config)
3215 #define RTMP_PROTOCOL(flavor, uppercase) \
3216 RTMP_PROTOCOL_3(flavor, CONFIG_ ## uppercase ## _PROTOCOL)
3217
3218 RTMP_PROTOCOL(rtmp, RTMP)
3219 RTMP_PROTOCOL(rtmpe, RTMPE)
3220 RTMP_PROTOCOL(rtmps, RTMPS)
3221 RTMP_PROTOCOL(rtmpt, RTMPT)
3222 RTMP_PROTOCOL(rtmpte, RTMPTE)
3223 RTMP_PROTOCOL(rtmpts, RTMPTS)
3224