FFmpeg coverage


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