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