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