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