]> git.sesse.net Git - ffmpeg/blob - libavformat/rtmpproto.c
rtmp: Return a proper error code in handle_invoke_error
[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, 1);
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, 1);
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_sha_alloc();
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     int 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     int 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     int 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 = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1375          randomidx += 4)
1376         AV_WB32(hs_s1 + 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                                !strcmp(tracked_method, "releaseStream") ||
1530                                !strcmp(tracked_method, "FCSubscribe")   ||
1531                                !strcmp(tracked_method, "FCPublish"))) {
1532             /* Gracefully ignore Adobe-specific historical artifact errors. */
1533             level = AV_LOG_WARNING;
1534             ret = 0;
1535         } else
1536             ret = AVERROR_UNKNOWN;
1537         av_log(s, level, "Server error: %s\n", tmpstr);
1538     }
1539
1540     av_free(tracked_method);
1541     return ret;
1542 }
1543
1544 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1545 {
1546     RTMPContext *rt = s->priv_data;
1547     double seqnum;
1548     char filename[64];
1549     char command[64];
1550     char statusmsg[128];
1551     int stringlen;
1552     char *pchar;
1553     const uint8_t *p = pkt->data;
1554     uint8_t *pp      = NULL;
1555     RTMPPacket spkt  = { 0 };
1556     GetByteContext gbc;
1557     int ret;
1558
1559     bytestream2_init(&gbc, p, pkt->data_size);
1560     if (ff_amf_read_string(&gbc, command, sizeof(command),
1561                            &stringlen)) {
1562         av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1563         return AVERROR_INVALIDDATA;
1564     }
1565
1566     ret = ff_amf_read_number(&gbc, &seqnum);
1567     if (ret)
1568         return ret;
1569     ret = ff_amf_read_null(&gbc);
1570     if (ret)
1571         return ret;
1572     if (!strcmp(command, "FCPublish") ||
1573         !strcmp(command, "publish")) {
1574         ret = ff_amf_read_string(&gbc, filename,
1575                                  sizeof(filename), &stringlen);
1576         // check with url
1577         if (s->filename) {
1578             pchar = strrchr(s->filename, '/');
1579             if (!pchar) {
1580                 av_log(s, AV_LOG_WARNING,
1581                        "Unable to find / in url %s, bad format\n",
1582                        s->filename);
1583                 pchar = s->filename;
1584             }
1585             pchar++;
1586             if (strcmp(pchar, filename))
1587                 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1588                        " %s\n", filename, pchar);
1589         }
1590         rt->state = STATE_RECEIVING;
1591     }
1592
1593     if (!strcmp(command, "FCPublish")) {
1594         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1595                                          RTMP_PT_INVOKE, 0,
1596                                          RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1597             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1598             return ret;
1599         }
1600         pp = spkt.data;
1601         ff_amf_write_string(&pp, "onFCPublish");
1602     } else if (!strcmp(command, "publish")) {
1603         PutByteContext pbc;
1604         // Send Stream Begin 1
1605         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1606                                          RTMP_PT_PING, 0, 6)) < 0) {
1607             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1608             return ret;
1609         }
1610         pp = spkt.data;
1611         bytestream2_init_writer(&pbc, pp, spkt.data_size);
1612         bytestream2_put_be16(&pbc, 0);          // 0 -> Stream Begin
1613         bytestream2_put_be32(&pbc, rt->nb_streamid);
1614         ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1615                                    rt->prev_pkt[1]);
1616         ff_rtmp_packet_destroy(&spkt);
1617         if (ret < 0)
1618             return ret;
1619
1620         // Send onStatus(NetStream.Publish.Start)
1621         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1622                                          RTMP_PT_INVOKE, 0,
1623                                          RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1624             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1625             return ret;
1626         }
1627         spkt.extra = pkt->extra;
1628         pp = spkt.data;
1629         ff_amf_write_string(&pp, "onStatus");
1630         ff_amf_write_number(&pp, 0);
1631         ff_amf_write_null(&pp);
1632
1633         ff_amf_write_object_start(&pp);
1634         ff_amf_write_field_name(&pp, "level");
1635         ff_amf_write_string(&pp, "status");
1636         ff_amf_write_field_name(&pp, "code");
1637         ff_amf_write_string(&pp, "NetStream.Publish.Start");
1638         ff_amf_write_field_name(&pp, "description");
1639         snprintf(statusmsg, sizeof(statusmsg),
1640                  "%s is now published", filename);
1641         ff_amf_write_string(&pp, statusmsg);
1642         ff_amf_write_field_name(&pp, "details");
1643         ff_amf_write_string(&pp, filename);
1644         ff_amf_write_field_name(&pp, "clientid");
1645         snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1646         ff_amf_write_string(&pp, statusmsg);
1647         ff_amf_write_object_end(&pp);
1648
1649     } else {
1650         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1651                                          RTMP_PT_INVOKE, 0,
1652                                          RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1653             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1654             return ret;
1655         }
1656         pp = spkt.data;
1657         ff_amf_write_string(&pp, "_result");
1658         ff_amf_write_number(&pp, seqnum);
1659         ff_amf_write_null(&pp);
1660         if (!strcmp(command, "createStream")) {
1661             rt->nb_streamid++;
1662             if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1663                 rt->nb_streamid++; /* Values 0 and 2 are reserved */
1664             ff_amf_write_number(&pp, rt->nb_streamid);
1665             /* By now we don't control which streams are removed in
1666              * deleteStream. There is no stream creation control
1667              * if a client creates more than 2^32 - 2 streams. */
1668         }
1669     }
1670     spkt.data_size = pp - spkt.data;
1671     ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1672                                rt->prev_pkt[1]);
1673     ff_rtmp_packet_destroy(&spkt);
1674     return ret;
1675 }
1676
1677 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1678 {
1679     RTMPContext *rt = s->priv_data;
1680     char *tracked_method = NULL;
1681     int ret = 0;
1682
1683     if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1684         return ret;
1685
1686     if (!tracked_method) {
1687         /* Ignore this reply when the current method is not tracked. */
1688         return ret;
1689     }
1690
1691     if (!memcmp(tracked_method, "connect", 7)) {
1692         if (!rt->is_input) {
1693             if ((ret = gen_release_stream(s, rt)) < 0)
1694                 goto fail;
1695
1696             if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1697                 goto fail;
1698         } else {
1699             if ((ret = gen_server_bw(s, rt)) < 0)
1700                 goto fail;
1701         }
1702
1703         if ((ret = gen_create_stream(s, rt)) < 0)
1704             goto fail;
1705
1706         if (rt->is_input) {
1707             /* Send the FCSubscribe command when the name of live
1708              * stream is defined by the user or if it's a live stream. */
1709             if (rt->subscribe) {
1710                 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1711                     goto fail;
1712             } else if (rt->live == -1) {
1713                 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1714                     goto fail;
1715             }
1716         }
1717     } else if (!memcmp(tracked_method, "createStream", 12)) {
1718         //extract a number from the result
1719         if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1720             av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
1721         } else {
1722             rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
1723         }
1724
1725         if (!rt->is_input) {
1726             if ((ret = gen_publish(s, rt)) < 0)
1727                 goto fail;
1728         } else {
1729             if ((ret = gen_play(s, rt)) < 0)
1730                 goto fail;
1731             if ((ret = gen_buffer_time(s, rt)) < 0)
1732                 goto fail;
1733         }
1734     }
1735
1736 fail:
1737     av_free(tracked_method);
1738     return ret;
1739 }
1740
1741 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
1742 {
1743     RTMPContext *rt = s->priv_data;
1744     const uint8_t *data_end = pkt->data + pkt->data_size;
1745     const uint8_t *ptr = pkt->data + 11;
1746     uint8_t tmpstr[256];
1747     int i, t;
1748
1749     for (i = 0; i < 2; i++) {
1750         t = ff_amf_tag_size(ptr, data_end);
1751         if (t < 0)
1752             return 1;
1753         ptr += t;
1754     }
1755
1756     t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
1757     if (!t && !strcmp(tmpstr, "error")) {
1758         if (!ff_amf_get_field_value(ptr, data_end,
1759                                     "description", tmpstr, sizeof(tmpstr)))
1760             av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
1761         return -1;
1762     }
1763
1764     t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
1765     if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
1766     if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
1767     if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
1768     if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
1769
1770     return 0;
1771 }
1772
1773 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
1774 {
1775     RTMPContext *rt = s->priv_data;
1776     int ret = 0;
1777
1778     //TODO: check for the messages sent for wrong state?
1779     if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
1780         if ((ret = handle_invoke_error(s, pkt)) < 0)
1781             return ret;
1782     } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
1783         if ((ret = handle_invoke_result(s, pkt)) < 0)
1784             return ret;
1785     } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
1786         if ((ret = handle_invoke_status(s, pkt)) < 0)
1787             return ret;
1788     } else if (!memcmp(pkt->data, "\002\000\010onBWDone", 11)) {
1789         if ((ret = gen_check_bw(s, rt)) < 0)
1790             return ret;
1791     } else if (!memcmp(pkt->data, "\002\000\015releaseStream", 16) ||
1792                !memcmp(pkt->data, "\002\000\011FCPublish", 12)     ||
1793                !memcmp(pkt->data, "\002\000\007publish", 10)       ||
1794                !memcmp(pkt->data, "\002\000\010_checkbw", 11)      ||
1795                !memcmp(pkt->data, "\002\000\014createStream", 15)) {
1796         if (ret = send_invoke_response(s, pkt) < 0)
1797             return ret;
1798     }
1799
1800     return ret;
1801 }
1802
1803 static int handle_notify(URLContext *s, RTMPPacket *pkt) {
1804     RTMPContext *rt  = s->priv_data;
1805     const uint8_t *p = NULL;
1806     uint8_t *cp      = NULL;
1807     uint8_t commandbuffer[64];
1808     char statusmsg[128];
1809     int stringlen;
1810     GetByteContext gbc;
1811     PutByteContext pbc;
1812     uint32_t ts;
1813     int old_flv_size;
1814     const uint8_t *datatowrite;
1815     unsigned datatowritelength;
1816
1817     p = pkt->data;
1818     bytestream2_init(&gbc, p, pkt->data_size);
1819     if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
1820                            &stringlen))
1821         return AVERROR_INVALIDDATA;
1822     if (!strcmp(commandbuffer, "@setDataFrame")) {
1823         datatowrite       = gbc.buffer;
1824         datatowritelength = bytestream2_get_bytes_left(&gbc);
1825         if (ff_amf_read_string(&gbc, statusmsg,
1826                                sizeof(statusmsg), &stringlen))
1827             return AVERROR_INVALIDDATA;
1828         if (strcmp(statusmsg, "onMetaData")) {
1829             av_log(s, AV_LOG_INFO, "Expecting onMetadata but got %s\n",
1830                    statusmsg);
1831             return 0;
1832         }
1833
1834         /* Provide ECMAArray to flv */
1835         ts = pkt->timestamp;
1836
1837         // generate packet header and put data into buffer for FLV demuxer
1838         if (rt->flv_off < rt->flv_size) {
1839             old_flv_size  = rt->flv_size;
1840             rt->flv_size += datatowritelength + 15;
1841         } else {
1842             old_flv_size = 0;
1843             rt->flv_size = datatowritelength + 15;
1844             rt->flv_off  = 0;
1845         }
1846
1847         cp = av_realloc(rt->flv_data, rt->flv_size);
1848         if (!cp)
1849             return AVERROR(ENOMEM);
1850         rt->flv_data = cp;
1851         bytestream2_init_writer(&pbc, cp, rt->flv_size);
1852         bytestream2_skip_p(&pbc, old_flv_size);
1853         bytestream2_put_byte(&pbc, pkt->type);
1854         bytestream2_put_be24(&pbc, datatowritelength);
1855         bytestream2_put_be24(&pbc, ts);
1856         bytestream2_put_byte(&pbc, ts >> 24);
1857         bytestream2_put_be24(&pbc, 0);
1858         bytestream2_put_buffer(&pbc, datatowrite, datatowritelength);
1859         bytestream2_put_be32(&pbc, 0);
1860     }
1861     return 0;
1862 }
1863
1864 /**
1865  * Parse received packet and possibly perform some action depending on
1866  * the packet contents.
1867  * @return 0 for no errors, negative values for serious errors which prevent
1868  *         further communications, positive values for uncritical errors
1869  */
1870 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
1871 {
1872     int ret;
1873
1874 #ifdef DEBUG
1875     ff_rtmp_packet_dump(s, pkt);
1876 #endif
1877
1878     switch (pkt->type) {
1879     case RTMP_PT_BYTES_READ:
1880         av_dlog(s, "received bytes read report\n");
1881         break;
1882     case RTMP_PT_CHUNK_SIZE:
1883         if ((ret = handle_chunk_size(s, pkt)) < 0)
1884             return ret;
1885         break;
1886     case RTMP_PT_PING:
1887         if ((ret = handle_ping(s, pkt)) < 0)
1888             return ret;
1889         break;
1890     case RTMP_PT_CLIENT_BW:
1891         if ((ret = handle_client_bw(s, pkt)) < 0)
1892             return ret;
1893         break;
1894     case RTMP_PT_SERVER_BW:
1895         if ((ret = handle_server_bw(s, pkt)) < 0)
1896             return ret;
1897         break;
1898     case RTMP_PT_INVOKE:
1899         if ((ret = handle_invoke(s, pkt)) < 0)
1900             return ret;
1901         break;
1902     case RTMP_PT_VIDEO:
1903     case RTMP_PT_AUDIO:
1904     case RTMP_PT_METADATA:
1905     case RTMP_PT_NOTIFY:
1906         /* Audio, Video and Metadata packets are parsed in get_packet() */
1907         break;
1908     default:
1909         av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
1910         break;
1911     }
1912     return 0;
1913 }
1914
1915 /**
1916  * Interact with the server by receiving and sending RTMP packets until
1917  * there is some significant data (media data or expected status notification).
1918  *
1919  * @param s          reading context
1920  * @param for_header non-zero value tells function to work until it
1921  * gets notification from the server that playing has been started,
1922  * otherwise function will work until some media data is received (or
1923  * an error happens)
1924  * @return 0 for successful operation, negative value in case of error
1925  */
1926 static int get_packet(URLContext *s, int for_header)
1927 {
1928     RTMPContext *rt = s->priv_data;
1929     int ret;
1930     uint8_t *p;
1931     const uint8_t *next;
1932     uint32_t data_size;
1933     uint32_t ts, cts, pts=0;
1934
1935     if (rt->state == STATE_STOPPED)
1936         return AVERROR_EOF;
1937
1938     for (;;) {
1939         RTMPPacket rpkt = { 0 };
1940         if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
1941                                        rt->in_chunk_size, rt->prev_pkt[0])) <= 0) {
1942             if (ret == 0) {
1943                 return AVERROR(EAGAIN);
1944             } else {
1945                 return AVERROR(EIO);
1946             }
1947         }
1948         rt->bytes_read += ret;
1949         if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
1950             av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
1951             if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
1952                 return ret;
1953             rt->last_bytes_read = rt->bytes_read;
1954         }
1955
1956         ret = rtmp_parse_result(s, rt, &rpkt);
1957         if (ret < 0) {//serious error in current packet
1958             ff_rtmp_packet_destroy(&rpkt);
1959             return ret;
1960         }
1961         if (rt->state == STATE_STOPPED) {
1962             ff_rtmp_packet_destroy(&rpkt);
1963             return AVERROR_EOF;
1964         }
1965         if (for_header && (rt->state == STATE_PLAYING    ||
1966                            rt->state == STATE_PUBLISHING ||
1967                            rt->state == STATE_RECEIVING)) {
1968             ff_rtmp_packet_destroy(&rpkt);
1969             return 0;
1970         }
1971         if (!rpkt.data_size || !rt->is_input) {
1972             ff_rtmp_packet_destroy(&rpkt);
1973             continue;
1974         }
1975         if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
1976            (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
1977             ts = rpkt.timestamp;
1978
1979             // generate packet header and put data into buffer for FLV demuxer
1980             rt->flv_off  = 0;
1981             rt->flv_size = rpkt.data_size + 15;
1982             rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
1983             bytestream_put_byte(&p, rpkt.type);
1984             bytestream_put_be24(&p, rpkt.data_size);
1985             bytestream_put_be24(&p, ts);
1986             bytestream_put_byte(&p, ts >> 24);
1987             bytestream_put_be24(&p, 0);
1988             bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);
1989             bytestream_put_be32(&p, 0);
1990             ff_rtmp_packet_destroy(&rpkt);
1991             return 0;
1992         } else if (rpkt.type == RTMP_PT_NOTIFY) {
1993             ret = handle_notify(s, &rpkt);
1994             ff_rtmp_packet_destroy(&rpkt);
1995             if (ret) {
1996                 av_log(s, AV_LOG_ERROR, "Handle notify error\n");
1997                 return ret;
1998             }
1999             return 0;
2000         } else if (rpkt.type == RTMP_PT_METADATA) {
2001             // we got raw FLV data, make it available for FLV demuxer
2002             rt->flv_off  = 0;
2003             rt->flv_size = rpkt.data_size;
2004             rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2005             /* rewrite timestamps */
2006             next = rpkt.data;
2007             ts = rpkt.timestamp;
2008             while (next - rpkt.data < rpkt.data_size - 11) {
2009                 next++;
2010                 data_size = bytestream_get_be24(&next);
2011                 p=next;
2012                 cts = bytestream_get_be24(&next);
2013                 cts |= bytestream_get_byte(&next) << 24;
2014                 if (pts==0)
2015                     pts=cts;
2016                 ts += cts - pts;
2017                 pts = cts;
2018                 bytestream_put_be24(&p, ts);
2019                 bytestream_put_byte(&p, ts >> 24);
2020                 next += data_size + 3 + 4;
2021             }
2022             memcpy(rt->flv_data, rpkt.data, rpkt.data_size);
2023             ff_rtmp_packet_destroy(&rpkt);
2024             return 0;
2025         }
2026         ff_rtmp_packet_destroy(&rpkt);
2027     }
2028 }
2029
2030 static int rtmp_close(URLContext *h)
2031 {
2032     RTMPContext *rt = h->priv_data;
2033     int ret = 0;
2034
2035     if (!rt->is_input) {
2036         rt->flv_data = NULL;
2037         if (rt->out_pkt.data_size)
2038             ff_rtmp_packet_destroy(&rt->out_pkt);
2039         if (rt->state > STATE_FCPUBLISH)
2040             ret = gen_fcunpublish_stream(h, rt);
2041     }
2042     if (rt->state > STATE_HANDSHAKED)
2043         ret = gen_delete_stream(h, rt);
2044
2045     free_tracked_methods(rt);
2046     av_freep(&rt->flv_data);
2047     ffurl_close(rt->stream);
2048     return ret;
2049 }
2050
2051 /**
2052  * Open RTMP connection and verify that the stream can be played.
2053  *
2054  * URL syntax: rtmp://server[:port][/app][/playpath]
2055  *             where 'app' is first one or two directories in the path
2056  *             (e.g. /ondemand/, /flash/live/, etc.)
2057  *             and 'playpath' is a file name (the rest of the path,
2058  *             may be prefixed with "mp4:")
2059  */
2060 static int rtmp_open(URLContext *s, const char *uri, int flags)
2061 {
2062     RTMPContext *rt = s->priv_data;
2063     char proto[8], hostname[256], path[1024], *fname;
2064     char *old_app;
2065     uint8_t buf[2048];
2066     int port;
2067     AVDictionary *opts = NULL;
2068     int ret;
2069
2070     if (rt->listen_timeout > 0)
2071         rt->listen = 1;
2072
2073     rt->is_input = !(flags & AVIO_FLAG_WRITE);
2074
2075     av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
2076                  path, sizeof(path), s->filename);
2077
2078     if (rt->listen && strcmp(proto, "rtmp")) {
2079         av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2080                proto);
2081         return AVERROR(EINVAL);
2082     }
2083     if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2084         if (!strcmp(proto, "rtmpts"))
2085             av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2086
2087         /* open the http tunneling connection */
2088         ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2089     } else if (!strcmp(proto, "rtmps")) {
2090         /* open the tls connection */
2091         if (port < 0)
2092             port = RTMPS_DEFAULT_PORT;
2093         ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2094     } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2095         if (!strcmp(proto, "rtmpte"))
2096             av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2097
2098         /* open the encrypted connection */
2099         ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2100         rt->encrypted = 1;
2101     } else {
2102         /* open the tcp connection */
2103         if (port < 0)
2104             port = RTMP_DEFAULT_PORT;
2105         if (rt->listen)
2106             ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2107                         "?listen&listen_timeout=%d",
2108                         rt->listen_timeout * 1000);
2109         else
2110             ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2111     }
2112
2113     if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2114                           &s->interrupt_callback, &opts)) < 0) {
2115         av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2116         goto fail;
2117     }
2118
2119     if (rt->swfverify) {
2120         if ((ret = rtmp_calc_swfhash(s)) < 0)
2121             goto fail;
2122     }
2123
2124     rt->state = STATE_START;
2125     if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2126         goto fail;
2127     if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2128         goto fail;
2129
2130     rt->out_chunk_size = 128;
2131     rt->in_chunk_size  = 128; // Probably overwritten later
2132     rt->state = STATE_HANDSHAKED;
2133
2134     // Keep the application name when it has been defined by the user.
2135     old_app = rt->app;
2136
2137     rt->app = av_malloc(APP_MAX_LENGTH);
2138     if (!rt->app) {
2139         ret = AVERROR(ENOMEM);
2140         goto fail;
2141     }
2142
2143     //extract "app" part from path
2144     if (!strncmp(path, "/ondemand/", 10)) {
2145         fname = path + 10;
2146         memcpy(rt->app, "ondemand", 9);
2147     } else {
2148         char *next = *path ? path + 1 : path;
2149         char *p = strchr(next, '/');
2150         if (!p) {
2151             fname = next;
2152             rt->app[0] = '\0';
2153         } else {
2154             // make sure we do not mismatch a playpath for an application instance
2155             char *c = strchr(p + 1, ':');
2156             fname = strchr(p + 1, '/');
2157             if (!fname || (c && c < fname)) {
2158                 fname = p + 1;
2159                 av_strlcpy(rt->app, path + 1, p - path);
2160             } else {
2161                 fname++;
2162                 av_strlcpy(rt->app, path + 1, fname - path - 1);
2163             }
2164         }
2165     }
2166
2167     if (old_app) {
2168         // The name of application has been defined by the user, override it.
2169         av_free(rt->app);
2170         rt->app = old_app;
2171     }
2172
2173     if (!rt->playpath) {
2174         int len = strlen(fname);
2175
2176         rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2177         if (!rt->playpath) {
2178             ret = AVERROR(ENOMEM);
2179             goto fail;
2180         }
2181
2182         if (!strchr(fname, ':') && len >= 4 &&
2183             (!strcmp(fname + len - 4, ".f4v") ||
2184              !strcmp(fname + len - 4, ".mp4"))) {
2185             memcpy(rt->playpath, "mp4:", 5);
2186         } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
2187             fname[len - 4] = '\0';
2188         } else {
2189             rt->playpath[0] = 0;
2190         }
2191         av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
2192     }
2193
2194     if (!rt->tcurl) {
2195         rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2196         if (!rt->tcurl) {
2197             ret = AVERROR(ENOMEM);
2198             goto fail;
2199         }
2200         ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2201                     port, "/%s", rt->app);
2202     }
2203
2204     if (!rt->flashver) {
2205         rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2206         if (!rt->flashver) {
2207             ret = AVERROR(ENOMEM);
2208             goto fail;
2209         }
2210         if (rt->is_input) {
2211             snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2212                     RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2213                     RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2214         } else {
2215             snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2216                     "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2217         }
2218     }
2219
2220     rt->client_report_size = 1048576;
2221     rt->bytes_read = 0;
2222     rt->last_bytes_read = 0;
2223     rt->server_bw = 2500000;
2224
2225     av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2226            proto, path, rt->app, rt->playpath);
2227     if (!rt->listen) {
2228         if ((ret = gen_connect(s, rt)) < 0)
2229             goto fail;
2230     } else {
2231         if (read_connect(s, s->priv_data) < 0)
2232             goto fail;
2233         rt->is_input = 1;
2234     }
2235
2236     do {
2237         ret = get_packet(s, 1);
2238     } while (ret == EAGAIN);
2239     if (ret < 0)
2240         goto fail;
2241
2242     if (rt->is_input) {
2243         // generate FLV header for demuxer
2244         rt->flv_size = 13;
2245         rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2246         rt->flv_off  = 0;
2247         memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
2248     } else {
2249         rt->flv_size = 0;
2250         rt->flv_data = NULL;
2251         rt->flv_off  = 0;
2252         rt->skip_bytes = 13;
2253     }
2254
2255     s->max_packet_size = rt->stream->max_packet_size;
2256     s->is_streamed     = 1;
2257     return 0;
2258
2259 fail:
2260     av_dict_free(&opts);
2261     rtmp_close(s);
2262     return ret;
2263 }
2264
2265 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2266 {
2267     RTMPContext *rt = s->priv_data;
2268     int orig_size = size;
2269     int ret;
2270
2271     while (size > 0) {
2272         int data_left = rt->flv_size - rt->flv_off;
2273
2274         if (data_left >= size) {
2275             memcpy(buf, rt->flv_data + rt->flv_off, size);
2276             rt->flv_off += size;
2277             return orig_size;
2278         }
2279         if (data_left > 0) {
2280             memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2281             buf  += data_left;
2282             size -= data_left;
2283             rt->flv_off = rt->flv_size;
2284             return data_left;
2285         }
2286         if ((ret = get_packet(s, 0)) < 0)
2287            return ret;
2288     }
2289     return orig_size;
2290 }
2291
2292 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2293 {
2294     RTMPContext *rt = s->priv_data;
2295     int size_temp = size;
2296     int pktsize, pkttype;
2297     uint32_t ts;
2298     const uint8_t *buf_temp = buf;
2299     uint8_t c;
2300     int ret;
2301
2302     do {
2303         if (rt->skip_bytes) {
2304             int skip = FFMIN(rt->skip_bytes, size_temp);
2305             buf_temp       += skip;
2306             size_temp      -= skip;
2307             rt->skip_bytes -= skip;
2308             continue;
2309         }
2310
2311         if (rt->flv_header_bytes < 11) {
2312             const uint8_t *header = rt->flv_header;
2313             int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
2314             bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2315             rt->flv_header_bytes += copy;
2316             size_temp            -= copy;
2317             if (rt->flv_header_bytes < 11)
2318                 break;
2319
2320             pkttype = bytestream_get_byte(&header);
2321             pktsize = bytestream_get_be24(&header);
2322             ts = bytestream_get_be24(&header);
2323             ts |= bytestream_get_byte(&header) << 24;
2324             bytestream_get_be24(&header);
2325             rt->flv_size = pktsize;
2326
2327             //force 12bytes header
2328             if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2329                 pkttype == RTMP_PT_NOTIFY) {
2330                 if (pkttype == RTMP_PT_NOTIFY)
2331                     pktsize += 16;
2332                 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
2333             }
2334
2335             //this can be a big packet, it's better to send it right here
2336             if ((ret = ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL,
2337                                              pkttype, ts, pktsize)) < 0)
2338                 return ret;
2339
2340             rt->out_pkt.extra = rt->main_channel_id;
2341             rt->flv_data = rt->out_pkt.data;
2342
2343             if (pkttype == RTMP_PT_NOTIFY)
2344                 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2345         }
2346
2347         if (rt->flv_size - rt->flv_off > size_temp) {
2348             bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2349             rt->flv_off += size_temp;
2350             size_temp = 0;
2351         } else {
2352             bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2353             size_temp   -= rt->flv_size - rt->flv_off;
2354             rt->flv_off += rt->flv_size - rt->flv_off;
2355         }
2356
2357         if (rt->flv_off == rt->flv_size) {
2358             rt->skip_bytes = 4;
2359
2360             if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2361                 return ret;
2362             rt->flv_size = 0;
2363             rt->flv_off = 0;
2364             rt->flv_header_bytes = 0;
2365             rt->flv_nb_packets++;
2366         }
2367     } while (buf_temp - buf < size);
2368
2369     if (rt->flv_nb_packets < rt->flush_interval)
2370         return size;
2371     rt->flv_nb_packets = 0;
2372
2373     /* set stream into nonblocking mode */
2374     rt->stream->flags |= AVIO_FLAG_NONBLOCK;
2375
2376     /* try to read one byte from the stream */
2377     ret = ffurl_read(rt->stream, &c, 1);
2378
2379     /* switch the stream back into blocking mode */
2380     rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2381
2382     if (ret == AVERROR(EAGAIN)) {
2383         /* no incoming data to handle */
2384         return size;
2385     } else if (ret < 0) {
2386         return ret;
2387     } else if (ret == 1) {
2388         RTMPPacket rpkt = { 0 };
2389
2390         if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2391                                                 rt->in_chunk_size,
2392                                                 rt->prev_pkt[0], c)) <= 0)
2393              return ret;
2394
2395         if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2396             return ret;
2397
2398         ff_rtmp_packet_destroy(&rpkt);
2399     }
2400
2401     return size;
2402 }
2403
2404 #define OFFSET(x) offsetof(RTMPContext, x)
2405 #define DEC AV_OPT_FLAG_DECODING_PARAM
2406 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2407
2408 static const AVOption rtmp_options[] = {
2409     {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2410     {"rtmp_buffer", "Set buffer time in milliseconds. The default is 3000.", OFFSET(client_buffer_time), AV_OPT_TYPE_INT, {.i64 = 3000}, 0, INT_MAX, DEC|ENC},
2411     {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2412     {"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},
2413     {"rtmp_flush_interval", "Number of packets flushed in the same request (RTMPT only).", OFFSET(flush_interval), AV_OPT_TYPE_INT, {.i64 = 10}, 0, INT_MAX, ENC},
2414     {"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {.i64 = -2}, INT_MIN, INT_MAX, DEC, "rtmp_live"},
2415     {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
2416     {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
2417     {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
2418     {"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},
2419     {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2420     {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2421     {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2422     {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
2423     {"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},
2424     {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2425     {"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},
2426     {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2427     {"timeout", "Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies -rtmp_listen 1",  OFFSET(listen_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2428     { NULL },
2429 };
2430
2431 #define RTMP_PROTOCOL(flavor)                    \
2432 static const AVClass flavor##_class = {          \
2433     .class_name = #flavor,                       \
2434     .item_name  = av_default_item_name,          \
2435     .option     = rtmp_options,                  \
2436     .version    = LIBAVUTIL_VERSION_INT,         \
2437 };                                               \
2438                                                  \
2439 URLProtocol ff_##flavor##_protocol = {           \
2440     .name           = #flavor,                   \
2441     .url_open       = rtmp_open,                 \
2442     .url_read       = rtmp_read,                 \
2443     .url_write      = rtmp_write,                \
2444     .url_close      = rtmp_close,                \
2445     .priv_data_size = sizeof(RTMPContext),       \
2446     .flags          = URL_PROTOCOL_FLAG_NETWORK, \
2447     .priv_data_class= &flavor##_class,           \
2448 };
2449
2450
2451 RTMP_PROTOCOL(rtmp)
2452 RTMP_PROTOCOL(rtmpe)
2453 RTMP_PROTOCOL(rtmps)
2454 RTMP_PROTOCOL(rtmpt)
2455 RTMP_PROTOCOL(rtmpte)
2456 RTMP_PROTOCOL(rtmpts)