]> git.sesse.net Git - ffmpeg/blob - libavformat/rtmpproto.c
avformat/utils: functions that add entries should not destroy the whole list on failure
[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->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->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.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.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.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.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.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.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 %"PRId64"\n",
715            timestamp);
716
717     if ((ret = ff_rtmp_packet_create(&pkt, 3, RTMP_PT_INVOKE, 0, 26)) < 0)
718         return ret;
719
720     pkt.extra = rt->main_channel_id;
721
722     p = pkt.data;
723     ff_amf_write_string(&p, "seek");
724     ff_amf_write_number(&p, 0); //no tracking back responses
725     ff_amf_write_null(&p); //as usual, the first null param
726     ff_amf_write_number(&p, timestamp); //where we want to jump
727
728     return rtmp_send_packet(rt, &pkt, 1);
729 }
730
731 /**
732  * Generate 'publish' call and send it to the server.
733  */
734 static int gen_publish(URLContext *s, RTMPContext *rt)
735 {
736     RTMPPacket pkt;
737     uint8_t *p;
738     int ret;
739
740     av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
741
742     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
743                                      0, 30 + strlen(rt->playpath))) < 0)
744         return ret;
745
746     pkt.extra = rt->main_channel_id;
747
748     p = pkt.data;
749     ff_amf_write_string(&p, "publish");
750     ff_amf_write_number(&p, ++rt->nb_invokes);
751     ff_amf_write_null(&p);
752     ff_amf_write_string(&p, rt->playpath);
753     ff_amf_write_string(&p, "live");
754
755     return rtmp_send_packet(rt, &pkt, 1);
756 }
757
758 /**
759  * Generate ping reply and send it to the server.
760  */
761 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
762 {
763     RTMPPacket pkt;
764     uint8_t *p;
765     int ret;
766
767     if (ppkt->size < 6) {
768         av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
769                ppkt->size);
770         return AVERROR_INVALIDDATA;
771     }
772
773     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
774                                      ppkt->timestamp + 1, 6)) < 0)
775         return ret;
776
777     p = pkt.data;
778     bytestream_put_be16(&p, 7);
779     bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
780
781     return rtmp_send_packet(rt, &pkt, 0);
782 }
783
784 /**
785  * Generate SWF verification message and send it to the server.
786  */
787 static int gen_swf_verification(URLContext *s, RTMPContext *rt)
788 {
789     RTMPPacket pkt;
790     uint8_t *p;
791     int ret;
792
793     av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
794     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
795                                      0, 44)) < 0)
796         return ret;
797
798     p = pkt.data;
799     bytestream_put_be16(&p, 27);
800     memcpy(p, rt->swfverification, 42);
801
802     return rtmp_send_packet(rt, &pkt, 0);
803 }
804
805 /**
806  * Generate server bandwidth message and send it to the server.
807  */
808 static int gen_server_bw(URLContext *s, RTMPContext *rt)
809 {
810     RTMPPacket pkt;
811     uint8_t *p;
812     int ret;
813
814     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
815                                      0, 4)) < 0)
816         return ret;
817
818     p = pkt.data;
819     bytestream_put_be32(&p, rt->server_bw);
820
821     return rtmp_send_packet(rt, &pkt, 0);
822 }
823
824 /**
825  * Generate check bandwidth message and send it to the server.
826  */
827 static int gen_check_bw(URLContext *s, RTMPContext *rt)
828 {
829     RTMPPacket pkt;
830     uint8_t *p;
831     int ret;
832
833     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
834                                      0, 21)) < 0)
835         return ret;
836
837     p = pkt.data;
838     ff_amf_write_string(&p, "_checkbw");
839     ff_amf_write_number(&p, ++rt->nb_invokes);
840     ff_amf_write_null(&p);
841
842     return rtmp_send_packet(rt, &pkt, 1);
843 }
844
845 /**
846  * Generate report on bytes read so far and send it to the server.
847  */
848 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
849 {
850     RTMPPacket pkt;
851     uint8_t *p;
852     int ret;
853
854     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
855                                      ts, 4)) < 0)
856         return ret;
857
858     p = pkt.data;
859     bytestream_put_be32(&p, rt->bytes_read);
860
861     return rtmp_send_packet(rt, &pkt, 0);
862 }
863
864 static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
865                                   const char *subscribe)
866 {
867     RTMPPacket pkt;
868     uint8_t *p;
869     int ret;
870
871     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
872                                      0, 27 + strlen(subscribe))) < 0)
873         return ret;
874
875     p = pkt.data;
876     ff_amf_write_string(&p, "FCSubscribe");
877     ff_amf_write_number(&p, ++rt->nb_invokes);
878     ff_amf_write_null(&p);
879     ff_amf_write_string(&p, subscribe);
880
881     return rtmp_send_packet(rt, &pkt, 1);
882 }
883
884 int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
885                         const uint8_t *key, int keylen, uint8_t *dst)
886 {
887     struct AVSHA *sha;
888     uint8_t hmac_buf[64+32] = {0};
889     int i;
890
891     sha = av_sha_alloc();
892     if (!sha)
893         return AVERROR(ENOMEM);
894
895     if (keylen < 64) {
896         memcpy(hmac_buf, key, keylen);
897     } else {
898         av_sha_init(sha, 256);
899         av_sha_update(sha,key, keylen);
900         av_sha_final(sha, hmac_buf);
901     }
902     for (i = 0; i < 64; i++)
903         hmac_buf[i] ^= HMAC_IPAD_VAL;
904
905     av_sha_init(sha, 256);
906     av_sha_update(sha, hmac_buf, 64);
907     if (gap <= 0) {
908         av_sha_update(sha, src, len);
909     } else { //skip 32 bytes used for storing digest
910         av_sha_update(sha, src, gap);
911         av_sha_update(sha, src + gap + 32, len - gap - 32);
912     }
913     av_sha_final(sha, hmac_buf + 64);
914
915     for (i = 0; i < 64; i++)
916         hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
917     av_sha_init(sha, 256);
918     av_sha_update(sha, hmac_buf, 64+32);
919     av_sha_final(sha, dst);
920
921     av_free(sha);
922
923     return 0;
924 }
925
926 int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
927                             int add_val)
928 {
929     int i, digest_pos = 0;
930
931     for (i = 0; i < 4; i++)
932         digest_pos += buf[i + off];
933     digest_pos = digest_pos % mod_val + add_val;
934
935     return digest_pos;
936 }
937
938 /**
939  * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
940  * will be stored) into that packet.
941  *
942  * @param buf handshake data (1536 bytes)
943  * @param encrypted use an encrypted connection (RTMPE)
944  * @return offset to the digest inside input data
945  */
946 static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
947 {
948     int ret, digest_pos;
949
950     if (encrypted)
951         digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
952     else
953         digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
954
955     ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
956                               rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
957                               buf + digest_pos);
958     if (ret < 0)
959         return ret;
960
961     return digest_pos;
962 }
963
964 /**
965  * Verify that the received server response has the expected digest value.
966  *
967  * @param buf handshake data received from the server (1536 bytes)
968  * @param off position to search digest offset from
969  * @return 0 if digest is valid, digest position otherwise
970  */
971 static int rtmp_validate_digest(uint8_t *buf, int off)
972 {
973     uint8_t digest[32];
974     int ret, digest_pos;
975
976     digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
977
978     ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
979                               rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
980                               digest);
981     if (ret < 0)
982         return ret;
983
984     if (!memcmp(digest, buf + digest_pos, 32))
985         return digest_pos;
986     return 0;
987 }
988
989 static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
990                                       uint8_t *buf)
991 {
992     uint8_t *p;
993     int ret;
994
995     if (rt->swfhash_len != 32) {
996         av_log(s, AV_LOG_ERROR,
997                "Hash of the decompressed SWF file is not 32 bytes long.\n");
998         return AVERROR(EINVAL);
999     }
1000
1001     p = &rt->swfverification[0];
1002     bytestream_put_byte(&p, 1);
1003     bytestream_put_byte(&p, 1);
1004     bytestream_put_be32(&p, rt->swfsize);
1005     bytestream_put_be32(&p, rt->swfsize);
1006
1007     if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
1008         return ret;
1009
1010     return 0;
1011 }
1012
1013 #if CONFIG_ZLIB
1014 static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
1015                                      uint8_t **out_data, int64_t *out_size)
1016 {
1017     z_stream zs = { 0 };
1018     void *ptr;
1019     int size;
1020     int ret = 0;
1021
1022     zs.avail_in = in_size;
1023     zs.next_in  = in_data;
1024     ret = inflateInit(&zs);
1025     if (ret != Z_OK)
1026         return AVERROR_UNKNOWN;
1027
1028     do {
1029         uint8_t tmp_buf[16384];
1030
1031         zs.avail_out = sizeof(tmp_buf);
1032         zs.next_out  = tmp_buf;
1033
1034         ret = inflate(&zs, Z_NO_FLUSH);
1035         if (ret != Z_OK && ret != Z_STREAM_END) {
1036             ret = AVERROR_UNKNOWN;
1037             goto fail;
1038         }
1039
1040         size = sizeof(tmp_buf) - zs.avail_out;
1041         if (!(ptr = av_realloc(*out_data, *out_size + size))) {
1042             ret = AVERROR(ENOMEM);
1043             goto fail;
1044         }
1045         *out_data = ptr;
1046
1047         memcpy(*out_data + *out_size, tmp_buf, size);
1048         *out_size += size;
1049     } while (zs.avail_out == 0);
1050
1051 fail:
1052     inflateEnd(&zs);
1053     return ret;
1054 }
1055 #endif
1056
1057 static int rtmp_calc_swfhash(URLContext *s)
1058 {
1059     RTMPContext *rt = s->priv_data;
1060     uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
1061     int64_t in_size, out_size;
1062     URLContext *stream;
1063     char swfhash[32];
1064     int swfsize;
1065     int ret = 0;
1066
1067     /* Get the SWF player file. */
1068     if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
1069                           &s->interrupt_callback, NULL)) < 0) {
1070         av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1071         goto fail;
1072     }
1073
1074     if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
1075         ret = AVERROR(EIO);
1076         goto fail;
1077     }
1078
1079     if (!(in_data = av_malloc(in_size))) {
1080         ret = AVERROR(ENOMEM);
1081         goto fail;
1082     }
1083
1084     if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
1085         goto fail;
1086
1087     if (in_size < 3) {
1088         ret = AVERROR_INVALIDDATA;
1089         goto fail;
1090     }
1091
1092     if (!memcmp(in_data, "CWS", 3)) {
1093         /* Decompress the SWF player file using Zlib. */
1094         if (!(out_data = av_malloc(8))) {
1095             ret = AVERROR(ENOMEM);
1096             goto fail;
1097         }
1098         *in_data = 'F'; // magic stuff
1099         memcpy(out_data, in_data, 8);
1100         out_size = 8;
1101
1102 #if CONFIG_ZLIB
1103         if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1104                                              &out_data, &out_size)) < 0)
1105             goto fail;
1106 #else
1107         av_log(s, AV_LOG_ERROR,
1108                "Zlib is required for decompressing the SWF player file.\n");
1109         ret = AVERROR(EINVAL);
1110         goto fail;
1111 #endif
1112         swfsize = out_size;
1113         swfdata = out_data;
1114     } else {
1115         swfsize = in_size;
1116         swfdata = in_data;
1117     }
1118
1119     /* Compute the SHA256 hash of the SWF player file. */
1120     if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
1121                                    "Genuine Adobe Flash Player 001", 30,
1122                                    swfhash)) < 0)
1123         goto fail;
1124
1125     /* Set SWFVerification parameters. */
1126     av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
1127     rt->swfsize = swfsize;
1128
1129 fail:
1130     av_freep(&in_data);
1131     av_freep(&out_data);
1132     ffurl_close(stream);
1133     return ret;
1134 }
1135
1136 /**
1137  * Perform handshake with the server by means of exchanging pseudorandom data
1138  * signed with HMAC-SHA2 digest.
1139  *
1140  * @return 0 if handshake succeeds, negative value otherwise
1141  */
1142 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
1143 {
1144     AVLFG rnd;
1145     uint8_t tosend    [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
1146         3,                // unencrypted data
1147         0, 0, 0, 0,       // client uptime
1148         RTMP_CLIENT_VER1,
1149         RTMP_CLIENT_VER2,
1150         RTMP_CLIENT_VER3,
1151         RTMP_CLIENT_VER4,
1152     };
1153     uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1154     uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1155     int i;
1156     int server_pos, client_pos;
1157     uint8_t digest[32], signature[32];
1158     int ret, type = 0;
1159
1160     av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1161
1162     av_lfg_init(&rnd, 0xDEADC0DE);
1163     // generate handshake packet - 1536 bytes of pseudorandom data
1164     for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1165         tosend[i] = av_lfg_get(&rnd) >> 24;
1166
1167     if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1168         /* When the client wants to use RTMPE, we have to change the command
1169          * byte to 0x06 which means to use encrypted data and we have to set
1170          * the flash version to at least 9.0.115.0. */
1171         tosend[0] = 6;
1172         tosend[5] = 128;
1173         tosend[6] = 0;
1174         tosend[7] = 3;
1175         tosend[8] = 2;
1176
1177         /* Initialize the Diffie-Hellmann context and generate the public key
1178          * to send to the server. */
1179         if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1180             return ret;
1181     }
1182
1183     client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1184     if (client_pos < 0)
1185         return client_pos;
1186
1187     if ((ret = ffurl_write(rt->stream, tosend,
1188                            RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1189         av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1190         return ret;
1191     }
1192
1193     if ((ret = ffurl_read_complete(rt->stream, serverdata,
1194                                    RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1195         av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1196         return ret;
1197     }
1198
1199     if ((ret = ffurl_read_complete(rt->stream, clientdata,
1200                                    RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
1201         av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1202         return ret;
1203     }
1204
1205     av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1206     av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1207            serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1208
1209     if (rt->is_input && serverdata[5] >= 3) {
1210         server_pos = rtmp_validate_digest(serverdata + 1, 772);
1211         if (server_pos < 0)
1212             return server_pos;
1213
1214         if (!server_pos) {
1215             type = 1;
1216             server_pos = rtmp_validate_digest(serverdata + 1, 8);
1217             if (server_pos < 0)
1218                 return server_pos;
1219
1220             if (!server_pos) {
1221                 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1222                 return AVERROR(EIO);
1223             }
1224         }
1225
1226         /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1227          * key are the last 32 bytes of the server handshake. */
1228         if (rt->swfsize) {
1229             if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1230                                                   RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1231                 return ret;
1232         }
1233
1234         ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1235                                   rtmp_server_key, sizeof(rtmp_server_key),
1236                                   digest);
1237         if (ret < 0)
1238             return ret;
1239
1240         ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1241                                   0, digest, 32, signature);
1242         if (ret < 0)
1243             return ret;
1244
1245         if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1246             /* Compute the shared secret key sent by the server and initialize
1247              * the RC4 encryption. */
1248             if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1249                                                    tosend + 1, type)) < 0)
1250                 return ret;
1251
1252             /* Encrypt the signature received by the server. */
1253             ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1254         }
1255
1256         if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1257             av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1258             return AVERROR(EIO);
1259         }
1260
1261         for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1262             tosend[i] = av_lfg_get(&rnd) >> 24;
1263         ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1264                                   rtmp_player_key, sizeof(rtmp_player_key),
1265                                   digest);
1266         if (ret < 0)
1267             return ret;
1268
1269         ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1270                                   digest, 32,
1271                                   tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1272         if (ret < 0)
1273             return ret;
1274
1275         if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1276             /* Encrypt the signature to be send to the server. */
1277             ff_rtmpe_encrypt_sig(rt->stream, tosend +
1278                                  RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1279                                  serverdata[0]);
1280         }
1281
1282         // write reply back to the server
1283         if ((ret = ffurl_write(rt->stream, tosend,
1284                                RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1285             return ret;
1286
1287         if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1288             /* Set RC4 keys for encryption and update the keystreams. */
1289             if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1290                 return ret;
1291         }
1292     } else {
1293         if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1294             /* Compute the shared secret key sent by the server and initialize
1295              * the RC4 encryption. */
1296             if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1297                             tosend + 1, 1)) < 0)
1298                 return ret;
1299
1300             if (serverdata[0] == 9) {
1301                 /* Encrypt the signature received by the server. */
1302                 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1303                                      serverdata[0]);
1304             }
1305         }
1306
1307         if ((ret = ffurl_write(rt->stream, serverdata + 1,
1308                                RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1309             return ret;
1310
1311         if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1312             /* Set RC4 keys for encryption and update the keystreams. */
1313             if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1314                 return ret;
1315         }
1316     }
1317
1318     return 0;
1319 }
1320
1321 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1322                                   uint32_t *second_int, char *arraydata,
1323                                   int size)
1324 {
1325     int inoutsize;
1326
1327     inoutsize = ffurl_read_complete(rt->stream, arraydata,
1328                                     RTMP_HANDSHAKE_PACKET_SIZE);
1329     if (inoutsize <= 0)
1330         return AVERROR(EIO);
1331     if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1332         av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1333                " not following standard\n", (int)inoutsize);
1334         return AVERROR(EINVAL);
1335     }
1336
1337     *first_int  = AV_RB32(arraydata);
1338     *second_int = AV_RB32(arraydata + 4);
1339     return 0;
1340 }
1341
1342 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1343                                uint32_t second_int, char *arraydata, int size)
1344 {
1345     int inoutsize;
1346
1347     AV_WB32(arraydata, first_int);
1348     AV_WB32(arraydata + 4, first_int);
1349     inoutsize = ffurl_write(rt->stream, arraydata,
1350                             RTMP_HANDSHAKE_PACKET_SIZE);
1351     if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1352         av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1353         return AVERROR(EIO);
1354     }
1355
1356     return 0;
1357 }
1358
1359 /**
1360  * rtmp handshake server side
1361  */
1362 static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
1363 {
1364     uint8_t buffer[RTMP_HANDSHAKE_PACKET_SIZE];
1365     uint32_t hs_epoch;
1366     uint32_t hs_my_epoch;
1367     uint8_t hs_c1[RTMP_HANDSHAKE_PACKET_SIZE];
1368     uint8_t hs_s1[RTMP_HANDSHAKE_PACKET_SIZE];
1369     uint32_t zeroes;
1370     uint32_t temp       = 0;
1371     int randomidx       = 0;
1372     int inoutsize       = 0;
1373     int ret;
1374
1375     inoutsize = ffurl_read_complete(rt->stream, buffer, 1);       // Receive C0
1376     if (inoutsize <= 0) {
1377         av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1378         return AVERROR(EIO);
1379     }
1380     // Check Version
1381     if (buffer[0] != 3) {
1382         av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1383         return AVERROR(EIO);
1384     }
1385     if (ffurl_write(rt->stream, buffer, 1) <= 0) {                 // Send S0
1386         av_log(s, AV_LOG_ERROR,
1387                "Unable to write answer - RTMP S0\n");
1388         return AVERROR(EIO);
1389     }
1390     /* Receive C1 */
1391     ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1392                                  RTMP_HANDSHAKE_PACKET_SIZE);
1393     if (ret) {
1394         av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1395         return ret;
1396     }
1397     if (zeroes)
1398         av_log(s, AV_LOG_WARNING, "Erroneous C1 Message zero != 0\n");
1399     /* Send S1 */
1400     /* By now same epoch will be sent */
1401     hs_my_epoch = hs_epoch;
1402     /* Generate random */
1403     for (randomidx = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1404          randomidx += 4)
1405         AV_WB32(hs_s1 + randomidx, av_get_random_seed());
1406
1407     ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1408                               RTMP_HANDSHAKE_PACKET_SIZE);
1409     if (ret) {
1410         av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1411         return ret;
1412     }
1413     /* Send S2 */
1414     ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1415                               RTMP_HANDSHAKE_PACKET_SIZE);
1416     if (ret) {
1417         av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1418         return ret;
1419     }
1420     /* Receive C2 */
1421     ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1422                                  RTMP_HANDSHAKE_PACKET_SIZE);
1423     if (ret) {
1424         av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1425         return ret;
1426     }
1427     if (temp != hs_my_epoch)
1428         av_log(s, AV_LOG_WARNING,
1429                "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1430     if (memcmp(buffer + 8, hs_s1 + 8,
1431                RTMP_HANDSHAKE_PACKET_SIZE - 8))
1432         av_log(s, AV_LOG_WARNING,
1433                "Erroneous C2 Message random does not match up\n");
1434
1435     return 0;
1436 }
1437
1438 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1439 {
1440     RTMPContext *rt = s->priv_data;
1441     int ret;
1442
1443     if (pkt->size < 4) {
1444         av_log(s, AV_LOG_ERROR,
1445                "Too short chunk size change packet (%d)\n",
1446                pkt->size);
1447         return AVERROR_INVALIDDATA;
1448     }
1449
1450     if (!rt->is_input) {
1451         /* Send the same chunk size change packet back to the server,
1452          * setting the outgoing chunk size to the same as the incoming one. */
1453         if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1454                                         rt->prev_pkt[1])) < 0)
1455             return ret;
1456         rt->out_chunk_size = AV_RB32(pkt->data);
1457     }
1458
1459     rt->in_chunk_size = AV_RB32(pkt->data);
1460     if (rt->in_chunk_size <= 0) {
1461         av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1462                rt->in_chunk_size);
1463         return AVERROR_INVALIDDATA;
1464     }
1465     av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1466            rt->in_chunk_size);
1467
1468     return 0;
1469 }
1470
1471 static int handle_ping(URLContext *s, RTMPPacket *pkt)
1472 {
1473     RTMPContext *rt = s->priv_data;
1474     int t, ret;
1475
1476     if (pkt->size < 2) {
1477         av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
1478                pkt->size);
1479         return AVERROR_INVALIDDATA;
1480     }
1481
1482     t = AV_RB16(pkt->data);
1483     if (t == 6) {
1484         if ((ret = gen_pong(s, rt, pkt)) < 0)
1485             return ret;
1486     } else if (t == 26) {
1487         if (rt->swfsize) {
1488             if ((ret = gen_swf_verification(s, rt)) < 0)
1489                 return ret;
1490         } else {
1491             av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1492         }
1493     }
1494
1495     return 0;
1496 }
1497
1498 static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
1499 {
1500     RTMPContext *rt = s->priv_data;
1501
1502     if (pkt->size < 4) {
1503         av_log(s, AV_LOG_ERROR,
1504                "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1505                pkt->size);
1506         return AVERROR_INVALIDDATA;
1507     }
1508
1509     rt->client_report_size = AV_RB32(pkt->data);
1510     if (rt->client_report_size <= 0) {
1511         av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
1512                 rt->client_report_size);
1513         return AVERROR_INVALIDDATA;
1514
1515     }
1516     av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
1517     rt->client_report_size >>= 1;
1518
1519     return 0;
1520 }
1521
1522 static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
1523 {
1524     RTMPContext *rt = s->priv_data;
1525
1526     if (pkt->size < 4) {
1527         av_log(s, AV_LOG_ERROR,
1528                "Too short server bandwidth report packet (%d)\n",
1529                pkt->size);
1530         return AVERROR_INVALIDDATA;
1531     }
1532
1533     rt->server_bw = AV_RB32(pkt->data);
1534     if (rt->server_bw <= 0) {
1535         av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
1536                rt->server_bw);
1537         return AVERROR_INVALIDDATA;
1538     }
1539     av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
1540
1541     return 0;
1542 }
1543
1544 static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt,
1545                          const char *opaque, const char *challenge)
1546 {
1547     uint8_t hash[16];
1548     char hashstr[AV_BASE64_SIZE(sizeof(hash))], challenge2[10];
1549     struct AVMD5 *md5 = av_md5_alloc();
1550     if (!md5)
1551         return AVERROR(ENOMEM);
1552
1553     snprintf(challenge2, sizeof(challenge2), "%08x", av_get_random_seed());
1554
1555     av_md5_init(md5);
1556     av_md5_update(md5, user, strlen(user));
1557     av_md5_update(md5, salt, strlen(salt));
1558     av_md5_update(md5, rt->password, strlen(rt->password));
1559     av_md5_final(md5, hash);
1560     av_base64_encode(hashstr, sizeof(hashstr), hash,
1561                      sizeof(hash));
1562     av_md5_init(md5);
1563     av_md5_update(md5, hashstr, strlen(hashstr));
1564     if (opaque)
1565         av_md5_update(md5, opaque, strlen(opaque));
1566     else if (challenge)
1567         av_md5_update(md5, challenge, strlen(challenge));
1568     av_md5_update(md5, challenge2, strlen(challenge2));
1569     av_md5_final(md5, hash);
1570     av_base64_encode(hashstr, sizeof(hashstr), hash,
1571                      sizeof(hash));
1572     snprintf(rt->auth_params, sizeof(rt->auth_params),
1573              "?authmod=%s&user=%s&challenge=%s&response=%s",
1574              "adobe", user, challenge2, hashstr);
1575     if (opaque)
1576         av_strlcatf(rt->auth_params, sizeof(rt->auth_params),
1577                     "&opaque=%s", opaque);
1578
1579     av_free(md5);
1580     return 0;
1581 }
1582
1583 static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
1584 {
1585     uint8_t hash[16];
1586     char hashstr1[33], hashstr2[33];
1587     const char *realm = "live";
1588     const char *method = "publish";
1589     const char *qop = "auth";
1590     const char *nc = "00000001";
1591     char cnonce[10];
1592     struct AVMD5 *md5 = av_md5_alloc();
1593     if (!md5)
1594         return AVERROR(ENOMEM);
1595
1596     snprintf(cnonce, sizeof(cnonce), "%08x", av_get_random_seed());
1597
1598     av_md5_init(md5);
1599     av_md5_update(md5, user, strlen(user));
1600     av_md5_update(md5, ":", 1);
1601     av_md5_update(md5, realm, strlen(realm));
1602     av_md5_update(md5, ":", 1);
1603     av_md5_update(md5, rt->password, strlen(rt->password));
1604     av_md5_final(md5, hash);
1605     ff_data_to_hex(hashstr1, hash, 16, 1);
1606     hashstr1[32] = '\0';
1607
1608     av_md5_init(md5);
1609     av_md5_update(md5, method, strlen(method));
1610     av_md5_update(md5, ":/", 2);
1611     av_md5_update(md5, rt->app, strlen(rt->app));
1612     if (!strchr(rt->app, '/'))
1613         av_md5_update(md5, "/_definst_", strlen("/_definst_"));
1614     av_md5_final(md5, hash);
1615     ff_data_to_hex(hashstr2, hash, 16, 1);
1616     hashstr2[32] = '\0';
1617
1618     av_md5_init(md5);
1619     av_md5_update(md5, hashstr1, strlen(hashstr1));
1620     av_md5_update(md5, ":", 1);
1621     if (nonce)
1622         av_md5_update(md5, nonce, strlen(nonce));
1623     av_md5_update(md5, ":", 1);
1624     av_md5_update(md5, nc, strlen(nc));
1625     av_md5_update(md5, ":", 1);
1626     av_md5_update(md5, cnonce, strlen(cnonce));
1627     av_md5_update(md5, ":", 1);
1628     av_md5_update(md5, qop, strlen(qop));
1629     av_md5_update(md5, ":", 1);
1630     av_md5_update(md5, hashstr2, strlen(hashstr2));
1631     av_md5_final(md5, hash);
1632     ff_data_to_hex(hashstr1, hash, 16, 1);
1633
1634     snprintf(rt->auth_params, sizeof(rt->auth_params),
1635              "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1636              "llnw", user, nonce, cnonce, nc, hashstr1);
1637
1638     av_free(md5);
1639     return 0;
1640 }
1641
1642 static int handle_connect_error(URLContext *s, const char *desc)
1643 {
1644     RTMPContext *rt = s->priv_data;
1645     char buf[300], *ptr, authmod[15];
1646     int i = 0, ret = 0;
1647     const char *user = "", *salt = "", *opaque = NULL,
1648                *challenge = NULL, *cptr = NULL, *nonce = NULL;
1649
1650     if (!(cptr = strstr(desc, "authmod=adobe")) &&
1651         !(cptr = strstr(desc, "authmod=llnw"))) {
1652         av_log(s, AV_LOG_ERROR,
1653                "Unknown connect error (unsupported authentication method?)\n");
1654         return AVERROR_UNKNOWN;
1655     }
1656     cptr += strlen("authmod=");
1657     while (*cptr && *cptr != ' ' && i < sizeof(authmod) - 1)
1658         authmod[i++] = *cptr++;
1659     authmod[i] = '\0';
1660
1661     if (!rt->username[0] || !rt->password[0]) {
1662         av_log(s, AV_LOG_ERROR, "No credentials set\n");
1663         return AVERROR_UNKNOWN;
1664     }
1665
1666     if (strstr(desc, "?reason=authfailed")) {
1667         av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1668         return AVERROR_UNKNOWN;
1669     } else if (strstr(desc, "?reason=nosuchuser")) {
1670         av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1671         return AVERROR_UNKNOWN;
1672     }
1673
1674     if (rt->auth_tried) {
1675         av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1676         return AVERROR_UNKNOWN;
1677     }
1678
1679     rt->auth_params[0] = '\0';
1680
1681     if (strstr(desc, "code=403 need auth")) {
1682         snprintf(rt->auth_params, sizeof(rt->auth_params),
1683                  "?authmod=%s&user=%s", authmod, rt->username);
1684         return 0;
1685     }
1686
1687     if (!(cptr = strstr(desc, "?reason=needauth"))) {
1688         av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1689         return AVERROR_UNKNOWN;
1690     }
1691
1692     av_strlcpy(buf, cptr + 1, sizeof(buf));
1693     ptr = buf;
1694
1695     while (ptr) {
1696         char *next  = strchr(ptr, '&');
1697         char *value = strchr(ptr, '=');
1698         if (next)
1699             *next++ = '\0';
1700         if (value)
1701             *value++ = '\0';
1702         if (!strcmp(ptr, "user")) {
1703             user = value;
1704         } else if (!strcmp(ptr, "salt")) {
1705             salt = value;
1706         } else if (!strcmp(ptr, "opaque")) {
1707             opaque = value;
1708         } else if (!strcmp(ptr, "challenge")) {
1709             challenge = value;
1710         } else if (!strcmp(ptr, "nonce")) {
1711             nonce = value;
1712         }
1713         ptr = next;
1714     }
1715
1716     if (!strcmp(authmod, "adobe")) {
1717         if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1718             return ret;
1719     } else {
1720         if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1721             return ret;
1722     }
1723
1724     rt->auth_tried = 1;
1725     return 0;
1726 }
1727
1728 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1729 {
1730     RTMPContext *rt = s->priv_data;
1731     const uint8_t *data_end = pkt->data + pkt->size;
1732     char *tracked_method = NULL;
1733     int level = AV_LOG_ERROR;
1734     uint8_t tmpstr[256];
1735     int ret;
1736
1737     if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1738         return ret;
1739
1740     if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1741                                 "description", tmpstr, sizeof(tmpstr))) {
1742         if (tracked_method && (!strcmp(tracked_method, "_checkbw")      ||
1743                                !strcmp(tracked_method, "releaseStream") ||
1744                                !strcmp(tracked_method, "FCSubscribe")   ||
1745                                !strcmp(tracked_method, "FCPublish"))) {
1746             /* Gracefully ignore Adobe-specific historical artifact errors. */
1747             level = AV_LOG_WARNING;
1748             ret = 0;
1749         } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1750             ret = handle_connect_error(s, tmpstr);
1751             if (!ret) {
1752                 rt->do_reconnect = 1;
1753                 level = AV_LOG_VERBOSE;
1754             }
1755         } else
1756             ret = AVERROR_UNKNOWN;
1757         av_log(s, level, "Server error: %s\n", tmpstr);
1758     }
1759
1760     av_free(tracked_method);
1761     return ret;
1762 }
1763
1764 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1765 {
1766     RTMPContext *rt = s->priv_data;
1767     double seqnum;
1768     char filename[64];
1769     char command[64];
1770     char statusmsg[128];
1771     int stringlen;
1772     char *pchar;
1773     const uint8_t *p = pkt->data;
1774     uint8_t *pp      = NULL;
1775     RTMPPacket spkt  = { 0 };
1776     GetByteContext gbc;
1777     int ret;
1778
1779     bytestream2_init(&gbc, p, pkt->size);
1780     if (ff_amf_read_string(&gbc, command, sizeof(command),
1781                            &stringlen)) {
1782         av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1783         return AVERROR_INVALIDDATA;
1784     }
1785
1786     ret = ff_amf_read_number(&gbc, &seqnum);
1787     if (ret)
1788         return ret;
1789     ret = ff_amf_read_null(&gbc);
1790     if (ret)
1791         return ret;
1792     if (!strcmp(command, "FCPublish") ||
1793         !strcmp(command, "publish")) {
1794         ret = ff_amf_read_string(&gbc, filename,
1795                                  sizeof(filename), &stringlen);
1796         // check with url
1797         if (s->filename) {
1798             pchar = strrchr(s->filename, '/');
1799             if (!pchar) {
1800                 av_log(s, AV_LOG_WARNING,
1801                        "Unable to find / in url %s, bad format\n",
1802                        s->filename);
1803                 pchar = s->filename;
1804             }
1805             pchar++;
1806             if (strcmp(pchar, filename))
1807                 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1808                        " %s\n", filename, pchar);
1809         }
1810         rt->state = STATE_RECEIVING;
1811     }
1812
1813     if (!strcmp(command, "FCPublish")) {
1814         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1815                                          RTMP_PT_INVOKE, 0,
1816                                          RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1817             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1818             return ret;
1819         }
1820         pp = spkt.data;
1821         ff_amf_write_string(&pp, "onFCPublish");
1822     } else if (!strcmp(command, "publish")) {
1823         PutByteContext pbc;
1824         // Send Stream Begin 1
1825         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1826                                          RTMP_PT_PING, 0, 6)) < 0) {
1827             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1828             return ret;
1829         }
1830         pp = spkt.data;
1831         bytestream2_init_writer(&pbc, pp, spkt.size);
1832         bytestream2_put_be16(&pbc, 0);          // 0 -> Stream Begin
1833         bytestream2_put_be32(&pbc, rt->nb_streamid);
1834         ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1835                                    rt->prev_pkt[1]);
1836         ff_rtmp_packet_destroy(&spkt);
1837         if (ret < 0)
1838             return ret;
1839
1840         // Send onStatus(NetStream.Publish.Start)
1841         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1842                                          RTMP_PT_INVOKE, 0,
1843                                          RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1844             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1845             return ret;
1846         }
1847         spkt.extra = pkt->extra;
1848         pp = spkt.data;
1849         ff_amf_write_string(&pp, "onStatus");
1850         ff_amf_write_number(&pp, 0);
1851         ff_amf_write_null(&pp);
1852
1853         ff_amf_write_object_start(&pp);
1854         ff_amf_write_field_name(&pp, "level");
1855         ff_amf_write_string(&pp, "status");
1856         ff_amf_write_field_name(&pp, "code");
1857         ff_amf_write_string(&pp, "NetStream.Publish.Start");
1858         ff_amf_write_field_name(&pp, "description");
1859         snprintf(statusmsg, sizeof(statusmsg),
1860                  "%s is now published", filename);
1861         ff_amf_write_string(&pp, statusmsg);
1862         ff_amf_write_field_name(&pp, "details");
1863         ff_amf_write_string(&pp, filename);
1864         ff_amf_write_field_name(&pp, "clientid");
1865         snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1866         ff_amf_write_string(&pp, statusmsg);
1867         ff_amf_write_object_end(&pp);
1868
1869     } else {
1870         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1871                                          RTMP_PT_INVOKE, 0,
1872                                          RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1873             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1874             return ret;
1875         }
1876         pp = spkt.data;
1877         ff_amf_write_string(&pp, "_result");
1878         ff_amf_write_number(&pp, seqnum);
1879         ff_amf_write_null(&pp);
1880         if (!strcmp(command, "createStream")) {
1881             rt->nb_streamid++;
1882             if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1883                 rt->nb_streamid++; /* Values 0 and 2 are reserved */
1884             ff_amf_write_number(&pp, rt->nb_streamid);
1885             /* By now we don't control which streams are removed in
1886              * deleteStream. There is no stream creation control
1887              * if a client creates more than 2^32 - 2 streams. */
1888         }
1889     }
1890     spkt.size = pp - spkt.data;
1891     ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1892                                rt->prev_pkt[1]);
1893     ff_rtmp_packet_destroy(&spkt);
1894     return ret;
1895 }
1896
1897 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1898 {
1899     RTMPContext *rt = s->priv_data;
1900     char *tracked_method = NULL;
1901     int ret = 0;
1902
1903     if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1904         return ret;
1905
1906     if (!tracked_method) {
1907         /* Ignore this reply when the current method is not tracked. */
1908         return ret;
1909     }
1910
1911     if (!strcmp(tracked_method, "connect")) {
1912         if (!rt->is_input) {
1913             if ((ret = gen_release_stream(s, rt)) < 0)
1914                 goto fail;
1915
1916             if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1917                 goto fail;
1918         } else {
1919             if ((ret = gen_server_bw(s, rt)) < 0)
1920                 goto fail;
1921         }
1922
1923         if ((ret = gen_create_stream(s, rt)) < 0)
1924             goto fail;
1925
1926         if (rt->is_input) {
1927             /* Send the FCSubscribe command when the name of live
1928              * stream is defined by the user or if it's a live stream. */
1929             if (rt->subscribe) {
1930                 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1931                     goto fail;
1932             } else if (rt->live == -1) {
1933                 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1934                     goto fail;
1935             }
1936         }
1937     } else if (!strcmp(tracked_method, "createStream")) {
1938         //extract a number from the result
1939         if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1940             av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
1941         } else {
1942             rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
1943         }
1944
1945         if (!rt->is_input) {
1946             if ((ret = gen_publish(s, rt)) < 0)
1947                 goto fail;
1948         } else {
1949             if ((ret = gen_play(s, rt)) < 0)
1950                 goto fail;
1951             if ((ret = gen_buffer_time(s, rt)) < 0)
1952                 goto fail;
1953         }
1954     }
1955
1956 fail:
1957     av_free(tracked_method);
1958     return ret;
1959 }
1960
1961 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
1962 {
1963     RTMPContext *rt = s->priv_data;
1964     const uint8_t *data_end = pkt->data + pkt->size;
1965     const uint8_t *ptr = pkt->data + 11;
1966     uint8_t tmpstr[256];
1967     int i, t;
1968
1969     for (i = 0; i < 2; i++) {
1970         t = ff_amf_tag_size(ptr, data_end);
1971         if (t < 0)
1972             return 1;
1973         ptr += t;
1974     }
1975
1976     t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
1977     if (!t && !strcmp(tmpstr, "error")) {
1978         if (!ff_amf_get_field_value(ptr, data_end,
1979                                     "description", tmpstr, sizeof(tmpstr)))
1980             av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
1981         return -1;
1982     }
1983
1984     t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
1985     if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
1986     if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
1987     if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
1988     if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
1989     if (!t && !strcmp(tmpstr, "NetStream.Seek.Notify")) rt->state = STATE_PLAYING;
1990
1991     return 0;
1992 }
1993
1994 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
1995 {
1996     RTMPContext *rt = s->priv_data;
1997     int ret = 0;
1998
1999     //TODO: check for the messages sent for wrong state?
2000     if (ff_amf_match_string(pkt->data, pkt->size, "_error")) {
2001         if ((ret = handle_invoke_error(s, pkt)) < 0)
2002             return ret;
2003     } else if (ff_amf_match_string(pkt->data, pkt->size, "_result")) {
2004         if ((ret = handle_invoke_result(s, pkt)) < 0)
2005             return ret;
2006     } else if (ff_amf_match_string(pkt->data, pkt->size, "onStatus")) {
2007         if ((ret = handle_invoke_status(s, pkt)) < 0)
2008             return ret;
2009     } else if (ff_amf_match_string(pkt->data, pkt->size, "onBWDone")) {
2010         if ((ret = gen_check_bw(s, rt)) < 0)
2011             return ret;
2012     } else if (ff_amf_match_string(pkt->data, pkt->size, "releaseStream") ||
2013                ff_amf_match_string(pkt->data, pkt->size, "FCPublish")     ||
2014                ff_amf_match_string(pkt->data, pkt->size, "publish")       ||
2015                ff_amf_match_string(pkt->data, pkt->size, "_checkbw")      ||
2016                ff_amf_match_string(pkt->data, pkt->size, "createStream")) {
2017         if ((ret = send_invoke_response(s, pkt)) < 0)
2018             return ret;
2019     }
2020
2021     return ret;
2022 }
2023
2024 static int handle_notify(URLContext *s, RTMPPacket *pkt) {
2025     RTMPContext *rt  = s->priv_data;
2026     const uint8_t *p = NULL;
2027     uint8_t *cp      = NULL;
2028     uint8_t commandbuffer[64];
2029     char statusmsg[128];
2030     int stringlen;
2031     GetByteContext gbc;
2032     PutByteContext pbc;
2033     uint32_t ts;
2034     int old_flv_size;
2035     const uint8_t *datatowrite;
2036     unsigned datatowritelength;
2037
2038     p = pkt->data;
2039     bytestream2_init(&gbc, p, pkt->size);
2040     if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2041                            &stringlen))
2042         return AVERROR_INVALIDDATA;
2043     if (!strcmp(commandbuffer, "@setDataFrame")) {
2044         datatowrite       = gbc.buffer;
2045         datatowritelength = bytestream2_get_bytes_left(&gbc);
2046         if (ff_amf_read_string(&gbc, statusmsg,
2047                                sizeof(statusmsg), &stringlen))
2048             return AVERROR_INVALIDDATA;
2049         if (strcmp(statusmsg, "onMetaData")) {
2050             av_log(s, AV_LOG_INFO, "Expecting onMetadata but got %s\n",
2051                    statusmsg);
2052             return 0;
2053         }
2054
2055         /* Provide ECMAArray to flv */
2056         ts = pkt->timestamp;
2057
2058         // generate packet header and put data into buffer for FLV demuxer
2059         if (rt->flv_off < rt->flv_size) {
2060             old_flv_size  = rt->flv_size;
2061             rt->flv_size += datatowritelength + 15;
2062         } else {
2063             old_flv_size = 0;
2064             rt->flv_size = datatowritelength + 15;
2065             rt->flv_off  = 0;
2066         }
2067
2068         cp = av_realloc(rt->flv_data, rt->flv_size);
2069         if (!cp)
2070             return AVERROR(ENOMEM);
2071         rt->flv_data = cp;
2072         bytestream2_init_writer(&pbc, cp, rt->flv_size);
2073         bytestream2_skip_p(&pbc, old_flv_size);
2074         bytestream2_put_byte(&pbc, pkt->type);
2075         bytestream2_put_be24(&pbc, datatowritelength);
2076         bytestream2_put_be24(&pbc, ts);
2077         bytestream2_put_byte(&pbc, ts >> 24);
2078         bytestream2_put_be24(&pbc, 0);
2079         bytestream2_put_buffer(&pbc, datatowrite, datatowritelength);
2080         bytestream2_put_be32(&pbc, 0);
2081     }
2082     return 0;
2083 }
2084
2085 /**
2086  * Parse received packet and possibly perform some action depending on
2087  * the packet contents.
2088  * @return 0 for no errors, negative values for serious errors which prevent
2089  *         further communications, positive values for uncritical errors
2090  */
2091 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
2092 {
2093     int ret;
2094
2095 #ifdef DEBUG
2096     ff_rtmp_packet_dump(s, pkt);
2097 #endif
2098
2099     switch (pkt->type) {
2100     case RTMP_PT_BYTES_READ:
2101         av_dlog(s, "received bytes read report\n");
2102         break;
2103     case RTMP_PT_CHUNK_SIZE:
2104         if ((ret = handle_chunk_size(s, pkt)) < 0)
2105             return ret;
2106         break;
2107     case RTMP_PT_PING:
2108         if ((ret = handle_ping(s, pkt)) < 0)
2109             return ret;
2110         break;
2111     case RTMP_PT_CLIENT_BW:
2112         if ((ret = handle_client_bw(s, pkt)) < 0)
2113             return ret;
2114         break;
2115     case RTMP_PT_SERVER_BW:
2116         if ((ret = handle_server_bw(s, pkt)) < 0)
2117             return ret;
2118         break;
2119     case RTMP_PT_INVOKE:
2120         if ((ret = handle_invoke(s, pkt)) < 0)
2121             return ret;
2122         break;
2123     case RTMP_PT_VIDEO:
2124     case RTMP_PT_AUDIO:
2125     case RTMP_PT_METADATA:
2126     case RTMP_PT_NOTIFY:
2127         /* Audio, Video and Metadata packets are parsed in get_packet() */
2128         break;
2129     default:
2130         av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2131         break;
2132     }
2133     return 0;
2134 }
2135
2136 /**
2137  * Interact with the server by receiving and sending RTMP packets until
2138  * there is some significant data (media data or expected status notification).
2139  *
2140  * @param s          reading context
2141  * @param for_header non-zero value tells function to work until it
2142  * gets notification from the server that playing has been started,
2143  * otherwise function will work until some media data is received (or
2144  * an error happens)
2145  * @return 0 for successful operation, negative value in case of error
2146  */
2147 static int get_packet(URLContext *s, int for_header)
2148 {
2149     RTMPContext *rt = s->priv_data;
2150     int ret;
2151     uint8_t *p;
2152     const uint8_t *next;
2153     uint32_t size;
2154     uint32_t ts, cts, pts=0;
2155
2156     if (rt->state == STATE_STOPPED)
2157         return AVERROR_EOF;
2158
2159     for (;;) {
2160         RTMPPacket rpkt = { 0 };
2161         if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2162                                        rt->in_chunk_size, rt->prev_pkt[0])) <= 0) {
2163             if (ret == 0) {
2164                 return AVERROR(EAGAIN);
2165             } else {
2166                 return AVERROR(EIO);
2167             }
2168         }
2169         rt->bytes_read += ret;
2170         if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
2171             av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2172             if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2173                 return ret;
2174             rt->last_bytes_read = rt->bytes_read;
2175         }
2176
2177         ret = rtmp_parse_result(s, rt, &rpkt);
2178
2179         // At this point we must check if we are in the seek state and continue
2180         // with the next packet. handle_invoke will get us out of this state
2181         // when the right message is encountered
2182         if (rt->state == STATE_SEEKING) {
2183             ff_rtmp_packet_destroy(&rpkt);
2184             // We continue, let the natural flow of things happen:
2185             // AVERROR(EAGAIN) or handle_invoke gets us out of here
2186             continue;
2187         }
2188
2189         if (ret < 0) {//serious error in current packet
2190             ff_rtmp_packet_destroy(&rpkt);
2191             return ret;
2192         }
2193         if (rt->do_reconnect && for_header) {
2194             ff_rtmp_packet_destroy(&rpkt);
2195             return 0;
2196         }
2197         if (rt->state == STATE_STOPPED) {
2198             ff_rtmp_packet_destroy(&rpkt);
2199             return AVERROR_EOF;
2200         }
2201         if (for_header && (rt->state == STATE_PLAYING    ||
2202                            rt->state == STATE_PUBLISHING ||
2203                            rt->state == STATE_RECEIVING)) {
2204             ff_rtmp_packet_destroy(&rpkt);
2205             return 0;
2206         }
2207         if (!rpkt.size || !rt->is_input) {
2208             ff_rtmp_packet_destroy(&rpkt);
2209             continue;
2210         }
2211         if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
2212            (rpkt.type == RTMP_PT_NOTIFY &&
2213             ff_amf_match_string(rpkt.data, rpkt.size, "onMetaData"))) {
2214             ts = rpkt.timestamp;
2215
2216             // generate packet header and put data into buffer for FLV demuxer
2217             rt->flv_off  = 0;
2218             rt->flv_size = rpkt.size + 15;
2219             rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
2220             bytestream_put_byte(&p, rpkt.type);
2221             bytestream_put_be24(&p, rpkt.size);
2222             bytestream_put_be24(&p, ts);
2223             bytestream_put_byte(&p, ts >> 24);
2224             bytestream_put_be24(&p, 0);
2225             bytestream_put_buffer(&p, rpkt.data, rpkt.size);
2226             bytestream_put_be32(&p, 0);
2227             ff_rtmp_packet_destroy(&rpkt);
2228             return 0;
2229         } else if (rpkt.type == RTMP_PT_NOTIFY) {
2230             ret = handle_notify(s, &rpkt);
2231             ff_rtmp_packet_destroy(&rpkt);
2232             if (ret) {
2233                 av_log(s, AV_LOG_ERROR, "Handle notify error\n");
2234                 return ret;
2235             }
2236             return 0;
2237         } else if (rpkt.type == RTMP_PT_METADATA) {
2238             // we got raw FLV data, make it available for FLV demuxer
2239             rt->flv_off  = 0;
2240             rt->flv_size = rpkt.size;
2241             rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2242             /* rewrite timestamps */
2243             next = rpkt.data;
2244             ts = rpkt.timestamp;
2245             while (next - rpkt.data < rpkt.size - 11) {
2246                 next++;
2247                 size = bytestream_get_be24(&next);
2248                 p=next;
2249                 cts = bytestream_get_be24(&next);
2250                 cts |= bytestream_get_byte(&next) << 24;
2251                 if (pts==0)
2252                     pts=cts;
2253                 ts += cts - pts;
2254                 pts = cts;
2255                 bytestream_put_be24(&p, ts);
2256                 bytestream_put_byte(&p, ts >> 24);
2257                 next += size + 3 + 4;
2258             }
2259             memcpy(rt->flv_data, rpkt.data, rpkt.size);
2260             ff_rtmp_packet_destroy(&rpkt);
2261             return 0;
2262         }
2263         ff_rtmp_packet_destroy(&rpkt);
2264     }
2265 }
2266
2267 static int rtmp_close(URLContext *h)
2268 {
2269     RTMPContext *rt = h->priv_data;
2270     int ret = 0;
2271
2272     if (!rt->is_input) {
2273         rt->flv_data = NULL;
2274         if (rt->out_pkt.size)
2275             ff_rtmp_packet_destroy(&rt->out_pkt);
2276         if (rt->state > STATE_FCPUBLISH)
2277             ret = gen_fcunpublish_stream(h, rt);
2278     }
2279     if (rt->state > STATE_HANDSHAKED)
2280         ret = gen_delete_stream(h, rt);
2281
2282     free_tracked_methods(rt);
2283     av_freep(&rt->flv_data);
2284     ffurl_close(rt->stream);
2285     return ret;
2286 }
2287
2288 /**
2289  * Open RTMP connection and verify that the stream can be played.
2290  *
2291  * URL syntax: rtmp://server[:port][/app][/playpath]
2292  *             where 'app' is first one or two directories in the path
2293  *             (e.g. /ondemand/, /flash/live/, etc.)
2294  *             and 'playpath' is a file name (the rest of the path,
2295  *             may be prefixed with "mp4:")
2296  */
2297 static int rtmp_open(URLContext *s, const char *uri, int flags)
2298 {
2299     RTMPContext *rt = s->priv_data;
2300     char proto[8], hostname[256], path[1024], auth[100], *fname;
2301     char *old_app;
2302     uint8_t buf[2048];
2303     int port;
2304     AVDictionary *opts = NULL;
2305     int ret;
2306
2307     if (rt->listen_timeout > 0)
2308         rt->listen = 1;
2309
2310     rt->is_input = !(flags & AVIO_FLAG_WRITE);
2311
2312     av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2313                  hostname, sizeof(hostname), &port,
2314                  path, sizeof(path), s->filename);
2315
2316     if (strchr(path, ' ')) {
2317         av_log(s, AV_LOG_WARNING,
2318                "Detected librtmp style URL parameters, these aren't supported "
2319                "by the libavformat internal RTMP handler currently enabled. "
2320                "See the documentation for the correct way to pass parameters.\n");
2321     }
2322
2323     if (auth[0]) {
2324         char *ptr = strchr(auth, ':');
2325         if (ptr) {
2326             *ptr = '\0';
2327             av_strlcpy(rt->username, auth, sizeof(rt->username));
2328             av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2329         }
2330     }
2331
2332     if (rt->listen && strcmp(proto, "rtmp")) {
2333         av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2334                proto);
2335         return AVERROR(EINVAL);
2336     }
2337     if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2338         if (!strcmp(proto, "rtmpts"))
2339             av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2340
2341         /* open the http tunneling connection */
2342         ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2343     } else if (!strcmp(proto, "rtmps")) {
2344         /* open the tls connection */
2345         if (port < 0)
2346             port = RTMPS_DEFAULT_PORT;
2347         ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2348     } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2349         if (!strcmp(proto, "rtmpte"))
2350             av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2351
2352         /* open the encrypted connection */
2353         ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2354         rt->encrypted = 1;
2355     } else {
2356         /* open the tcp connection */
2357         if (port < 0)
2358             port = RTMP_DEFAULT_PORT;
2359         if (rt->listen)
2360             ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2361                         "?listen&listen_timeout=%d",
2362                         rt->listen_timeout * 1000);
2363         else
2364             ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2365     }
2366
2367 reconnect:
2368     if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2369                           &s->interrupt_callback, &opts)) < 0) {
2370         av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2371         goto fail;
2372     }
2373
2374     if (rt->swfverify) {
2375         if ((ret = rtmp_calc_swfhash(s)) < 0)
2376             goto fail;
2377     }
2378
2379     rt->state = STATE_START;
2380     if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2381         goto fail;
2382     if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2383         goto fail;
2384
2385     rt->out_chunk_size = 128;
2386     rt->in_chunk_size  = 128; // Probably overwritten later
2387     rt->state = STATE_HANDSHAKED;
2388
2389     // Keep the application name when it has been defined by the user.
2390     old_app = rt->app;
2391
2392     rt->app = av_malloc(APP_MAX_LENGTH);
2393     if (!rt->app) {
2394         ret = AVERROR(ENOMEM);
2395         goto fail;
2396     }
2397
2398     //extract "app" part from path
2399     if (!strncmp(path, "/ondemand/", 10)) {
2400         fname = path + 10;
2401         memcpy(rt->app, "ondemand", 9);
2402     } else {
2403         char *next = *path ? path + 1 : path;
2404         char *p = strchr(next, '/');
2405         if (!p) {
2406             fname = next;
2407             rt->app[0] = '\0';
2408         } else {
2409             // make sure we do not mismatch a playpath for an application instance
2410             char *c = strchr(p + 1, ':');
2411             fname = strchr(p + 1, '/');
2412             if (!fname || (c && c < fname)) {
2413                 fname = p + 1;
2414                 av_strlcpy(rt->app, path + 1, FFMIN(p - path, APP_MAX_LENGTH));
2415             } else {
2416                 fname++;
2417                 av_strlcpy(rt->app, path + 1, FFMIN(fname - path - 1, APP_MAX_LENGTH));
2418             }
2419         }
2420     }
2421
2422     if (old_app) {
2423         // The name of application has been defined by the user, override it.
2424         if (strlen(old_app) >= APP_MAX_LENGTH) {
2425             ret = AVERROR(EINVAL);
2426             goto fail;
2427         }
2428         av_free(rt->app);
2429         rt->app = old_app;
2430     }
2431
2432     if (!rt->playpath) {
2433         int len = strlen(fname);
2434
2435         rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2436         if (!rt->playpath) {
2437             ret = AVERROR(ENOMEM);
2438             goto fail;
2439         }
2440
2441         if (!strchr(fname, ':') && len >= 4 &&
2442             (!strcmp(fname + len - 4, ".f4v") ||
2443              !strcmp(fname + len - 4, ".mp4"))) {
2444             memcpy(rt->playpath, "mp4:", 5);
2445         } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
2446             fname[len - 4] = '\0';
2447         } else {
2448             rt->playpath[0] = 0;
2449         }
2450         av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
2451     }
2452
2453     if (!rt->tcurl) {
2454         rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2455         if (!rt->tcurl) {
2456             ret = AVERROR(ENOMEM);
2457             goto fail;
2458         }
2459         ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2460                     port, "/%s", rt->app);
2461     }
2462
2463     if (!rt->flashver) {
2464         rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2465         if (!rt->flashver) {
2466             ret = AVERROR(ENOMEM);
2467             goto fail;
2468         }
2469         if (rt->is_input) {
2470             snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2471                     RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2472                     RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2473         } else {
2474             snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2475                     "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2476         }
2477     }
2478
2479     rt->client_report_size = 1048576;
2480     rt->bytes_read = 0;
2481     rt->last_bytes_read = 0;
2482     rt->server_bw = 2500000;
2483
2484     av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2485            proto, path, rt->app, rt->playpath);
2486     if (!rt->listen) {
2487         if ((ret = gen_connect(s, rt)) < 0)
2488             goto fail;
2489     } else {
2490         if (read_connect(s, s->priv_data) < 0)
2491             goto fail;
2492         rt->is_input = 1;
2493     }
2494
2495     do {
2496         ret = get_packet(s, 1);
2497     } while (ret == EAGAIN);
2498     if (ret < 0)
2499         goto fail;
2500
2501     if (rt->do_reconnect) {
2502         ffurl_close(rt->stream);
2503         rt->stream       = NULL;
2504         rt->do_reconnect = 0;
2505         rt->nb_invokes   = 0;
2506         memset(rt->prev_pkt, 0, sizeof(rt->prev_pkt));
2507         free_tracked_methods(rt);
2508         goto reconnect;
2509     }
2510
2511     if (rt->is_input) {
2512         // generate FLV header for demuxer
2513         rt->flv_size = 13;
2514         rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2515         rt->flv_off  = 0;
2516         memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
2517     } else {
2518         rt->flv_size = 0;
2519         rt->flv_data = NULL;
2520         rt->flv_off  = 0;
2521         rt->skip_bytes = 13;
2522     }
2523
2524     s->max_packet_size = rt->stream->max_packet_size;
2525     s->is_streamed     = 1;
2526     return 0;
2527
2528 fail:
2529     av_dict_free(&opts);
2530     rtmp_close(s);
2531     return ret;
2532 }
2533
2534 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2535 {
2536     RTMPContext *rt = s->priv_data;
2537     int orig_size = size;
2538     int ret;
2539
2540     while (size > 0) {
2541         int data_left = rt->flv_size - rt->flv_off;
2542
2543         if (data_left >= size) {
2544             memcpy(buf, rt->flv_data + rt->flv_off, size);
2545             rt->flv_off += size;
2546             return orig_size;
2547         }
2548         if (data_left > 0) {
2549             memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2550             buf  += data_left;
2551             size -= data_left;
2552             rt->flv_off = rt->flv_size;
2553             return data_left;
2554         }
2555         if ((ret = get_packet(s, 0)) < 0)
2556            return ret;
2557     }
2558     return orig_size;
2559 }
2560
2561 static int64_t rtmp_seek(URLContext *s, int stream_index, int64_t timestamp,
2562                          int flags)
2563 {
2564     RTMPContext *rt = s->priv_data;
2565     int ret;
2566     av_log(s, AV_LOG_DEBUG,
2567            "Seek on stream index %d at timestamp %"PRId64" with flags %08x\n",
2568            stream_index, timestamp, flags);
2569     if ((ret = gen_seek(s, rt, timestamp)) < 0) {
2570         av_log(s, AV_LOG_ERROR,
2571                "Unable to send seek command on stream index %d at timestamp "
2572                "%"PRId64" with flags %08x\n",
2573                stream_index, timestamp, flags);
2574         return ret;
2575     }
2576     rt->flv_off = rt->flv_size;
2577     rt->state = STATE_SEEKING;
2578     return timestamp;
2579 }
2580
2581 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2582 {
2583     RTMPContext *rt = s->priv_data;
2584     int size_temp = size;
2585     int pktsize, pkttype;
2586     uint32_t ts;
2587     const uint8_t *buf_temp = buf;
2588     uint8_t c;
2589     int ret;
2590
2591     do {
2592         if (rt->skip_bytes) {
2593             int skip = FFMIN(rt->skip_bytes, size_temp);
2594             buf_temp       += skip;
2595             size_temp      -= skip;
2596             rt->skip_bytes -= skip;
2597             continue;
2598         }
2599
2600         if (rt->flv_header_bytes < 11) {
2601             const uint8_t *header = rt->flv_header;
2602             int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
2603             bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2604             rt->flv_header_bytes += copy;
2605             size_temp            -= copy;
2606             if (rt->flv_header_bytes < 11)
2607                 break;
2608
2609             pkttype = bytestream_get_byte(&header);
2610             pktsize = bytestream_get_be24(&header);
2611             ts = bytestream_get_be24(&header);
2612             ts |= bytestream_get_byte(&header) << 24;
2613             bytestream_get_be24(&header);
2614             rt->flv_size = pktsize;
2615
2616             //force 12bytes header
2617             if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2618                 pkttype == RTMP_PT_NOTIFY) {
2619                 if (pkttype == RTMP_PT_NOTIFY)
2620                     pktsize += 16;
2621                 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
2622             }
2623
2624             //this can be a big packet, it's better to send it right here
2625             if ((ret = ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL,
2626                                              pkttype, ts, pktsize)) < 0)
2627                 return ret;
2628
2629             rt->out_pkt.extra = rt->main_channel_id;
2630             rt->flv_data = rt->out_pkt.data;
2631
2632             if (pkttype == RTMP_PT_NOTIFY)
2633                 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2634         }
2635
2636         if (rt->flv_size - rt->flv_off > size_temp) {
2637             bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2638             rt->flv_off += size_temp;
2639             size_temp = 0;
2640         } else {
2641             bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2642             size_temp   -= rt->flv_size - rt->flv_off;
2643             rt->flv_off += rt->flv_size - rt->flv_off;
2644         }
2645
2646         if (rt->flv_off == rt->flv_size) {
2647             rt->skip_bytes = 4;
2648
2649             if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2650                 return ret;
2651             rt->flv_size = 0;
2652             rt->flv_off = 0;
2653             rt->flv_header_bytes = 0;
2654             rt->flv_nb_packets++;
2655         }
2656     } while (buf_temp - buf < size);
2657
2658     if (rt->flv_nb_packets < rt->flush_interval)
2659         return size;
2660     rt->flv_nb_packets = 0;
2661
2662     /* set stream into nonblocking mode */
2663     rt->stream->flags |= AVIO_FLAG_NONBLOCK;
2664
2665     /* try to read one byte from the stream */
2666     ret = ffurl_read(rt->stream, &c, 1);
2667
2668     /* switch the stream back into blocking mode */
2669     rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2670
2671     if (ret == AVERROR(EAGAIN)) {
2672         /* no incoming data to handle */
2673         return size;
2674     } else if (ret < 0) {
2675         return ret;
2676     } else if (ret == 1) {
2677         RTMPPacket rpkt = { 0 };
2678
2679         if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2680                                                 rt->in_chunk_size,
2681                                                 rt->prev_pkt[0], c)) <= 0)
2682              return ret;
2683
2684         if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2685             return ret;
2686
2687         ff_rtmp_packet_destroy(&rpkt);
2688     }
2689
2690     return size;
2691 }
2692
2693 #define OFFSET(x) offsetof(RTMPContext, x)
2694 #define DEC AV_OPT_FLAG_DECODING_PARAM
2695 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2696
2697 static const AVOption rtmp_options[] = {
2698     {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2699     {"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},
2700     {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2701     {"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},
2702     {"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},
2703     {"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"},
2704     {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
2705     {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
2706     {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
2707     {"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},
2708     {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2709     {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2710     {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2711     {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
2712     {"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},
2713     {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2714     {"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},
2715     {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2716     {"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" },
2717     { NULL },
2718 };
2719
2720 #define RTMP_PROTOCOL(flavor)                    \
2721 static const AVClass flavor##_class = {          \
2722     .class_name = #flavor,                       \
2723     .item_name  = av_default_item_name,          \
2724     .option     = rtmp_options,                  \
2725     .version    = LIBAVUTIL_VERSION_INT,         \
2726 };                                               \
2727                                                  \
2728 URLProtocol ff_##flavor##_protocol = {           \
2729     .name           = #flavor,                   \
2730     .url_open       = rtmp_open,                 \
2731     .url_read       = rtmp_read,                 \
2732     .url_read_seek  = rtmp_seek,                 \
2733     .url_write      = rtmp_write,                \
2734     .url_close      = rtmp_close,                \
2735     .priv_data_size = sizeof(RTMPContext),       \
2736     .flags          = URL_PROTOCOL_FLAG_NETWORK, \
2737     .priv_data_class= &flavor##_class,           \
2738 };
2739
2740
2741 RTMP_PROTOCOL(rtmp)
2742 RTMP_PROTOCOL(rtmpe)
2743 RTMP_PROTOCOL(rtmps)
2744 RTMP_PROTOCOL(rtmpt)
2745 RTMP_PROTOCOL(rtmpte)
2746 RTMP_PROTOCOL(rtmpts)