]> git.sesse.net Git - ffmpeg/blob - libavformat/rtmpproto.c
rtmp: Add support for receiving incoming streams
[ffmpeg] / libavformat / rtmpproto.c
1 /*
2  * RTMP network protocol
3  * Copyright (c) 2009 Kostya 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/intfloat.h"
30 #include "libavutil/lfg.h"
31 #include "libavutil/opt.h"
32 #include "libavutil/random_seed.h"
33 #include "libavutil/sha.h"
34 #include "avformat.h"
35 #include "internal.h"
36
37 #include "network.h"
38
39 #include "flv.h"
40 #include "rtmp.h"
41 #include "rtmpcrypt.h"
42 #include "rtmppkt.h"
43 #include "url.h"
44
45 #if CONFIG_ZLIB
46 #include <zlib.h>
47 #endif
48
49 //#define DEBUG
50
51 #define APP_MAX_LENGTH 128
52 #define PLAYPATH_MAX_LENGTH 256
53 #define TCURL_MAX_LENGTH 512
54 #define FLASHVER_MAX_LENGTH 64
55 #define RTMP_PKTDATA_DEFAULT_SIZE 4096
56
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_PUBLISHING, ///< client has started sending multimedia data to server (for output)
64     STATE_RECEIVING,  ///< received a publish command (for input)
65     STATE_STOPPED,    ///< the broadcast has been stopped
66 } ClientState;
67
68 typedef struct TrackedMethod {
69     char *name;
70     int id;
71 } TrackedMethod;
72
73 /** protocol handler context */
74 typedef struct RTMPContext {
75     const AVClass *class;
76     URLContext*   stream;                     ///< TCP stream used in interactions with RTMP server
77     RTMPPacket    prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets
78     int           in_chunk_size;              ///< size of the chunks incoming RTMP packets are divided into
79     int           out_chunk_size;             ///< size of the chunks outgoing RTMP packets are divided into
80     int           is_input;                   ///< input/output flag
81     char          *playpath;                  ///< stream identifier to play (with possible "mp4:" prefix)
82     int           live;                       ///< 0: recorded, -1: live, -2: both
83     char          *app;                       ///< name of application
84     char          *conn;                      ///< append arbitrary AMF data to the Connect message
85     ClientState   state;                      ///< current state
86     int           main_channel_id;            ///< an additional channel ID which is used for some invocations
87     uint8_t*      flv_data;                   ///< buffer with data for demuxer
88     int           flv_size;                   ///< current buffer size
89     int           flv_off;                    ///< number of bytes read from current buffer
90     int           flv_nb_packets;             ///< number of flv packets published
91     RTMPPacket    out_pkt;                    ///< rtmp packet, created from flv a/v or metadata (for output)
92     uint32_t      client_report_size;         ///< number of bytes after which client should report to server
93     uint32_t      bytes_read;                 ///< number of bytes read from server
94     uint32_t      last_bytes_read;            ///< number of bytes read last reported to server
95     int           skip_bytes;                 ///< number of bytes to skip from the input FLV stream in the next write call
96     uint8_t       flv_header[11];             ///< partial incoming flv packet header
97     int           flv_header_bytes;           ///< number of initialized bytes in flv_header
98     int           nb_invokes;                 ///< keeps track of invoke messages
99     char*         tcurl;                      ///< url of the target stream
100     char*         flashver;                   ///< version of the flash plugin
101     char*         swfhash;                    ///< SHA256 hash of the decompressed SWF file (32 bytes)
102     int           swfhash_len;                ///< length of the SHA256 hash
103     int           swfsize;                    ///< size of the decompressed SWF file
104     char*         swfurl;                     ///< url of the swf player
105     char*         swfverify;                  ///< URL to player swf file, compute hash/size automatically
106     char          swfverification[42];        ///< hash of the SWF verification
107     char*         pageurl;                    ///< url of the web page
108     char*         subscribe;                  ///< name of live stream to subscribe
109     int           server_bw;                  ///< server bandwidth
110     int           client_buffer_time;         ///< client buffer time in ms
111     int           flush_interval;             ///< number of packets flushed in the same request (RTMPT only)
112     int           encrypted;                  ///< use an encrypted connection (RTMPE only)
113     TrackedMethod*tracked_methods;            ///< tracked methods buffer
114     int           nb_tracked_methods;         ///< number of tracked methods
115     int           tracked_methods_size;       ///< size of the tracked methods buffer
116     int           listen;                     ///< listen mode flag
117     int           listen_timeout;             ///< listen timeout to wait for new connections
118     int           nb_streamid;                ///< The next stream id to return on createStream calls
119 } RTMPContext;
120
121 #define PLAYER_KEY_OPEN_PART_LEN 30   ///< length of partial key used for first client digest signing
122 /** Client key used for digest signing */
123 static const uint8_t rtmp_player_key[] = {
124     'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
125     'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
126
127     0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
128     0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
129     0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
130 };
131
132 #define SERVER_KEY_OPEN_PART_LEN 36   ///< length of partial key used for first server digest signing
133 /** Key used for RTMP server digest signing */
134 static const uint8_t rtmp_server_key[] = {
135     'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
136     'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
137     'S', 'e', 'r', 'v', '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 static int add_tracked_method(RTMPContext *rt, const char *name, int id)
145 {
146     void *ptr;
147
148     if (rt->nb_tracked_methods + 1 > rt->tracked_methods_size) {
149         rt->tracked_methods_size = (rt->nb_tracked_methods + 1) * 2;
150         ptr = av_realloc(rt->tracked_methods,
151                          rt->tracked_methods_size * sizeof(*rt->tracked_methods));
152         if (!ptr)
153             return AVERROR(ENOMEM);
154         rt->tracked_methods = ptr;
155     }
156
157     rt->tracked_methods[rt->nb_tracked_methods].name = av_strdup(name);
158     if (!rt->tracked_methods[rt->nb_tracked_methods].name)
159         return AVERROR(ENOMEM);
160     rt->tracked_methods[rt->nb_tracked_methods].id = id;
161     rt->nb_tracked_methods++;
162
163     return 0;
164 }
165
166 static void del_tracked_method(RTMPContext *rt, int index)
167 {
168     memmove(&rt->tracked_methods[index], &rt->tracked_methods[index + 1],
169             sizeof(*rt->tracked_methods) * (rt->nb_tracked_methods - index - 1));
170     rt->nb_tracked_methods--;
171 }
172
173 static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset,
174                                char **tracked_method)
175 {
176     RTMPContext *rt = s->priv_data;
177     GetByteContext gbc;
178     double pkt_id;
179     int ret;
180     int i;
181
182     bytestream2_init(&gbc, pkt->data + offset, pkt->data_size - offset);
183     if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
184         return ret;
185
186     for (i = 0; i < rt->nb_tracked_methods; i++) {
187         if (rt->tracked_methods[i].id != pkt_id)
188             continue;
189
190         *tracked_method = rt->tracked_methods[i].name;
191         del_tracked_method(rt, i);
192         break;
193     }
194
195     return 0;
196 }
197
198 static void free_tracked_methods(RTMPContext *rt)
199 {
200     int i;
201
202     for (i = 0; i < rt->nb_tracked_methods; i ++)
203         av_free(rt->tracked_methods[i].name);
204     av_free(rt->tracked_methods);
205 }
206
207 static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
208 {
209     int ret;
210
211     if (pkt->type == RTMP_PT_INVOKE && track) {
212         GetByteContext gbc;
213         char name[128];
214         double pkt_id;
215         int len;
216
217         bytestream2_init(&gbc, pkt->data, pkt->data_size);
218         if ((ret = ff_amf_read_string(&gbc, name, sizeof(name), &len)) < 0)
219             goto fail;
220
221         if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
222             goto fail;
223
224         if ((ret = add_tracked_method(rt, name, pkt_id)) < 0)
225             goto fail;
226     }
227
228     ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
229                                rt->prev_pkt[1]);
230 fail:
231     ff_rtmp_packet_destroy(pkt);
232     return ret;
233 }
234
235 static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
236 {
237     char *field, *value;
238     char type;
239
240     /* The type must be B for Boolean, N for number, S for string, O for
241      * object, or Z for null. For Booleans the data must be either 0 or 1 for
242      * FALSE or TRUE, respectively. Likewise for Objects the data must be
243      * 0 or 1 to end or begin an object, respectively. Data items in subobjects
244      * may be named, by prefixing the type with 'N' and specifying the name
245      * before the value (ie. NB:myFlag:1). This option may be used multiple times
246      * to construct arbitrary AMF sequences. */
247     if (param[0] && param[1] == ':') {
248         type = param[0];
249         value = param + 2;
250     } else if (param[0] == 'N' && param[1] && param[2] == ':') {
251         type = param[1];
252         field = param + 3;
253         value = strchr(field, ':');
254         if (!value)
255             goto fail;
256         *value = '\0';
257         value++;
258
259         if (!field || !value)
260             goto fail;
261
262         ff_amf_write_field_name(p, field);
263     } else {
264         goto fail;
265     }
266
267     switch (type) {
268     case 'B':
269         ff_amf_write_bool(p, value[0] != '0');
270         break;
271     case 'S':
272         ff_amf_write_string(p, value);
273         break;
274     case 'N':
275         ff_amf_write_number(p, strtod(value, NULL));
276         break;
277     case 'Z':
278         ff_amf_write_null(p);
279         break;
280     case 'O':
281         if (value[0] != '0')
282             ff_amf_write_object_start(p);
283         else
284             ff_amf_write_object_end(p);
285         break;
286     default:
287         goto fail;
288         break;
289     }
290
291     return 0;
292
293 fail:
294     av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
295     return AVERROR(EINVAL);
296 }
297
298 /**
299  * Generate 'connect' call and send it to the server.
300  */
301 static int gen_connect(URLContext *s, RTMPContext *rt)
302 {
303     RTMPPacket pkt;
304     uint8_t *p;
305     int ret;
306
307     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
308                                      0, 4096)) < 0)
309         return ret;
310
311     p = pkt.data;
312
313     ff_amf_write_string(&p, "connect");
314     ff_amf_write_number(&p, ++rt->nb_invokes);
315     ff_amf_write_object_start(&p);
316     ff_amf_write_field_name(&p, "app");
317     ff_amf_write_string(&p, rt->app);
318
319     if (!rt->is_input) {
320         ff_amf_write_field_name(&p, "type");
321         ff_amf_write_string(&p, "nonprivate");
322     }
323     ff_amf_write_field_name(&p, "flashVer");
324     ff_amf_write_string(&p, rt->flashver);
325
326     if (rt->swfurl) {
327         ff_amf_write_field_name(&p, "swfUrl");
328         ff_amf_write_string(&p, rt->swfurl);
329     }
330
331     ff_amf_write_field_name(&p, "tcUrl");
332     ff_amf_write_string(&p, rt->tcurl);
333     if (rt->is_input) {
334         ff_amf_write_field_name(&p, "fpad");
335         ff_amf_write_bool(&p, 0);
336         ff_amf_write_field_name(&p, "capabilities");
337         ff_amf_write_number(&p, 15.0);
338
339         /* Tell the server we support all the audio codecs except
340          * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
341          * which are unused in the RTMP protocol implementation. */
342         ff_amf_write_field_name(&p, "audioCodecs");
343         ff_amf_write_number(&p, 4071.0);
344         ff_amf_write_field_name(&p, "videoCodecs");
345         ff_amf_write_number(&p, 252.0);
346         ff_amf_write_field_name(&p, "videoFunction");
347         ff_amf_write_number(&p, 1.0);
348
349         if (rt->pageurl) {
350             ff_amf_write_field_name(&p, "pageUrl");
351             ff_amf_write_string(&p, rt->pageurl);
352         }
353     }
354     ff_amf_write_object_end(&p);
355
356     if (rt->conn) {
357         char *param = rt->conn;
358
359         // Write arbitrary AMF data to the Connect message.
360         while (param != NULL) {
361             char *sep;
362             param += strspn(param, " ");
363             if (!*param)
364                 break;
365             sep = strchr(param, ' ');
366             if (sep)
367                 *sep = '\0';
368             if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
369                 // Invalid AMF parameter.
370                 ff_rtmp_packet_destroy(&pkt);
371                 return ret;
372             }
373
374             if (sep)
375                 param = sep + 1;
376             else
377                 break;
378         }
379     }
380
381     pkt.data_size = p - pkt.data;
382
383     return rtmp_send_packet(rt, &pkt, 1);
384 }
385
386 static int read_connect(URLContext *s, RTMPContext *rt)
387 {
388     RTMPPacket pkt = { 0 };
389     uint8_t *p;
390     const uint8_t *cp;
391     int ret;
392     char command[64];
393     int stringlen;
394     double seqnum;
395     uint8_t tmpstr[256];
396     GetByteContext gbc;
397
398     if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
399                                    rt->prev_pkt[1])) < 0)
400         return ret;
401     cp = pkt.data;
402     bytestream2_init(&gbc, cp, pkt.data_size);
403     if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) {
404         av_log(s, AV_LOG_ERROR, "Unable to read command string\n");
405         ff_rtmp_packet_destroy(&pkt);
406         return AVERROR_INVALIDDATA;
407     }
408     if (strcmp(command, "connect")) {
409         av_log(s, AV_LOG_ERROR, "Expecting connect, got %s\n", command);
410         ff_rtmp_packet_destroy(&pkt);
411         return AVERROR_INVALIDDATA;
412     }
413     ret = ff_amf_read_number(&gbc, &seqnum);
414     if (ret)
415         av_log(s, AV_LOG_WARNING, "SeqNum not found\n");
416     /* Here one could parse an AMF Object with data as flashVers and others. */
417     ret = ff_amf_get_field_value(gbc.buffer,
418                                  gbc.buffer + bytestream2_get_bytes_left(&gbc),
419                                  "app", tmpstr, sizeof(tmpstr));
420     if (ret)
421         av_log(s, AV_LOG_WARNING, "App field not found in connect\n");
422     if (!ret && strcmp(tmpstr, rt->app))
423         av_log(s, AV_LOG_WARNING, "App field don't match up: %s <-> %s\n",
424                tmpstr, rt->app);
425     ff_rtmp_packet_destroy(&pkt);
426
427     // Send Window Acknowledgement Size (as defined in speficication)
428     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
429                                      RTMP_PT_SERVER_BW, 0, 4)) < 0)
430         return ret;
431     p = pkt.data;
432     bytestream_put_be32(&p, rt->server_bw);
433     pkt.data_size = p - pkt.data;
434     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
435                                rt->prev_pkt[1]);
436     ff_rtmp_packet_destroy(&pkt);
437     if (ret < 0)
438         return ret;
439     // Send Peer Bandwidth
440     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
441                                      RTMP_PT_CLIENT_BW, 0, 5)) < 0)
442         return ret;
443     p = pkt.data;
444     bytestream_put_be32(&p, rt->server_bw);
445     bytestream_put_byte(&p, 2); // dynamic
446     pkt.data_size = p - pkt.data;
447     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
448                                rt->prev_pkt[1]);
449     ff_rtmp_packet_destroy(&pkt);
450     if (ret < 0)
451         return ret;
452
453     // Ping request
454     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
455                                      RTMP_PT_PING, 0, 6)) < 0)
456         return ret;
457
458     p = pkt.data;
459     bytestream_put_be16(&p, 0); // 0 -> Stream Begin
460     bytestream_put_be32(&p, 0);
461     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
462                                rt->prev_pkt[1]);
463     ff_rtmp_packet_destroy(&pkt);
464     if (ret < 0)
465         return ret;
466
467     // Chunk size
468     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
469                                      RTMP_PT_CHUNK_SIZE, 0, 4)) < 0)
470         return ret;
471
472     p = pkt.data;
473     bytestream_put_be32(&p, rt->out_chunk_size);
474     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
475                                rt->prev_pkt[1]);
476     ff_rtmp_packet_destroy(&pkt);
477     if (ret < 0)
478         return ret;
479
480     // Send result_ NetConnection.Connect.Success to connect
481     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
482                                      RTMP_PT_INVOKE, 0,
483                                      RTMP_PKTDATA_DEFAULT_SIZE)) < 0)
484         return ret;
485
486     p = pkt.data;
487     ff_amf_write_string(&p, "_result");
488     ff_amf_write_number(&p, seqnum);
489
490     ff_amf_write_object_start(&p);
491     ff_amf_write_field_name(&p, "fmsVer");
492     ff_amf_write_string(&p, "FMS/3,0,1,123");
493     ff_amf_write_field_name(&p, "capabilities");
494     ff_amf_write_number(&p, 31);
495     ff_amf_write_object_end(&p);
496
497     ff_amf_write_object_start(&p);
498     ff_amf_write_field_name(&p, "level");
499     ff_amf_write_string(&p, "status");
500     ff_amf_write_field_name(&p, "code");
501     ff_amf_write_string(&p, "NetConnection.Connect.Success");
502     ff_amf_write_field_name(&p, "description");
503     ff_amf_write_string(&p, "Connection succeeded.");
504     ff_amf_write_field_name(&p, "objectEncoding");
505     ff_amf_write_number(&p, 0);
506     ff_amf_write_object_end(&p);
507
508     pkt.data_size = p - pkt.data;
509     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
510                                rt->prev_pkt[1]);
511     ff_rtmp_packet_destroy(&pkt);
512     if (ret < 0)
513         return ret;
514
515     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
516                                      RTMP_PT_INVOKE, 0, 30)) < 0)
517         return ret;
518     p = pkt.data;
519     ff_amf_write_string(&p, "onBWDone");
520     ff_amf_write_number(&p, 0);
521     ff_amf_write_null(&p);
522     ff_amf_write_number(&p, 8192);
523     pkt.data_size = p - pkt.data;
524     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
525                                rt->prev_pkt[1]);
526     ff_rtmp_packet_destroy(&pkt);
527
528     return ret;
529 }
530
531 /**
532  * Generate 'releaseStream' call and send it to the server. It should make
533  * the server release some channel for media streams.
534  */
535 static int gen_release_stream(URLContext *s, RTMPContext *rt)
536 {
537     RTMPPacket pkt;
538     uint8_t *p;
539     int ret;
540
541     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
542                                      0, 29 + strlen(rt->playpath))) < 0)
543         return ret;
544
545     av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
546     p = pkt.data;
547     ff_amf_write_string(&p, "releaseStream");
548     ff_amf_write_number(&p, ++rt->nb_invokes);
549     ff_amf_write_null(&p);
550     ff_amf_write_string(&p, rt->playpath);
551
552     return rtmp_send_packet(rt, &pkt, 0);
553 }
554
555 /**
556  * Generate 'FCPublish' call and send it to the server. It should make
557  * the server preapare for receiving media streams.
558  */
559 static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
560 {
561     RTMPPacket pkt;
562     uint8_t *p;
563     int ret;
564
565     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
566                                      0, 25 + strlen(rt->playpath))) < 0)
567         return ret;
568
569     av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
570     p = pkt.data;
571     ff_amf_write_string(&p, "FCPublish");
572     ff_amf_write_number(&p, ++rt->nb_invokes);
573     ff_amf_write_null(&p);
574     ff_amf_write_string(&p, rt->playpath);
575
576     return rtmp_send_packet(rt, &pkt, 0);
577 }
578
579 /**
580  * Generate 'FCUnpublish' call and send it to the server. It should make
581  * the server destroy stream.
582  */
583 static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
584 {
585     RTMPPacket pkt;
586     uint8_t *p;
587     int ret;
588
589     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
590                                      0, 27 + strlen(rt->playpath))) < 0)
591         return ret;
592
593     av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
594     p = pkt.data;
595     ff_amf_write_string(&p, "FCUnpublish");
596     ff_amf_write_number(&p, ++rt->nb_invokes);
597     ff_amf_write_null(&p);
598     ff_amf_write_string(&p, rt->playpath);
599
600     return rtmp_send_packet(rt, &pkt, 0);
601 }
602
603 /**
604  * Generate 'createStream' call and send it to the server. It should make
605  * the server allocate some channel for media streams.
606  */
607 static int gen_create_stream(URLContext *s, RTMPContext *rt)
608 {
609     RTMPPacket pkt;
610     uint8_t *p;
611     int ret;
612
613     av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
614
615     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
616                                      0, 25)) < 0)
617         return ret;
618
619     p = pkt.data;
620     ff_amf_write_string(&p, "createStream");
621     ff_amf_write_number(&p, ++rt->nb_invokes);
622     ff_amf_write_null(&p);
623
624     return rtmp_send_packet(rt, &pkt, 1);
625 }
626
627
628 /**
629  * Generate 'deleteStream' call and send it to the server. It should make
630  * the server remove some channel for media streams.
631  */
632 static int gen_delete_stream(URLContext *s, RTMPContext *rt)
633 {
634     RTMPPacket pkt;
635     uint8_t *p;
636     int ret;
637
638     av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
639
640     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
641                                      0, 34)) < 0)
642         return ret;
643
644     p = pkt.data;
645     ff_amf_write_string(&p, "deleteStream");
646     ff_amf_write_number(&p, ++rt->nb_invokes);
647     ff_amf_write_null(&p);
648     ff_amf_write_number(&p, rt->main_channel_id);
649
650     return rtmp_send_packet(rt, &pkt, 0);
651 }
652
653 /**
654  * Generate client buffer time and send it to the server.
655  */
656 static int gen_buffer_time(URLContext *s, RTMPContext *rt)
657 {
658     RTMPPacket pkt;
659     uint8_t *p;
660     int ret;
661
662     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
663                                      1, 10)) < 0)
664         return ret;
665
666     p = pkt.data;
667     bytestream_put_be16(&p, 3);
668     bytestream_put_be32(&p, rt->main_channel_id);
669     bytestream_put_be32(&p, rt->client_buffer_time);
670
671     return rtmp_send_packet(rt, &pkt, 0);
672 }
673
674 /**
675  * Generate 'play' call and send it to the server, then ping the server
676  * to start actual playing.
677  */
678 static int gen_play(URLContext *s, RTMPContext *rt)
679 {
680     RTMPPacket pkt;
681     uint8_t *p;
682     int ret;
683
684     av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
685
686     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE,
687                                      0, 29 + strlen(rt->playpath))) < 0)
688         return ret;
689
690     pkt.extra = rt->main_channel_id;
691
692     p = pkt.data;
693     ff_amf_write_string(&p, "play");
694     ff_amf_write_number(&p, ++rt->nb_invokes);
695     ff_amf_write_null(&p);
696     ff_amf_write_string(&p, rt->playpath);
697     ff_amf_write_number(&p, rt->live);
698
699     return rtmp_send_packet(rt, &pkt, 1);
700 }
701
702 /**
703  * Generate 'publish' call and send it to the server.
704  */
705 static int gen_publish(URLContext *s, RTMPContext *rt)
706 {
707     RTMPPacket pkt;
708     uint8_t *p;
709     int ret;
710
711     av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
712
713     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
714                                      0, 30 + strlen(rt->playpath))) < 0)
715         return ret;
716
717     pkt.extra = rt->main_channel_id;
718
719     p = pkt.data;
720     ff_amf_write_string(&p, "publish");
721     ff_amf_write_number(&p, ++rt->nb_invokes);
722     ff_amf_write_null(&p);
723     ff_amf_write_string(&p, rt->playpath);
724     ff_amf_write_string(&p, "live");
725
726     return rtmp_send_packet(rt, &pkt, 1);
727 }
728
729 /**
730  * Generate ping reply and send it to the server.
731  */
732 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
733 {
734     RTMPPacket pkt;
735     uint8_t *p;
736     int ret;
737
738     if (ppkt->data_size < 6) {
739         av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
740                ppkt->data_size);
741         return AVERROR_INVALIDDATA;
742     }
743
744     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
745                                      ppkt->timestamp + 1, 6)) < 0)
746         return ret;
747
748     p = pkt.data;
749     bytestream_put_be16(&p, 7);
750     bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
751
752     return rtmp_send_packet(rt, &pkt, 0);
753 }
754
755 /**
756  * Generate SWF verification message and send it to the server.
757  */
758 static int gen_swf_verification(URLContext *s, RTMPContext *rt)
759 {
760     RTMPPacket pkt;
761     uint8_t *p;
762     int ret;
763
764     av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
765     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
766                                      0, 44)) < 0)
767         return ret;
768
769     p = pkt.data;
770     bytestream_put_be16(&p, 27);
771     memcpy(p, rt->swfverification, 42);
772
773     return rtmp_send_packet(rt, &pkt, 0);
774 }
775
776 /**
777  * Generate server bandwidth message and send it to the server.
778  */
779 static int gen_server_bw(URLContext *s, RTMPContext *rt)
780 {
781     RTMPPacket pkt;
782     uint8_t *p;
783     int ret;
784
785     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
786                                      0, 4)) < 0)
787         return ret;
788
789     p = pkt.data;
790     bytestream_put_be32(&p, rt->server_bw);
791
792     return rtmp_send_packet(rt, &pkt, 0);
793 }
794
795 /**
796  * Generate check bandwidth message and send it to the server.
797  */
798 static int gen_check_bw(URLContext *s, RTMPContext *rt)
799 {
800     RTMPPacket pkt;
801     uint8_t *p;
802     int ret;
803
804     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
805                                      0, 21)) < 0)
806         return ret;
807
808     p = pkt.data;
809     ff_amf_write_string(&p, "_checkbw");
810     ff_amf_write_number(&p, ++rt->nb_invokes);
811     ff_amf_write_null(&p);
812
813     return rtmp_send_packet(rt, &pkt, 1);
814 }
815
816 /**
817  * Generate report on bytes read so far and send it to the server.
818  */
819 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
820 {
821     RTMPPacket pkt;
822     uint8_t *p;
823     int ret;
824
825     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
826                                      ts, 4)) < 0)
827         return ret;
828
829     p = pkt.data;
830     bytestream_put_be32(&p, rt->bytes_read);
831
832     return rtmp_send_packet(rt, &pkt, 0);
833 }
834
835 static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
836                                   const char *subscribe)
837 {
838     RTMPPacket pkt;
839     uint8_t *p;
840     int ret;
841
842     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
843                                      0, 27 + strlen(subscribe))) < 0)
844         return ret;
845
846     p = pkt.data;
847     ff_amf_write_string(&p, "FCSubscribe");
848     ff_amf_write_number(&p, ++rt->nb_invokes);
849     ff_amf_write_null(&p);
850     ff_amf_write_string(&p, subscribe);
851
852     return rtmp_send_packet(rt, &pkt, 1);
853 }
854
855 int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
856                         const uint8_t *key, int keylen, uint8_t *dst)
857 {
858     struct AVSHA *sha;
859     uint8_t hmac_buf[64+32] = {0};
860     int i;
861
862     sha = av_mallocz(av_sha_size);
863     if (!sha)
864         return AVERROR(ENOMEM);
865
866     if (keylen < 64) {
867         memcpy(hmac_buf, key, keylen);
868     } else {
869         av_sha_init(sha, 256);
870         av_sha_update(sha,key, keylen);
871         av_sha_final(sha, hmac_buf);
872     }
873     for (i = 0; i < 64; i++)
874         hmac_buf[i] ^= HMAC_IPAD_VAL;
875
876     av_sha_init(sha, 256);
877     av_sha_update(sha, hmac_buf, 64);
878     if (gap <= 0) {
879         av_sha_update(sha, src, len);
880     } else { //skip 32 bytes used for storing digest
881         av_sha_update(sha, src, gap);
882         av_sha_update(sha, src + gap + 32, len - gap - 32);
883     }
884     av_sha_final(sha, hmac_buf + 64);
885
886     for (i = 0; i < 64; i++)
887         hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
888     av_sha_init(sha, 256);
889     av_sha_update(sha, hmac_buf, 64+32);
890     av_sha_final(sha, dst);
891
892     av_free(sha);
893
894     return 0;
895 }
896
897 int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
898                             int add_val)
899 {
900     int i, digest_pos = 0;
901
902     for (i = 0; i < 4; i++)
903         digest_pos += buf[i + off];
904     digest_pos = digest_pos % mod_val + add_val;
905
906     return digest_pos;
907 }
908
909 /**
910  * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
911  * will be stored) into that packet.
912  *
913  * @param buf handshake data (1536 bytes)
914  * @param encrypted use an encrypted connection (RTMPE)
915  * @return offset to the digest inside input data
916  */
917 static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
918 {
919     int ret, digest_pos;
920
921     if (encrypted)
922         digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
923     else
924         digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
925
926     ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
927                               rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
928                               buf + digest_pos);
929     if (ret < 0)
930         return ret;
931
932     return digest_pos;
933 }
934
935 /**
936  * Verify that the received server response has the expected digest value.
937  *
938  * @param buf handshake data received from the server (1536 bytes)
939  * @param off position to search digest offset from
940  * @return 0 if digest is valid, digest position otherwise
941  */
942 static int rtmp_validate_digest(uint8_t *buf, int off)
943 {
944     uint8_t digest[32];
945     int ret, digest_pos;
946
947     digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
948
949     ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
950                               rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
951                               digest);
952     if (ret < 0)
953         return ret;
954
955     if (!memcmp(digest, buf + digest_pos, 32))
956         return digest_pos;
957     return 0;
958 }
959
960 static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
961                                       uint8_t *buf)
962 {
963     uint8_t *p;
964     int ret;
965
966     if (rt->swfhash_len != 32) {
967         av_log(s, AV_LOG_ERROR,
968                "Hash of the decompressed SWF file is not 32 bytes long.\n");
969         return AVERROR(EINVAL);
970     }
971
972     p = &rt->swfverification[0];
973     bytestream_put_byte(&p, 1);
974     bytestream_put_byte(&p, 1);
975     bytestream_put_be32(&p, rt->swfsize);
976     bytestream_put_be32(&p, rt->swfsize);
977
978     if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
979         return ret;
980
981     return 0;
982 }
983
984 #if CONFIG_ZLIB
985 static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
986                                      uint8_t **out_data, int64_t *out_size)
987 {
988     z_stream zs = { 0 };
989     void *ptr;
990     int size;
991     int ret = 0;
992
993     zs.avail_in = in_size;
994     zs.next_in  = in_data;
995     ret = inflateInit(&zs);
996     if (ret != Z_OK)
997         return AVERROR_UNKNOWN;
998
999     do {
1000         uint8_t tmp_buf[16384];
1001
1002         zs.avail_out = sizeof(tmp_buf);
1003         zs.next_out  = tmp_buf;
1004
1005         ret = inflate(&zs, Z_NO_FLUSH);
1006         if (ret != Z_OK && ret != Z_STREAM_END) {
1007             ret = AVERROR_UNKNOWN;
1008             goto fail;
1009         }
1010
1011         size = sizeof(tmp_buf) - zs.avail_out;
1012         if (!(ptr = av_realloc(*out_data, *out_size + size))) {
1013             ret = AVERROR(ENOMEM);
1014             goto fail;
1015         }
1016         *out_data = ptr;
1017
1018         memcpy(*out_data + *out_size, tmp_buf, size);
1019         *out_size += size;
1020     } while (zs.avail_out == 0);
1021
1022 fail:
1023     inflateEnd(&zs);
1024     return ret;
1025 }
1026 #endif
1027
1028 static int rtmp_calc_swfhash(URLContext *s)
1029 {
1030     RTMPContext *rt = s->priv_data;
1031     uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
1032     int64_t in_size, out_size;
1033     URLContext *stream;
1034     char swfhash[32];
1035     int swfsize;
1036     int ret = 0;
1037
1038     /* Get the SWF player file. */
1039     if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
1040                           &s->interrupt_callback, NULL)) < 0) {
1041         av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1042         goto fail;
1043     }
1044
1045     if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
1046         ret = AVERROR(EIO);
1047         goto fail;
1048     }
1049
1050     if (!(in_data = av_malloc(in_size))) {
1051         ret = AVERROR(ENOMEM);
1052         goto fail;
1053     }
1054
1055     if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
1056         goto fail;
1057
1058     if (in_size < 3) {
1059         ret = AVERROR_INVALIDDATA;
1060         goto fail;
1061     }
1062
1063     if (!memcmp(in_data, "CWS", 3)) {
1064         /* Decompress the SWF player file using Zlib. */
1065         if (!(out_data = av_malloc(8))) {
1066             ret = AVERROR(ENOMEM);
1067             goto fail;
1068         }
1069         *in_data = 'F'; // magic stuff
1070         memcpy(out_data, in_data, 8);
1071         out_size = 8;
1072
1073 #if CONFIG_ZLIB
1074         if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1075                                              &out_data, &out_size)) < 0)
1076             goto fail;
1077 #else
1078         av_log(s, AV_LOG_ERROR,
1079                "Zlib is required for decompressing the SWF player file.\n");
1080         ret = AVERROR(EINVAL);
1081         goto fail;
1082 #endif
1083         swfsize = out_size;
1084         swfdata = out_data;
1085     } else {
1086         swfsize = in_size;
1087         swfdata = in_data;
1088     }
1089
1090     /* Compute the SHA256 hash of the SWF player file. */
1091     if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
1092                                    "Genuine Adobe Flash Player 001", 30,
1093                                    swfhash)) < 0)
1094         goto fail;
1095
1096     /* Set SWFVerification parameters. */
1097     av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
1098     rt->swfsize = swfsize;
1099
1100 fail:
1101     av_freep(&in_data);
1102     av_freep(&out_data);
1103     ffurl_close(stream);
1104     return ret;
1105 }
1106
1107 /**
1108  * Perform handshake with the server by means of exchanging pseudorandom data
1109  * signed with HMAC-SHA2 digest.
1110  *
1111  * @return 0 if handshake succeeds, negative value otherwise
1112  */
1113 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
1114 {
1115     AVLFG rnd;
1116     uint8_t tosend    [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
1117         3,                // unencrypted data
1118         0, 0, 0, 0,       // client uptime
1119         RTMP_CLIENT_VER1,
1120         RTMP_CLIENT_VER2,
1121         RTMP_CLIENT_VER3,
1122         RTMP_CLIENT_VER4,
1123     };
1124     uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1125     uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1126     int i;
1127     int server_pos, client_pos;
1128     uint8_t digest[32], signature[32];
1129     int ret, type = 0;
1130
1131     av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1132
1133     av_lfg_init(&rnd, 0xDEADC0DE);
1134     // generate handshake packet - 1536 bytes of pseudorandom data
1135     for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1136         tosend[i] = av_lfg_get(&rnd) >> 24;
1137
1138     if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1139         /* When the client wants to use RTMPE, we have to change the command
1140          * byte to 0x06 which means to use encrypted data and we have to set
1141          * the flash version to at least 9.0.115.0. */
1142         tosend[0] = 6;
1143         tosend[5] = 128;
1144         tosend[6] = 0;
1145         tosend[7] = 3;
1146         tosend[8] = 2;
1147
1148         /* Initialize the Diffie-Hellmann context and generate the public key
1149          * to send to the server. */
1150         if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1151             return ret;
1152     }
1153
1154     client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1155     if (client_pos < 0)
1156         return client_pos;
1157
1158     if ((ret = ffurl_write(rt->stream, tosend,
1159                            RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1160         av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1161         return ret;
1162     }
1163
1164     if ((ret = ffurl_read_complete(rt->stream, serverdata,
1165                                    RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1166         av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1167         return ret;
1168     }
1169
1170     if ((ret = ffurl_read_complete(rt->stream, clientdata,
1171                                    RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
1172         av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1173         return ret;
1174     }
1175
1176     av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1177     av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1178            serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1179
1180     if (rt->is_input && serverdata[5] >= 3) {
1181         server_pos = rtmp_validate_digest(serverdata + 1, 772);
1182         if (server_pos < 0)
1183             return server_pos;
1184
1185         if (!server_pos) {
1186             type = 1;
1187             server_pos = rtmp_validate_digest(serverdata + 1, 8);
1188             if (server_pos < 0)
1189                 return server_pos;
1190
1191             if (!server_pos) {
1192                 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1193                 return AVERROR(EIO);
1194             }
1195         }
1196
1197         /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1198          * key are the last 32 bytes of the server handshake. */
1199         if (rt->swfsize) {
1200             if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1201                                                   RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1202                 return ret;
1203         }
1204
1205         ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1206                                   rtmp_server_key, sizeof(rtmp_server_key),
1207                                   digest);
1208         if (ret < 0)
1209             return ret;
1210
1211         ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1212                                   0, digest, 32, signature);
1213         if (ret < 0)
1214             return ret;
1215
1216         if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1217             /* Compute the shared secret key sent by the server and initialize
1218              * the RC4 encryption. */
1219             if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1220                                                    tosend + 1, type)) < 0)
1221                 return ret;
1222
1223             /* Encrypt the signature received by the server. */
1224             ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1225         }
1226
1227         if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1228             av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1229             return AVERROR(EIO);
1230         }
1231
1232         for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1233             tosend[i] = av_lfg_get(&rnd) >> 24;
1234         ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1235                                   rtmp_player_key, sizeof(rtmp_player_key),
1236                                   digest);
1237         if (ret < 0)
1238             return ret;
1239
1240         ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1241                                   digest, 32,
1242                                   tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1243         if (ret < 0)
1244             return ret;
1245
1246         if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1247             /* Encrypt the signature to be send to the server. */
1248             ff_rtmpe_encrypt_sig(rt->stream, tosend +
1249                                  RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1250                                  serverdata[0]);
1251         }
1252
1253         // write reply back to the server
1254         if ((ret = ffurl_write(rt->stream, tosend,
1255                                RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1256             return ret;
1257
1258         if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1259             /* Set RC4 keys for encryption and update the keystreams. */
1260             if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1261                 return ret;
1262         }
1263     } else {
1264         if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1265             /* Compute the shared secret key sent by the server and initialize
1266              * the RC4 encryption. */
1267             if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1268                             tosend + 1, 1)) < 0)
1269                 return ret;
1270
1271             if (serverdata[0] == 9) {
1272                 /* Encrypt the signature received by the server. */
1273                 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1274                                      serverdata[0]);
1275             }
1276         }
1277
1278         if ((ret = ffurl_write(rt->stream, serverdata + 1,
1279                                RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1280             return ret;
1281
1282         if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1283             /* Set RC4 keys for encryption and update the keystreams. */
1284             if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1285                 return ret;
1286         }
1287     }
1288
1289     return 0;
1290 }
1291
1292 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1293                                   uint32_t *second_int, char *arraydata,
1294                                   int size)
1295 {
1296     ssize_t inoutsize;
1297
1298     inoutsize = ffurl_read_complete(rt->stream, arraydata,
1299                                     RTMP_HANDSHAKE_PACKET_SIZE);
1300     if (inoutsize <= 0)
1301         return AVERROR(EIO);
1302     if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1303         av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1304                " not following standard\n", (int)inoutsize);
1305         return AVERROR(EINVAL);
1306     }
1307
1308     *first_int  = AV_RB32(arraydata);
1309     *second_int = AV_RB32(arraydata + 4);
1310     return 0;
1311 }
1312
1313 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1314                                uint32_t second_int, char *arraydata, int size)
1315 {
1316     ssize_t inoutsize;
1317
1318     AV_WB32(arraydata, first_int);
1319     AV_WB32(arraydata + 4, first_int);
1320     inoutsize = ffurl_write(rt->stream, arraydata,
1321                             RTMP_HANDSHAKE_PACKET_SIZE);
1322     if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1323         av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1324         return AVERROR(EIO);
1325     }
1326
1327     return 0;
1328 }
1329
1330 /**
1331  * rtmp handshake server side
1332  */
1333 static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
1334 {
1335     uint8_t buffer[RTMP_HANDSHAKE_PACKET_SIZE];
1336     uint32_t hs_epoch;
1337     uint32_t hs_my_epoch;
1338     uint8_t hs_c1[RTMP_HANDSHAKE_PACKET_SIZE];
1339     uint8_t hs_s1[RTMP_HANDSHAKE_PACKET_SIZE];
1340     uint32_t zeroes;
1341     uint32_t temp       = 0;
1342     int randomidx       = 0;
1343     ssize_t inoutsize   = 0;
1344     int ret;
1345
1346     inoutsize = ffurl_read_complete(rt->stream, buffer, 1);       // Receive C0
1347     if (inoutsize <= 0) {
1348         av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1349         return AVERROR(EIO);
1350     }
1351     // Check Version
1352     if (buffer[0] != 3) {
1353         av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1354         return AVERROR(EIO);
1355     }
1356     if (ffurl_write(rt->stream, buffer, 1) <= 0) {                 // Send S0
1357         av_log(s, AV_LOG_ERROR,
1358                "Unable to write answer - RTMP S0\n");
1359         return AVERROR(EIO);
1360     }
1361     /* Receive C1 */
1362     ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1363                                  RTMP_HANDSHAKE_PACKET_SIZE);
1364     if (ret) {
1365         av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1366         return ret;
1367     }
1368     if (zeroes)
1369         av_log(s, AV_LOG_WARNING, "Erroneous C1 Message zero != 0\n");
1370     /* Send S1 */
1371     /* By now same epoch will be sent */
1372     hs_my_epoch = hs_epoch;
1373     /* Generate random */
1374     for (randomidx = 0; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1375          randomidx += 4)
1376         AV_WB32(hs_s1 + 8 + randomidx, av_get_random_seed());
1377
1378     ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1379                               RTMP_HANDSHAKE_PACKET_SIZE);
1380     if (ret) {
1381         av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1382         return ret;
1383     }
1384     /* Send S2 */
1385     ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1386                               RTMP_HANDSHAKE_PACKET_SIZE);
1387     if (ret) {
1388         av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1389         return ret;
1390     }
1391     /* Receive C2 */
1392     ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1393                                  RTMP_HANDSHAKE_PACKET_SIZE);
1394     if (ret) {
1395         av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1396         return ret;
1397     }
1398     if (temp != hs_my_epoch)
1399         av_log(s, AV_LOG_WARNING,
1400                "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1401     if (memcmp(buffer + 8, hs_s1 + 8,
1402                RTMP_HANDSHAKE_PACKET_SIZE - 8))
1403         av_log(s, AV_LOG_WARNING,
1404                "Erroneous C2 Message random does not match up\n");
1405
1406     return 0;
1407 }
1408
1409 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1410 {
1411     RTMPContext *rt = s->priv_data;
1412     int ret;
1413
1414     if (pkt->data_size < 4) {
1415         av_log(s, AV_LOG_ERROR,
1416                "Too short chunk size change packet (%d)\n",
1417                pkt->data_size);
1418         return AVERROR_INVALIDDATA;
1419     }
1420
1421     if (!rt->is_input) {
1422         /* Send the same chunk size change packet back to the server,
1423          * setting the outgoing chunk size to the same as the incoming one. */
1424         if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1425                                         rt->prev_pkt[1])) < 0)
1426             return ret;
1427         rt->out_chunk_size = AV_RB32(pkt->data);
1428     }
1429
1430     rt->in_chunk_size = AV_RB32(pkt->data);
1431     if (rt->in_chunk_size <= 0) {
1432         av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1433                rt->in_chunk_size);
1434         return AVERROR_INVALIDDATA;
1435     }
1436     av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1437            rt->in_chunk_size);
1438
1439     return 0;
1440 }
1441
1442 static int handle_ping(URLContext *s, RTMPPacket *pkt)
1443 {
1444     RTMPContext *rt = s->priv_data;
1445     int t, ret;
1446
1447     if (pkt->data_size < 2) {
1448         av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
1449                pkt->data_size);
1450         return AVERROR_INVALIDDATA;
1451     }
1452
1453     t = AV_RB16(pkt->data);
1454     if (t == 6) {
1455         if ((ret = gen_pong(s, rt, pkt)) < 0)
1456             return ret;
1457     } else if (t == 26) {
1458         if (rt->swfsize) {
1459             if ((ret = gen_swf_verification(s, rt)) < 0)
1460                 return ret;
1461         } else {
1462             av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1463         }
1464     }
1465
1466     return 0;
1467 }
1468
1469 static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
1470 {
1471     RTMPContext *rt = s->priv_data;
1472
1473     if (pkt->data_size < 4) {
1474         av_log(s, AV_LOG_ERROR,
1475                "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1476                pkt->data_size);
1477         return AVERROR_INVALIDDATA;
1478     }
1479
1480     rt->client_report_size = AV_RB32(pkt->data);
1481     if (rt->client_report_size <= 0) {
1482         av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
1483                 rt->client_report_size);
1484         return AVERROR_INVALIDDATA;
1485
1486     }
1487     av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
1488     rt->client_report_size >>= 1;
1489
1490     return 0;
1491 }
1492
1493 static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
1494 {
1495     RTMPContext *rt = s->priv_data;
1496
1497     if (pkt->data_size < 4) {
1498         av_log(s, AV_LOG_ERROR,
1499                "Too short server bandwidth report packet (%d)\n",
1500                pkt->data_size);
1501         return AVERROR_INVALIDDATA;
1502     }
1503
1504     rt->server_bw = AV_RB32(pkt->data);
1505     if (rt->server_bw <= 0) {
1506         av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
1507                rt->server_bw);
1508         return AVERROR_INVALIDDATA;
1509     }
1510     av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
1511
1512     return 0;
1513 }
1514
1515 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1516 {
1517     const uint8_t *data_end = pkt->data + pkt->data_size;
1518     char *tracked_method = NULL;
1519     int level = AV_LOG_ERROR;
1520     uint8_t tmpstr[256];
1521     int ret;
1522
1523     if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1524         return ret;
1525
1526     if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1527                                 "description", tmpstr, sizeof(tmpstr))) {
1528         if (tracked_method && !strcmp(tracked_method, "_checkbw")) {
1529             /* Ignore _checkbw errors. */
1530             level = AV_LOG_WARNING;
1531             ret = 0;
1532         } else
1533             ret = -1;
1534         av_log(s, level, "Server error: %s\n", tmpstr);
1535     }
1536
1537     av_free(tracked_method);
1538     return ret;
1539 }
1540
1541 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1542 {
1543     RTMPContext *rt = s->priv_data;
1544     double seqnum;
1545     char filename[64];
1546     char command[64];
1547     char statusmsg[128];
1548     int stringlen;
1549     char *pchar;
1550     const uint8_t *p = pkt->data;
1551     uint8_t *pp      = NULL;
1552     RTMPPacket spkt  = { 0 };
1553     GetByteContext gbc;
1554     int ret;
1555
1556     bytestream2_init(&gbc, p, pkt->data_size);
1557     if (ff_amf_read_string(&gbc, command, sizeof(command),
1558                            &stringlen)) {
1559         av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1560         return AVERROR_INVALIDDATA;
1561     }
1562
1563     ret = ff_amf_read_number(&gbc, &seqnum);
1564     if (ret)
1565         return ret;
1566     ret = ff_amf_read_null(&gbc);
1567     if (ret)
1568         return ret;
1569     if (!strcmp(command, "FCPublish") ||
1570         !strcmp(command, "publish")) {
1571         ret = ff_amf_read_string(&gbc, filename,
1572                                  sizeof(filename), &stringlen);
1573         // check with url
1574         if (s->filename) {
1575             pchar = strrchr(s->filename, '/');
1576             if (!pchar) {
1577                 av_log(s, AV_LOG_WARNING,
1578                        "Unable to find / in url %s, bad format\n",
1579                        s->filename);
1580                 pchar = s->filename;
1581             }
1582             pchar++;
1583             if (strcmp(pchar, filename))
1584                 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1585                        " %s\n", filename, pchar);
1586         }
1587         rt->state = STATE_RECEIVING;
1588     }
1589
1590     if (!strcmp(command, "FCPublish")) {
1591         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1592                                          RTMP_PT_INVOKE, 0,
1593                                          RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1594             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1595             return ret;
1596         }
1597         pp = spkt.data;
1598         ff_amf_write_string(&pp, "onFCPublish");
1599     } else if (!strcmp(command, "publish")) {
1600         PutByteContext pbc;
1601         // Send Stream Begin 1
1602         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1603                                          RTMP_PT_PING, 0, 6)) < 0) {
1604             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1605             return ret;
1606         }
1607         pp = spkt.data;
1608         bytestream2_init_writer(&pbc, pp, spkt.data_size);
1609         bytestream2_put_be16(&pbc, 0);          // 0 -> Stream Begin
1610         bytestream2_put_be32(&pbc, rt->nb_streamid);
1611         ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1612                                    rt->prev_pkt[1]);
1613         ff_rtmp_packet_destroy(&spkt);
1614         if (ret < 0)
1615             return ret;
1616
1617         // Send onStatus(NetStream.Publish.Start)
1618         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1619                                          RTMP_PT_INVOKE, 0,
1620                                          RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1621             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1622             return ret;
1623         }
1624         spkt.extra = pkt->extra;
1625         pp = spkt.data;
1626         ff_amf_write_string(&pp, "onStatus");
1627         ff_amf_write_number(&pp, 0);
1628         ff_amf_write_null(&pp);
1629
1630         ff_amf_write_object_start(&pp);
1631         ff_amf_write_field_name(&pp, "level");
1632         ff_amf_write_string(&pp, "status");
1633         ff_amf_write_field_name(&pp, "code");
1634         ff_amf_write_string(&pp, "NetStream.Publish.Start");
1635         ff_amf_write_field_name(&pp, "description");
1636         snprintf(statusmsg, sizeof(statusmsg),
1637                  "%s is now published", filename);
1638         ff_amf_write_string(&pp, statusmsg);
1639         ff_amf_write_field_name(&pp, "details");
1640         ff_amf_write_string(&pp, filename);
1641         ff_amf_write_field_name(&pp, "clientid");
1642         snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1643         ff_amf_write_string(&pp, statusmsg);
1644         ff_amf_write_object_end(&pp);
1645
1646     } else {
1647         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1648                                          RTMP_PT_INVOKE, 0,
1649                                          RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1650             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1651             return ret;
1652         }
1653         pp = spkt.data;
1654         ff_amf_write_string(&pp, "_result");
1655         ff_amf_write_number(&pp, seqnum);
1656         ff_amf_write_null(&pp);
1657         if (!strcmp(command, "createStream")) {
1658             rt->nb_streamid++;
1659             if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1660                 rt->nb_streamid++; /* Values 0 and 2 are reserved */
1661             ff_amf_write_number(&pp, rt->nb_streamid);
1662             /* By now we don't control which streams are removed in
1663              * deleteStream. There is no stream creation control
1664              * if a client creates more than 2^32 - 2 streams. */
1665         }
1666     }
1667     spkt.data_size = pp - spkt.data;
1668     ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1669                                rt->prev_pkt[1]);
1670     ff_rtmp_packet_destroy(&spkt);
1671     return ret;
1672 }
1673
1674 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1675 {
1676     RTMPContext *rt = s->priv_data;
1677     char *tracked_method = NULL;
1678     int ret = 0;
1679
1680     if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1681         return ret;
1682
1683     if (!tracked_method) {
1684         /* Ignore this reply when the current method is not tracked. */
1685         return ret;
1686     }
1687
1688     if (!memcmp(tracked_method, "connect", 7)) {
1689         if (!rt->is_input) {
1690             if ((ret = gen_release_stream(s, rt)) < 0)
1691                 goto fail;
1692
1693             if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1694                 goto fail;
1695         } else {
1696             if ((ret = gen_server_bw(s, rt)) < 0)
1697                 goto fail;
1698         }
1699
1700         if ((ret = gen_create_stream(s, rt)) < 0)
1701             goto fail;
1702
1703         if (rt->is_input) {
1704             /* Send the FCSubscribe command when the name of live
1705              * stream is defined by the user or if it's a live stream. */
1706             if (rt->subscribe) {
1707                 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1708                     goto fail;
1709             } else if (rt->live == -1) {
1710                 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1711                     goto fail;
1712             }
1713         }
1714     } else if (!memcmp(tracked_method, "createStream", 12)) {
1715         //extract a number from the result
1716         if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1717             av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
1718         } else {
1719             rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
1720         }
1721
1722         if (!rt->is_input) {
1723             if ((ret = gen_publish(s, rt)) < 0)
1724                 goto fail;
1725         } else {
1726             if ((ret = gen_play(s, rt)) < 0)
1727                 goto fail;
1728             if ((ret = gen_buffer_time(s, rt)) < 0)
1729                 goto fail;
1730         }
1731     }
1732
1733 fail:
1734     av_free(tracked_method);
1735     return ret;
1736 }
1737
1738 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
1739 {
1740     RTMPContext *rt = s->priv_data;
1741     const uint8_t *data_end = pkt->data + pkt->data_size;
1742     const uint8_t *ptr = pkt->data + 11;
1743     uint8_t tmpstr[256];
1744     int i, t;
1745
1746     for (i = 0; i < 2; i++) {
1747         t = ff_amf_tag_size(ptr, data_end);
1748         if (t < 0)
1749             return 1;
1750         ptr += t;
1751     }
1752
1753     t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
1754     if (!t && !strcmp(tmpstr, "error")) {
1755         if (!ff_amf_get_field_value(ptr, data_end,
1756                                     "description", tmpstr, sizeof(tmpstr)))
1757             av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
1758         return -1;
1759     }
1760
1761     t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
1762     if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
1763     if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
1764     if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
1765     if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
1766
1767     return 0;
1768 }
1769
1770 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
1771 {
1772     RTMPContext *rt = s->priv_data;
1773     int ret = 0;
1774
1775     //TODO: check for the messages sent for wrong state?
1776     if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
1777         if ((ret = handle_invoke_error(s, pkt)) < 0)
1778             return ret;
1779     } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
1780         if ((ret = handle_invoke_result(s, pkt)) < 0)
1781             return ret;
1782     } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
1783         if ((ret = handle_invoke_status(s, pkt)) < 0)
1784             return ret;
1785     } else if (!memcmp(pkt->data, "\002\000\010onBWDone", 11)) {
1786         if ((ret = gen_check_bw(s, rt)) < 0)
1787             return ret;
1788     } else if (!memcmp(pkt->data, "\002\000\015releaseStream", 16) ||
1789                !memcmp(pkt->data, "\002\000\011FCPublish", 12)     ||
1790                !memcmp(pkt->data, "\002\000\007publish", 10)       ||
1791                !memcmp(pkt->data, "\002\000\010_checkbw", 11)      ||
1792                !memcmp(pkt->data, "\002\000\014createStream", 15)) {
1793         if (ret = send_invoke_response(s, pkt) < 0)
1794             return ret;
1795     }
1796
1797     return ret;
1798 }
1799
1800 static int handle_notify(URLContext *s, RTMPPacket *pkt) {
1801     RTMPContext *rt  = s->priv_data;
1802     const uint8_t *p = NULL;
1803     uint8_t *cp      = NULL;
1804     uint8_t commandbuffer[64];
1805     char statusmsg[128];
1806     int stringlen;
1807     GetByteContext gbc;
1808     PutByteContext pbc;
1809     uint32_t ts;
1810     int old_flv_size;
1811     const uint8_t *datatowrite;
1812     unsigned datatowritelength;
1813
1814     p = pkt->data;
1815     bytestream2_init(&gbc, p, pkt->data_size);
1816     if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
1817                            &stringlen))
1818         return AVERROR_INVALIDDATA;
1819     if (!strcmp(commandbuffer, "@setDataFrame")) {
1820         datatowrite       = gbc.buffer;
1821         datatowritelength = bytestream2_get_bytes_left(&gbc);
1822         if (ff_amf_read_string(&gbc, statusmsg,
1823                                sizeof(statusmsg), &stringlen))
1824             return AVERROR_INVALIDDATA;
1825         if (strcmp(statusmsg, "onMetaData")) {
1826             av_log(s, AV_LOG_INFO, "Expecting onMetadata but got %s\n",
1827                    statusmsg);
1828             return 0;
1829         }
1830
1831         /* Provide ECMAArray to flv */
1832         ts = pkt->timestamp;
1833
1834         // generate packet header and put data into buffer for FLV demuxer
1835         if (rt->flv_off < rt->flv_size) {
1836             old_flv_size  = rt->flv_size;
1837             rt->flv_size += datatowritelength + 15;
1838         } else {
1839             old_flv_size = 0;
1840             rt->flv_size = datatowritelength + 15;
1841             rt->flv_off  = 0;
1842         }
1843
1844         cp = av_realloc(rt->flv_data, rt->flv_size);
1845         if (!cp)
1846             return AVERROR(ENOMEM);
1847         rt->flv_data = cp;
1848         bytestream2_init_writer(&pbc, cp, rt->flv_size);
1849         bytestream2_skip_p(&pbc, old_flv_size);
1850         bytestream2_put_byte(&pbc, pkt->type);
1851         bytestream2_put_be24(&pbc, datatowritelength);
1852         bytestream2_put_be24(&pbc, ts);
1853         bytestream2_put_byte(&pbc, ts >> 24);
1854         bytestream2_put_be24(&pbc, 0);
1855         bytestream2_put_buffer(&pbc, datatowrite, datatowritelength);
1856         bytestream2_put_be32(&pbc, 0);
1857     }
1858     return 0;
1859 }
1860
1861 /**
1862  * Parse received packet and possibly perform some action depending on
1863  * the packet contents.
1864  * @return 0 for no errors, negative values for serious errors which prevent
1865  *         further communications, positive values for uncritical errors
1866  */
1867 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
1868 {
1869     int ret;
1870
1871 #ifdef DEBUG
1872     ff_rtmp_packet_dump(s, pkt);
1873 #endif
1874
1875     switch (pkt->type) {
1876     case RTMP_PT_BYTES_READ:
1877         av_dlog(s, "received bytes read report\n");
1878         break;
1879     case RTMP_PT_CHUNK_SIZE:
1880         if ((ret = handle_chunk_size(s, pkt)) < 0)
1881             return ret;
1882         break;
1883     case RTMP_PT_PING:
1884         if ((ret = handle_ping(s, pkt)) < 0)
1885             return ret;
1886         break;
1887     case RTMP_PT_CLIENT_BW:
1888         if ((ret = handle_client_bw(s, pkt)) < 0)
1889             return ret;
1890         break;
1891     case RTMP_PT_SERVER_BW:
1892         if ((ret = handle_server_bw(s, pkt)) < 0)
1893             return ret;
1894         break;
1895     case RTMP_PT_INVOKE:
1896         if ((ret = handle_invoke(s, pkt)) < 0)
1897             return ret;
1898         break;
1899     case RTMP_PT_VIDEO:
1900     case RTMP_PT_AUDIO:
1901     case RTMP_PT_METADATA:
1902     case RTMP_PT_NOTIFY:
1903         /* Audio, Video and Metadata packets are parsed in get_packet() */
1904         break;
1905     default:
1906         av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
1907         break;
1908     }
1909     return 0;
1910 }
1911
1912 /**
1913  * Interact with the server by receiving and sending RTMP packets until
1914  * there is some significant data (media data or expected status notification).
1915  *
1916  * @param s          reading context
1917  * @param for_header non-zero value tells function to work until it
1918  * gets notification from the server that playing has been started,
1919  * otherwise function will work until some media data is received (or
1920  * an error happens)
1921  * @return 0 for successful operation, negative value in case of error
1922  */
1923 static int get_packet(URLContext *s, int for_header)
1924 {
1925     RTMPContext *rt = s->priv_data;
1926     int ret;
1927     uint8_t *p;
1928     const uint8_t *next;
1929     uint32_t data_size;
1930     uint32_t ts, cts, pts=0;
1931
1932     if (rt->state == STATE_STOPPED)
1933         return AVERROR_EOF;
1934
1935     for (;;) {
1936         RTMPPacket rpkt = { 0 };
1937         if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
1938                                        rt->in_chunk_size, rt->prev_pkt[0])) <= 0) {
1939             if (ret == 0) {
1940                 return AVERROR(EAGAIN);
1941             } else {
1942                 return AVERROR(EIO);
1943             }
1944         }
1945         rt->bytes_read += ret;
1946         if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
1947             av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
1948             if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
1949                 return ret;
1950             rt->last_bytes_read = rt->bytes_read;
1951         }
1952
1953         ret = rtmp_parse_result(s, rt, &rpkt);
1954         if (ret < 0) {//serious error in current packet
1955             ff_rtmp_packet_destroy(&rpkt);
1956             return ret;
1957         }
1958         if (rt->state == STATE_STOPPED) {
1959             ff_rtmp_packet_destroy(&rpkt);
1960             return AVERROR_EOF;
1961         }
1962         if (for_header && (rt->state == STATE_PLAYING    ||
1963                            rt->state == STATE_PUBLISHING ||
1964                            rt->state == STATE_RECEIVING)) {
1965             ff_rtmp_packet_destroy(&rpkt);
1966             return 0;
1967         }
1968         if (!rpkt.data_size || !rt->is_input) {
1969             ff_rtmp_packet_destroy(&rpkt);
1970             continue;
1971         }
1972         if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
1973            (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
1974             ts = rpkt.timestamp;
1975
1976             // generate packet header and put data into buffer for FLV demuxer
1977             rt->flv_off  = 0;
1978             rt->flv_size = rpkt.data_size + 15;
1979             rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
1980             bytestream_put_byte(&p, rpkt.type);
1981             bytestream_put_be24(&p, rpkt.data_size);
1982             bytestream_put_be24(&p, ts);
1983             bytestream_put_byte(&p, ts >> 24);
1984             bytestream_put_be24(&p, 0);
1985             bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);
1986             bytestream_put_be32(&p, 0);
1987             ff_rtmp_packet_destroy(&rpkt);
1988             return 0;
1989         } else if (rpkt.type == RTMP_PT_NOTIFY) {
1990             ret = handle_notify(s, &rpkt);
1991             ff_rtmp_packet_destroy(&rpkt);
1992             if (ret) {
1993                 av_log(s, AV_LOG_ERROR, "Handle notify error\n");
1994                 return ret;
1995             }
1996             return 0;
1997         } else if (rpkt.type == RTMP_PT_METADATA) {
1998             // we got raw FLV data, make it available for FLV demuxer
1999             rt->flv_off  = 0;
2000             rt->flv_size = rpkt.data_size;
2001             rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2002             /* rewrite timestamps */
2003             next = rpkt.data;
2004             ts = rpkt.timestamp;
2005             while (next - rpkt.data < rpkt.data_size - 11) {
2006                 next++;
2007                 data_size = bytestream_get_be24(&next);
2008                 p=next;
2009                 cts = bytestream_get_be24(&next);
2010                 cts |= bytestream_get_byte(&next) << 24;
2011                 if (pts==0)
2012                     pts=cts;
2013                 ts += cts - pts;
2014                 pts = cts;
2015                 bytestream_put_be24(&p, ts);
2016                 bytestream_put_byte(&p, ts >> 24);
2017                 next += data_size + 3 + 4;
2018             }
2019             memcpy(rt->flv_data, rpkt.data, rpkt.data_size);
2020             ff_rtmp_packet_destroy(&rpkt);
2021             return 0;
2022         }
2023         ff_rtmp_packet_destroy(&rpkt);
2024     }
2025 }
2026
2027 static int rtmp_close(URLContext *h)
2028 {
2029     RTMPContext *rt = h->priv_data;
2030     int ret = 0;
2031
2032     if (!rt->is_input) {
2033         rt->flv_data = NULL;
2034         if (rt->out_pkt.data_size)
2035             ff_rtmp_packet_destroy(&rt->out_pkt);
2036         if (rt->state > STATE_FCPUBLISH)
2037             ret = gen_fcunpublish_stream(h, rt);
2038     }
2039     if (rt->state > STATE_HANDSHAKED)
2040         ret = gen_delete_stream(h, rt);
2041
2042     free_tracked_methods(rt);
2043     av_freep(&rt->flv_data);
2044     ffurl_close(rt->stream);
2045     return ret;
2046 }
2047
2048 /**
2049  * Open RTMP connection and verify that the stream can be played.
2050  *
2051  * URL syntax: rtmp://server[:port][/app][/playpath]
2052  *             where 'app' is first one or two directories in the path
2053  *             (e.g. /ondemand/, /flash/live/, etc.)
2054  *             and 'playpath' is a file name (the rest of the path,
2055  *             may be prefixed with "mp4:")
2056  */
2057 static int rtmp_open(URLContext *s, const char *uri, int flags)
2058 {
2059     RTMPContext *rt = s->priv_data;
2060     char proto[8], hostname[256], path[1024], *fname;
2061     char *old_app;
2062     uint8_t buf[2048];
2063     int port;
2064     AVDictionary *opts = NULL;
2065     int ret;
2066
2067     if (rt->listen_timeout > 0)
2068         rt->listen = 1;
2069
2070     rt->is_input = !(flags & AVIO_FLAG_WRITE);
2071
2072     av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
2073                  path, sizeof(path), s->filename);
2074
2075     if (rt->listen && strcmp(proto, "rtmp")) {
2076         av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2077                proto);
2078         return AVERROR(EINVAL);
2079     }
2080     if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2081         if (!strcmp(proto, "rtmpts"))
2082             av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2083
2084         /* open the http tunneling connection */
2085         ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2086     } else if (!strcmp(proto, "rtmps")) {
2087         /* open the tls connection */
2088         if (port < 0)
2089             port = RTMPS_DEFAULT_PORT;
2090         ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2091     } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2092         if (!strcmp(proto, "rtmpte"))
2093             av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2094
2095         /* open the encrypted connection */
2096         ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2097         rt->encrypted = 1;
2098     } else {
2099         /* open the tcp connection */
2100         if (port < 0)
2101             port = RTMP_DEFAULT_PORT;
2102         if (rt->listen)
2103             ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2104                         "?listen&listen_timeout=%d",
2105                         rt->listen_timeout * 1000);
2106         else
2107             ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2108     }
2109
2110     if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2111                           &s->interrupt_callback, &opts)) < 0) {
2112         av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2113         goto fail;
2114     }
2115
2116     if (rt->swfverify) {
2117         if ((ret = rtmp_calc_swfhash(s)) < 0)
2118             goto fail;
2119     }
2120
2121     rt->state = STATE_START;
2122     if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2123         goto fail;
2124     if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2125         goto fail;
2126
2127     rt->out_chunk_size = 128;
2128     rt->in_chunk_size  = 128; // Probably overwritten later
2129     rt->state = STATE_HANDSHAKED;
2130
2131     // Keep the application name when it has been defined by the user.
2132     old_app = rt->app;
2133
2134     rt->app = av_malloc(APP_MAX_LENGTH);
2135     if (!rt->app) {
2136         ret = AVERROR(ENOMEM);
2137         goto fail;
2138     }
2139
2140     //extract "app" part from path
2141     if (!strncmp(path, "/ondemand/", 10)) {
2142         fname = path + 10;
2143         memcpy(rt->app, "ondemand", 9);
2144     } else {
2145         char *next = *path ? path + 1 : path;
2146         char *p = strchr(next, '/');
2147         if (!p) {
2148             fname = next;
2149             rt->app[0] = '\0';
2150         } else {
2151             // make sure we do not mismatch a playpath for an application instance
2152             char *c = strchr(p + 1, ':');
2153             fname = strchr(p + 1, '/');
2154             if (!fname || (c && c < fname)) {
2155                 fname = p + 1;
2156                 av_strlcpy(rt->app, path + 1, p - path);
2157             } else {
2158                 fname++;
2159                 av_strlcpy(rt->app, path + 1, fname - path - 1);
2160             }
2161         }
2162     }
2163
2164     if (old_app) {
2165         // The name of application has been defined by the user, override it.
2166         av_free(rt->app);
2167         rt->app = old_app;
2168     }
2169
2170     if (!rt->playpath) {
2171         int len = strlen(fname);
2172
2173         rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2174         if (!rt->playpath) {
2175             ret = AVERROR(ENOMEM);
2176             goto fail;
2177         }
2178
2179         if (!strchr(fname, ':') && len >= 4 &&
2180             (!strcmp(fname + len - 4, ".f4v") ||
2181              !strcmp(fname + len - 4, ".mp4"))) {
2182             memcpy(rt->playpath, "mp4:", 5);
2183         } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
2184             fname[len - 4] = '\0';
2185         } else {
2186             rt->playpath[0] = 0;
2187         }
2188         strncat(rt->playpath, fname, PLAYPATH_MAX_LENGTH - 5);
2189     }
2190
2191     if (!rt->tcurl) {
2192         rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2193         if (!rt->tcurl) {
2194             ret = AVERROR(ENOMEM);
2195             goto fail;
2196         }
2197         ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2198                     port, "/%s", rt->app);
2199     }
2200
2201     if (!rt->flashver) {
2202         rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2203         if (!rt->flashver) {
2204             ret = AVERROR(ENOMEM);
2205             goto fail;
2206         }
2207         if (rt->is_input) {
2208             snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2209                     RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2210                     RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2211         } else {
2212             snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2213                     "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2214         }
2215     }
2216
2217     rt->client_report_size = 1048576;
2218     rt->bytes_read = 0;
2219     rt->last_bytes_read = 0;
2220     rt->server_bw = 2500000;
2221
2222     av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2223            proto, path, rt->app, rt->playpath);
2224     if (!rt->listen) {
2225         if ((ret = gen_connect(s, rt)) < 0)
2226             goto fail;
2227     } else {
2228         if (read_connect(s, s->priv_data) < 0)
2229             goto fail;
2230         rt->is_input = 1;
2231     }
2232
2233     do {
2234         ret = get_packet(s, 1);
2235     } while (ret == EAGAIN);
2236     if (ret < 0)
2237         goto fail;
2238
2239     if (rt->is_input) {
2240         // generate FLV header for demuxer
2241         rt->flv_size = 13;
2242         rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2243         rt->flv_off  = 0;
2244         memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
2245     } else {
2246         rt->flv_size = 0;
2247         rt->flv_data = NULL;
2248         rt->flv_off  = 0;
2249         rt->skip_bytes = 13;
2250     }
2251
2252     s->max_packet_size = rt->stream->max_packet_size;
2253     s->is_streamed     = 1;
2254     return 0;
2255
2256 fail:
2257     av_dict_free(&opts);
2258     rtmp_close(s);
2259     return ret;
2260 }
2261
2262 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2263 {
2264     RTMPContext *rt = s->priv_data;
2265     int orig_size = size;
2266     int ret;
2267
2268     while (size > 0) {
2269         int data_left = rt->flv_size - rt->flv_off;
2270
2271         if (data_left >= size) {
2272             memcpy(buf, rt->flv_data + rt->flv_off, size);
2273             rt->flv_off += size;
2274             return orig_size;
2275         }
2276         if (data_left > 0) {
2277             memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2278             buf  += data_left;
2279             size -= data_left;
2280             rt->flv_off = rt->flv_size;
2281             return data_left;
2282         }
2283         if ((ret = get_packet(s, 0)) < 0)
2284            return ret;
2285     }
2286     return orig_size;
2287 }
2288
2289 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2290 {
2291     RTMPContext *rt = s->priv_data;
2292     int size_temp = size;
2293     int pktsize, pkttype;
2294     uint32_t ts;
2295     const uint8_t *buf_temp = buf;
2296     uint8_t c;
2297     int ret;
2298
2299     do {
2300         if (rt->skip_bytes) {
2301             int skip = FFMIN(rt->skip_bytes, size_temp);
2302             buf_temp       += skip;
2303             size_temp      -= skip;
2304             rt->skip_bytes -= skip;
2305             continue;
2306         }
2307
2308         if (rt->flv_header_bytes < 11) {
2309             const uint8_t *header = rt->flv_header;
2310             int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
2311             bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2312             rt->flv_header_bytes += copy;
2313             size_temp            -= copy;
2314             if (rt->flv_header_bytes < 11)
2315                 break;
2316
2317             pkttype = bytestream_get_byte(&header);
2318             pktsize = bytestream_get_be24(&header);
2319             ts = bytestream_get_be24(&header);
2320             ts |= bytestream_get_byte(&header) << 24;
2321             bytestream_get_be24(&header);
2322             rt->flv_size = pktsize;
2323
2324             //force 12bytes header
2325             if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2326                 pkttype == RTMP_PT_NOTIFY) {
2327                 if (pkttype == RTMP_PT_NOTIFY)
2328                     pktsize += 16;
2329                 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
2330             }
2331
2332             //this can be a big packet, it's better to send it right here
2333             if ((ret = ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL,
2334                                              pkttype, ts, pktsize)) < 0)
2335                 return ret;
2336
2337             rt->out_pkt.extra = rt->main_channel_id;
2338             rt->flv_data = rt->out_pkt.data;
2339
2340             if (pkttype == RTMP_PT_NOTIFY)
2341                 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2342         }
2343
2344         if (rt->flv_size - rt->flv_off > size_temp) {
2345             bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2346             rt->flv_off += size_temp;
2347             size_temp = 0;
2348         } else {
2349             bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2350             size_temp   -= rt->flv_size - rt->flv_off;
2351             rt->flv_off += rt->flv_size - rt->flv_off;
2352         }
2353
2354         if (rt->flv_off == rt->flv_size) {
2355             rt->skip_bytes = 4;
2356
2357             if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2358                 return ret;
2359             rt->flv_size = 0;
2360             rt->flv_off = 0;
2361             rt->flv_header_bytes = 0;
2362             rt->flv_nb_packets++;
2363         }
2364     } while (buf_temp - buf < size);
2365
2366     if (rt->flv_nb_packets < rt->flush_interval)
2367         return size;
2368     rt->flv_nb_packets = 0;
2369
2370     /* set stream into nonblocking mode */
2371     rt->stream->flags |= AVIO_FLAG_NONBLOCK;
2372
2373     /* try to read one byte from the stream */
2374     ret = ffurl_read(rt->stream, &c, 1);
2375
2376     /* switch the stream back into blocking mode */
2377     rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2378
2379     if (ret == AVERROR(EAGAIN)) {
2380         /* no incoming data to handle */
2381         return size;
2382     } else if (ret < 0) {
2383         return ret;
2384     } else if (ret == 1) {
2385         RTMPPacket rpkt = { 0 };
2386
2387         if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2388                                                 rt->in_chunk_size,
2389                                                 rt->prev_pkt[0], c)) <= 0)
2390              return ret;
2391
2392         if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2393             return ret;
2394
2395         ff_rtmp_packet_destroy(&rpkt);
2396     }
2397
2398     return size;
2399 }
2400
2401 #define OFFSET(x) offsetof(RTMPContext, x)
2402 #define DEC AV_OPT_FLAG_DECODING_PARAM
2403 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2404
2405 static const AVOption rtmp_options[] = {
2406     {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2407     {"rtmp_buffer", "Set buffer time in milliseconds. The default is 3000.", OFFSET(client_buffer_time), AV_OPT_TYPE_INT, {3000}, 0, INT_MAX, DEC|ENC},
2408     {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2409     {"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},
2410     {"rtmp_flush_interval", "Number of packets flushed in the same request (RTMPT only).", OFFSET(flush_interval), AV_OPT_TYPE_INT, {10}, 0, INT_MAX, ENC},
2411     {"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {-2}, INT_MIN, INT_MAX, DEC, "rtmp_live"},
2412     {"any", "both", 0, AV_OPT_TYPE_CONST, {-2}, 0, 0, DEC, "rtmp_live"},
2413     {"live", "live stream", 0, AV_OPT_TYPE_CONST, {-1}, 0, 0, DEC, "rtmp_live"},
2414     {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {0}, 0, 0, DEC, "rtmp_live"},
2415     {"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},
2416     {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2417     {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2418     {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2419     {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {0}, 0, INT_MAX, DEC},
2420     {"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},
2421     {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2422     {"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},
2423     {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2424     {"timeout", "Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies -rtmp_listen 1",  OFFSET(listen_timeout), AV_OPT_TYPE_INT, {-1}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2425     { NULL },
2426 };
2427
2428 #define RTMP_PROTOCOL(flavor)                    \
2429 static const AVClass flavor##_class = {          \
2430     .class_name = #flavor,                       \
2431     .item_name  = av_default_item_name,          \
2432     .option     = rtmp_options,                  \
2433     .version    = LIBAVUTIL_VERSION_INT,         \
2434 };                                               \
2435                                                  \
2436 URLProtocol ff_##flavor##_protocol = {           \
2437     .name           = #flavor,                   \
2438     .url_open       = rtmp_open,                 \
2439     .url_read       = rtmp_read,                 \
2440     .url_write      = rtmp_write,                \
2441     .url_close      = rtmp_close,                \
2442     .priv_data_size = sizeof(RTMPContext),       \
2443     .flags          = URL_PROTOCOL_FLAG_NETWORK, \
2444     .priv_data_class= &flavor##_class,           \
2445 };
2446
2447
2448 RTMP_PROTOCOL(rtmp)
2449 RTMP_PROTOCOL(rtmpe)
2450 RTMP_PROTOCOL(rtmps)
2451 RTMP_PROTOCOL(rtmpt)
2452 RTMP_PROTOCOL(rtmpte)
2453 RTMP_PROTOCOL(rtmpts)