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