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