FFmpeg coverage


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