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