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