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