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