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