rtmp: rename data_size to size
[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     av_md5_final(md5, hash);
1616     ff_data_to_hex(hashstr2, hash, 16, 1);
1617     hashstr2[32] = '\0';
1618
1619     av_md5_init(md5);
1620     av_md5_update(md5, hashstr1, strlen(hashstr1));
1621     av_md5_update(md5, ":", 1);
1622     if (nonce)
1623         av_md5_update(md5, nonce, strlen(nonce));
1624     av_md5_update(md5, ":", 1);
1625     av_md5_update(md5, nc, strlen(nc));
1626     av_md5_update(md5, ":", 1);
1627     av_md5_update(md5, cnonce, strlen(cnonce));
1628     av_md5_update(md5, ":", 1);
1629     av_md5_update(md5, qop, strlen(qop));
1630     av_md5_update(md5, ":", 1);
1631     av_md5_update(md5, hashstr2, strlen(hashstr2));
1632     av_md5_final(md5, hash);
1633     ff_data_to_hex(hashstr1, hash, 16, 1);
1634
1635     snprintf(rt->auth_params, sizeof(rt->auth_params),
1636              "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1637              "llnw", user, nonce, cnonce, nc, hashstr1);
1638
1639     av_free(md5);
1640     return 0;
1641 }
1642
1643 static int handle_connect_error(URLContext *s, const char *desc)
1644 {
1645     RTMPContext *rt = s->priv_data;
1646     char buf[300], *ptr, authmod[15];
1647     int i = 0, ret = 0;
1648     const char *user = "", *salt = "", *opaque = NULL,
1649                *challenge = NULL, *cptr = NULL, *nonce = NULL;
1650
1651     if (!(cptr = strstr(desc, "authmod=adobe")) &&
1652         !(cptr = strstr(desc, "authmod=llnw"))) {
1653         av_log(s, AV_LOG_ERROR,
1654                "Unknown connect error (unsupported authentication method?)\n");
1655         return AVERROR_UNKNOWN;
1656     }
1657     cptr += strlen("authmod=");
1658     while (*cptr && *cptr != ' ' && i < sizeof(authmod) - 1)
1659         authmod[i++] = *cptr++;
1660     authmod[i] = '\0';
1661
1662     if (!rt->username[0] || !rt->password[0]) {
1663         av_log(s, AV_LOG_ERROR, "No credentials set\n");
1664         return AVERROR_UNKNOWN;
1665     }
1666
1667     if (strstr(desc, "?reason=authfailed")) {
1668         av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1669         return AVERROR_UNKNOWN;
1670     } else if (strstr(desc, "?reason=nosuchuser")) {
1671         av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1672         return AVERROR_UNKNOWN;
1673     }
1674
1675     if (rt->auth_tried) {
1676         av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1677         return AVERROR_UNKNOWN;
1678     }
1679
1680     rt->auth_params[0] = '\0';
1681
1682     if (strstr(desc, "code=403 need auth")) {
1683         snprintf(rt->auth_params, sizeof(rt->auth_params),
1684                  "?authmod=%s&user=%s", authmod, rt->username);
1685         return 0;
1686     }
1687
1688     if (!(cptr = strstr(desc, "?reason=needauth"))) {
1689         av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1690         return AVERROR_UNKNOWN;
1691     }
1692
1693     av_strlcpy(buf, cptr + 1, sizeof(buf));
1694     ptr = buf;
1695
1696     while (ptr) {
1697         char *next  = strchr(ptr, '&');
1698         char *value = strchr(ptr, '=');
1699         if (next)
1700             *next++ = '\0';
1701         if (value)
1702             *value++ = '\0';
1703         if (!strcmp(ptr, "user")) {
1704             user = value;
1705         } else if (!strcmp(ptr, "salt")) {
1706             salt = value;
1707         } else if (!strcmp(ptr, "opaque")) {
1708             opaque = value;
1709         } else if (!strcmp(ptr, "challenge")) {
1710             challenge = value;
1711         } else if (!strcmp(ptr, "nonce")) {
1712             nonce = value;
1713         }
1714         ptr = next;
1715     }
1716
1717     if (!strcmp(authmod, "adobe")) {
1718         if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1719             return ret;
1720     } else {
1721         if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1722             return ret;
1723     }
1724
1725     rt->auth_tried = 1;
1726     return 0;
1727 }
1728
1729 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1730 {
1731     RTMPContext *rt = s->priv_data;
1732     const uint8_t *data_end = pkt->data + pkt->size;
1733     char *tracked_method = NULL;
1734     int level = AV_LOG_ERROR;
1735     uint8_t tmpstr[256];
1736     int ret;
1737
1738     if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1739         return ret;
1740
1741     if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1742                                 "description", tmpstr, sizeof(tmpstr))) {
1743         if (tracked_method && (!strcmp(tracked_method, "_checkbw")      ||
1744                                !strcmp(tracked_method, "releaseStream") ||
1745                                !strcmp(tracked_method, "FCSubscribe")   ||
1746                                !strcmp(tracked_method, "FCPublish"))) {
1747             /* Gracefully ignore Adobe-specific historical artifact errors. */
1748             level = AV_LOG_WARNING;
1749             ret = 0;
1750         } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1751             ret = handle_connect_error(s, tmpstr);
1752             if (!ret) {
1753                 rt->do_reconnect = 1;
1754                 level = AV_LOG_VERBOSE;
1755             }
1756         } else
1757             ret = AVERROR_UNKNOWN;
1758         av_log(s, level, "Server error: %s\n", tmpstr);
1759     }
1760
1761     av_free(tracked_method);
1762     return ret;
1763 }
1764
1765 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1766 {
1767     RTMPContext *rt = s->priv_data;
1768     double seqnum;
1769     char filename[64];
1770     char command[64];
1771     char statusmsg[128];
1772     int stringlen;
1773     char *pchar;
1774     const uint8_t *p = pkt->data;
1775     uint8_t *pp      = NULL;
1776     RTMPPacket spkt  = { 0 };
1777     GetByteContext gbc;
1778     int ret;
1779
1780     bytestream2_init(&gbc, p, pkt->size);
1781     if (ff_amf_read_string(&gbc, command, sizeof(command),
1782                            &stringlen)) {
1783         av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1784         return AVERROR_INVALIDDATA;
1785     }
1786
1787     ret = ff_amf_read_number(&gbc, &seqnum);
1788     if (ret)
1789         return ret;
1790     ret = ff_amf_read_null(&gbc);
1791     if (ret)
1792         return ret;
1793     if (!strcmp(command, "FCPublish") ||
1794         !strcmp(command, "publish")) {
1795         ret = ff_amf_read_string(&gbc, filename,
1796                                  sizeof(filename), &stringlen);
1797         // check with url
1798         if (s->filename) {
1799             pchar = strrchr(s->filename, '/');
1800             if (!pchar) {
1801                 av_log(s, AV_LOG_WARNING,
1802                        "Unable to find / in url %s, bad format\n",
1803                        s->filename);
1804                 pchar = s->filename;
1805             }
1806             pchar++;
1807             if (strcmp(pchar, filename))
1808                 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1809                        " %s\n", filename, pchar);
1810         }
1811         rt->state = STATE_RECEIVING;
1812     }
1813
1814     if (!strcmp(command, "FCPublish")) {
1815         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1816                                          RTMP_PT_INVOKE, 0,
1817                                          RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1818             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1819             return ret;
1820         }
1821         pp = spkt.data;
1822         ff_amf_write_string(&pp, "onFCPublish");
1823     } else if (!strcmp(command, "publish")) {
1824         PutByteContext pbc;
1825         // Send Stream Begin 1
1826         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1827                                          RTMP_PT_PING, 0, 6)) < 0) {
1828             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1829             return ret;
1830         }
1831         pp = spkt.data;
1832         bytestream2_init_writer(&pbc, pp, spkt.size);
1833         bytestream2_put_be16(&pbc, 0);          // 0 -> Stream Begin
1834         bytestream2_put_be32(&pbc, rt->nb_streamid);
1835         ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1836                                    rt->prev_pkt[1]);
1837         ff_rtmp_packet_destroy(&spkt);
1838         if (ret < 0)
1839             return ret;
1840
1841         // Send onStatus(NetStream.Publish.Start)
1842         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1843                                          RTMP_PT_INVOKE, 0,
1844                                          RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1845             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1846             return ret;
1847         }
1848         spkt.extra = pkt->extra;
1849         pp = spkt.data;
1850         ff_amf_write_string(&pp, "onStatus");
1851         ff_amf_write_number(&pp, 0);
1852         ff_amf_write_null(&pp);
1853
1854         ff_amf_write_object_start(&pp);
1855         ff_amf_write_field_name(&pp, "level");
1856         ff_amf_write_string(&pp, "status");
1857         ff_amf_write_field_name(&pp, "code");
1858         ff_amf_write_string(&pp, "NetStream.Publish.Start");
1859         ff_amf_write_field_name(&pp, "description");
1860         snprintf(statusmsg, sizeof(statusmsg),
1861                  "%s is now published", filename);
1862         ff_amf_write_string(&pp, statusmsg);
1863         ff_amf_write_field_name(&pp, "details");
1864         ff_amf_write_string(&pp, filename);
1865         ff_amf_write_field_name(&pp, "clientid");
1866         snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1867         ff_amf_write_string(&pp, statusmsg);
1868         ff_amf_write_object_end(&pp);
1869
1870     } else {
1871         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1872                                          RTMP_PT_INVOKE, 0,
1873                                          RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1874             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1875             return ret;
1876         }
1877         pp = spkt.data;
1878         ff_amf_write_string(&pp, "_result");
1879         ff_amf_write_number(&pp, seqnum);
1880         ff_amf_write_null(&pp);
1881         if (!strcmp(command, "createStream")) {
1882             rt->nb_streamid++;
1883             if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1884                 rt->nb_streamid++; /* Values 0 and 2 are reserved */
1885             ff_amf_write_number(&pp, rt->nb_streamid);
1886             /* By now we don't control which streams are removed in
1887              * deleteStream. There is no stream creation control
1888              * if a client creates more than 2^32 - 2 streams. */
1889         }
1890     }
1891     spkt.size = pp - spkt.data;
1892     ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1893                                rt->prev_pkt[1]);
1894     ff_rtmp_packet_destroy(&spkt);
1895     return ret;
1896 }
1897
1898 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1899 {
1900     RTMPContext *rt = s->priv_data;
1901     char *tracked_method = NULL;
1902     int ret = 0;
1903
1904     if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1905         return ret;
1906
1907     if (!tracked_method) {
1908         /* Ignore this reply when the current method is not tracked. */
1909         return ret;
1910     }
1911
1912     if (!memcmp(tracked_method, "connect", 7)) {
1913         if (!rt->is_input) {
1914             if ((ret = gen_release_stream(s, rt)) < 0)
1915                 goto fail;
1916
1917             if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1918                 goto fail;
1919         } else {
1920             if ((ret = gen_server_bw(s, rt)) < 0)
1921                 goto fail;
1922         }
1923
1924         if ((ret = gen_create_stream(s, rt)) < 0)
1925             goto fail;
1926
1927         if (rt->is_input) {
1928             /* Send the FCSubscribe command when the name of live
1929              * stream is defined by the user or if it's a live stream. */
1930             if (rt->subscribe) {
1931                 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1932                     goto fail;
1933             } else if (rt->live == -1) {
1934                 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1935                     goto fail;
1936             }
1937         }
1938     } else if (!memcmp(tracked_method, "createStream", 12)) {
1939         //extract a number from the result
1940         if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1941             av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
1942         } else {
1943             rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
1944         }
1945
1946         if (!rt->is_input) {
1947             if ((ret = gen_publish(s, rt)) < 0)
1948                 goto fail;
1949         } else {
1950             if ((ret = gen_play(s, rt)) < 0)
1951                 goto fail;
1952             if ((ret = gen_buffer_time(s, rt)) < 0)
1953                 goto fail;
1954         }
1955     }
1956
1957 fail:
1958     av_free(tracked_method);
1959     return ret;
1960 }
1961
1962 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
1963 {
1964     RTMPContext *rt = s->priv_data;
1965     const uint8_t *data_end = pkt->data + pkt->size;
1966     const uint8_t *ptr = pkt->data + 11;
1967     uint8_t tmpstr[256];
1968     int i, t;
1969
1970     for (i = 0; i < 2; i++) {
1971         t = ff_amf_tag_size(ptr, data_end);
1972         if (t < 0)
1973             return 1;
1974         ptr += t;
1975     }
1976
1977     t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
1978     if (!t && !strcmp(tmpstr, "error")) {
1979         if (!ff_amf_get_field_value(ptr, data_end,
1980                                     "description", tmpstr, sizeof(tmpstr)))
1981             av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
1982         return -1;
1983     }
1984
1985     t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
1986     if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
1987     if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
1988     if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
1989     if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
1990     if (!t && !strcmp(tmpstr, "NetStream.Seek.Notify")) rt->state = STATE_PLAYING;
1991
1992     return 0;
1993 }
1994
1995 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
1996 {
1997     RTMPContext *rt = s->priv_data;
1998     int ret = 0;
1999
2000     //TODO: check for the messages sent for wrong state?
2001     if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
2002         if ((ret = handle_invoke_error(s, pkt)) < 0)
2003             return ret;
2004     } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
2005         if ((ret = handle_invoke_result(s, pkt)) < 0)
2006             return ret;
2007     } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
2008         if ((ret = handle_invoke_status(s, pkt)) < 0)
2009             return ret;
2010     } else if (!memcmp(pkt->data, "\002\000\010onBWDone", 11)) {
2011         if ((ret = gen_check_bw(s, rt)) < 0)
2012             return ret;
2013     } else if (!memcmp(pkt->data, "\002\000\015releaseStream", 16) ||
2014                !memcmp(pkt->data, "\002\000\011FCPublish", 12)     ||
2015                !memcmp(pkt->data, "\002\000\007publish", 10)       ||
2016                !memcmp(pkt->data, "\002\000\010_checkbw", 11)      ||
2017                !memcmp(pkt->data, "\002\000\014createStream", 15)) {
2018         if ((ret = send_invoke_response(s, pkt)) < 0)
2019             return ret;
2020     }
2021
2022     return ret;
2023 }
2024
2025 static int handle_notify(URLContext *s, RTMPPacket *pkt) {
2026     RTMPContext *rt  = s->priv_data;
2027     const uint8_t *p = NULL;
2028     uint8_t *cp      = NULL;
2029     uint8_t commandbuffer[64];
2030     char statusmsg[128];
2031     int stringlen;
2032     GetByteContext gbc;
2033     PutByteContext pbc;
2034     uint32_t ts;
2035     int old_flv_size;
2036     const uint8_t *datatowrite;
2037     unsigned datatowritelength;
2038
2039     p = pkt->data;
2040     bytestream2_init(&gbc, p, pkt->size);
2041     if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2042                            &stringlen))
2043         return AVERROR_INVALIDDATA;
2044     if (!strcmp(commandbuffer, "@setDataFrame")) {
2045         datatowrite       = gbc.buffer;
2046         datatowritelength = bytestream2_get_bytes_left(&gbc);
2047         if (ff_amf_read_string(&gbc, statusmsg,
2048                                sizeof(statusmsg), &stringlen))
2049             return AVERROR_INVALIDDATA;
2050         if (strcmp(statusmsg, "onMetaData")) {
2051             av_log(s, AV_LOG_INFO, "Expecting onMetadata but got %s\n",
2052                    statusmsg);
2053             return 0;
2054         }
2055
2056         /* Provide ECMAArray to flv */
2057         ts = pkt->timestamp;
2058
2059         // generate packet header and put data into buffer for FLV demuxer
2060         if (rt->flv_off < rt->flv_size) {
2061             old_flv_size  = rt->flv_size;
2062             rt->flv_size += datatowritelength + 15;
2063         } else {
2064             old_flv_size = 0;
2065             rt->flv_size = datatowritelength + 15;
2066             rt->flv_off  = 0;
2067         }
2068
2069         cp = av_realloc(rt->flv_data, rt->flv_size);
2070         if (!cp)
2071             return AVERROR(ENOMEM);
2072         rt->flv_data = cp;
2073         bytestream2_init_writer(&pbc, cp, rt->flv_size);
2074         bytestream2_skip_p(&pbc, old_flv_size);
2075         bytestream2_put_byte(&pbc, pkt->type);
2076         bytestream2_put_be24(&pbc, datatowritelength);
2077         bytestream2_put_be24(&pbc, ts);
2078         bytestream2_put_byte(&pbc, ts >> 24);
2079         bytestream2_put_be24(&pbc, 0);
2080         bytestream2_put_buffer(&pbc, datatowrite, datatowritelength);
2081         bytestream2_put_be32(&pbc, 0);
2082     }
2083     return 0;
2084 }
2085
2086 /**
2087  * Parse received packet and possibly perform some action depending on
2088  * the packet contents.
2089  * @return 0 for no errors, negative values for serious errors which prevent
2090  *         further communications, positive values for uncritical errors
2091  */
2092 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
2093 {
2094     int ret;
2095
2096 #ifdef DEBUG
2097     ff_rtmp_packet_dump(s, pkt);
2098 #endif
2099
2100     switch (pkt->type) {
2101     case RTMP_PT_BYTES_READ:
2102         av_dlog(s, "received bytes read report\n");
2103         break;
2104     case RTMP_PT_CHUNK_SIZE:
2105         if ((ret = handle_chunk_size(s, pkt)) < 0)
2106             return ret;
2107         break;
2108     case RTMP_PT_PING:
2109         if ((ret = handle_ping(s, pkt)) < 0)
2110             return ret;
2111         break;
2112     case RTMP_PT_CLIENT_BW:
2113         if ((ret = handle_client_bw(s, pkt)) < 0)
2114             return ret;
2115         break;
2116     case RTMP_PT_SERVER_BW:
2117         if ((ret = handle_server_bw(s, pkt)) < 0)
2118             return ret;
2119         break;
2120     case RTMP_PT_INVOKE:
2121         if ((ret = handle_invoke(s, pkt)) < 0)
2122             return ret;
2123         break;
2124     case RTMP_PT_VIDEO:
2125     case RTMP_PT_AUDIO:
2126     case RTMP_PT_METADATA:
2127     case RTMP_PT_NOTIFY:
2128         /* Audio, Video and Metadata packets are parsed in get_packet() */
2129         break;
2130     default:
2131         av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2132         break;
2133     }
2134     return 0;
2135 }
2136
2137 /**
2138  * Interact with the server by receiving and sending RTMP packets until
2139  * there is some significant data (media data or expected status notification).
2140  *
2141  * @param s          reading context
2142  * @param for_header non-zero value tells function to work until it
2143  * gets notification from the server that playing has been started,
2144  * otherwise function will work until some media data is received (or
2145  * an error happens)
2146  * @return 0 for successful operation, negative value in case of error
2147  */
2148 static int get_packet(URLContext *s, int for_header)
2149 {
2150     RTMPContext *rt = s->priv_data;
2151     int ret;
2152     uint8_t *p;
2153     const uint8_t *next;
2154     uint32_t size;
2155     uint32_t ts, cts, pts=0;
2156
2157     if (rt->state == STATE_STOPPED)
2158         return AVERROR_EOF;
2159
2160     for (;;) {
2161         RTMPPacket rpkt = { 0 };
2162         if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2163                                        rt->in_chunk_size, rt->prev_pkt[0])) <= 0) {
2164             if (ret == 0) {
2165                 return AVERROR(EAGAIN);
2166             } else {
2167                 return AVERROR(EIO);
2168             }
2169         }
2170         rt->bytes_read += ret;
2171         if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
2172             av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2173             if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2174                 return ret;
2175             rt->last_bytes_read = rt->bytes_read;
2176         }
2177
2178         ret = rtmp_parse_result(s, rt, &rpkt);
2179
2180         // At this point we must check if we are in the seek state and continue
2181         // with the next packet. handle_invoke will get us out of this state
2182         // when the right message is encountered
2183         if (rt->state == STATE_SEEKING) {
2184             ff_rtmp_packet_destroy(&rpkt);
2185             // We continue, let the natural flow of things happen:
2186             // AVERROR(EAGAIN) or handle_invoke gets us out of here
2187             continue;
2188         }
2189
2190         if (ret < 0) {//serious error in current packet
2191             ff_rtmp_packet_destroy(&rpkt);
2192             return ret;
2193         }
2194         if (rt->do_reconnect && for_header) {
2195             ff_rtmp_packet_destroy(&rpkt);
2196             return 0;
2197         }
2198         if (rt->state == STATE_STOPPED) {
2199             ff_rtmp_packet_destroy(&rpkt);
2200             return AVERROR_EOF;
2201         }
2202         if (for_header && (rt->state == STATE_PLAYING    ||
2203                            rt->state == STATE_PUBLISHING ||
2204                            rt->state == STATE_RECEIVING)) {
2205             ff_rtmp_packet_destroy(&rpkt);
2206             return 0;
2207         }
2208         if (!rpkt.size || !rt->is_input) {
2209             ff_rtmp_packet_destroy(&rpkt);
2210             continue;
2211         }
2212         if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
2213            (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
2214             ts = rpkt.timestamp;
2215
2216             // generate packet header and put data into buffer for FLV demuxer
2217             rt->flv_off  = 0;
2218             rt->flv_size = rpkt.size + 15;
2219             rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
2220             bytestream_put_byte(&p, rpkt.type);
2221             bytestream_put_be24(&p, rpkt.size);
2222             bytestream_put_be24(&p, ts);
2223             bytestream_put_byte(&p, ts >> 24);
2224             bytestream_put_be24(&p, 0);
2225             bytestream_put_buffer(&p, rpkt.data, rpkt.size);
2226             bytestream_put_be32(&p, 0);
2227             ff_rtmp_packet_destroy(&rpkt);
2228             return 0;
2229         } else if (rpkt.type == RTMP_PT_NOTIFY) {
2230             ret = handle_notify(s, &rpkt);
2231             ff_rtmp_packet_destroy(&rpkt);
2232             if (ret) {
2233                 av_log(s, AV_LOG_ERROR, "Handle notify error\n");
2234                 return ret;
2235             }
2236             return 0;
2237         } else if (rpkt.type == RTMP_PT_METADATA) {
2238             // we got raw FLV data, make it available for FLV demuxer
2239             rt->flv_off  = 0;
2240             rt->flv_size = rpkt.size;
2241             rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2242             /* rewrite timestamps */
2243             next = rpkt.data;
2244             ts = rpkt.timestamp;
2245             while (next - rpkt.data < rpkt.size - 11) {
2246                 next++;
2247                 size = bytestream_get_be24(&next);
2248                 p=next;
2249                 cts = bytestream_get_be24(&next);
2250                 cts |= bytestream_get_byte(&next) << 24;
2251                 if (pts==0)
2252                     pts=cts;
2253                 ts += cts - pts;
2254                 pts = cts;
2255                 bytestream_put_be24(&p, ts);
2256                 bytestream_put_byte(&p, ts >> 24);
2257                 next += size + 3 + 4;
2258             }
2259             memcpy(rt->flv_data, rpkt.data, rpkt.size);
2260             ff_rtmp_packet_destroy(&rpkt);
2261             return 0;
2262         }
2263         ff_rtmp_packet_destroy(&rpkt);
2264     }
2265 }
2266
2267 static int rtmp_close(URLContext *h)
2268 {
2269     RTMPContext *rt = h->priv_data;
2270     int ret = 0;
2271
2272     if (!rt->is_input) {
2273         rt->flv_data = NULL;
2274         if (rt->out_pkt.size)
2275             ff_rtmp_packet_destroy(&rt->out_pkt);
2276         if (rt->state > STATE_FCPUBLISH)
2277             ret = gen_fcunpublish_stream(h, rt);
2278     }
2279     if (rt->state > STATE_HANDSHAKED)
2280         ret = gen_delete_stream(h, rt);
2281
2282     free_tracked_methods(rt);
2283     av_freep(&rt->flv_data);
2284     ffurl_close(rt->stream);
2285     return ret;
2286 }
2287
2288 /**
2289  * Open RTMP connection and verify that the stream can be played.
2290  *
2291  * URL syntax: rtmp://server[:port][/app][/playpath]
2292  *             where 'app' is first one or two directories in the path
2293  *             (e.g. /ondemand/, /flash/live/, etc.)
2294  *             and 'playpath' is a file name (the rest of the path,
2295  *             may be prefixed with "mp4:")
2296  */
2297 static int rtmp_open(URLContext *s, const char *uri, int flags)
2298 {
2299     RTMPContext *rt = s->priv_data;
2300     char proto[8], hostname[256], path[1024], auth[100], *fname;
2301     char *old_app;
2302     uint8_t buf[2048];
2303     int port;
2304     AVDictionary *opts = NULL;
2305     int ret;
2306
2307     if (rt->listen_timeout > 0)
2308         rt->listen = 1;
2309
2310     rt->is_input = !(flags & AVIO_FLAG_WRITE);
2311
2312     av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2313                  hostname, sizeof(hostname), &port,
2314                  path, sizeof(path), s->filename);
2315
2316     if (auth[0]) {
2317         char *ptr = strchr(auth, ':');
2318         if (ptr) {
2319             *ptr = '\0';
2320             av_strlcpy(rt->username, auth, sizeof(rt->username));
2321             av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2322         }
2323     }
2324
2325     if (rt->listen && strcmp(proto, "rtmp")) {
2326         av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2327                proto);
2328         return AVERROR(EINVAL);
2329     }
2330     if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2331         if (!strcmp(proto, "rtmpts"))
2332             av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2333
2334         /* open the http tunneling connection */
2335         ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2336     } else if (!strcmp(proto, "rtmps")) {
2337         /* open the tls connection */
2338         if (port < 0)
2339             port = RTMPS_DEFAULT_PORT;
2340         ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2341     } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2342         if (!strcmp(proto, "rtmpte"))
2343             av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2344
2345         /* open the encrypted connection */
2346         ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2347         rt->encrypted = 1;
2348     } else {
2349         /* open the tcp connection */
2350         if (port < 0)
2351             port = RTMP_DEFAULT_PORT;
2352         if (rt->listen)
2353             ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2354                         "?listen&listen_timeout=%d",
2355                         rt->listen_timeout * 1000);
2356         else
2357             ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2358     }
2359
2360 reconnect:
2361     if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2362                           &s->interrupt_callback, &opts)) < 0) {
2363         av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2364         goto fail;
2365     }
2366
2367     if (rt->swfverify) {
2368         if ((ret = rtmp_calc_swfhash(s)) < 0)
2369             goto fail;
2370     }
2371
2372     rt->state = STATE_START;
2373     if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2374         goto fail;
2375     if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2376         goto fail;
2377
2378     rt->out_chunk_size = 128;
2379     rt->in_chunk_size  = 128; // Probably overwritten later
2380     rt->state = STATE_HANDSHAKED;
2381
2382     // Keep the application name when it has been defined by the user.
2383     old_app = rt->app;
2384
2385     rt->app = av_malloc(APP_MAX_LENGTH);
2386     if (!rt->app) {
2387         ret = AVERROR(ENOMEM);
2388         goto fail;
2389     }
2390
2391     //extract "app" part from path
2392     if (!strncmp(path, "/ondemand/", 10)) {
2393         fname = path + 10;
2394         memcpy(rt->app, "ondemand", 9);
2395     } else {
2396         char *next = *path ? path + 1 : path;
2397         char *p = strchr(next, '/');
2398         if (!p) {
2399             fname = next;
2400             rt->app[0] = '\0';
2401         } else {
2402             // make sure we do not mismatch a playpath for an application instance
2403             char *c = strchr(p + 1, ':');
2404             fname = strchr(p + 1, '/');
2405             if (!fname || (c && c < fname)) {
2406                 fname = p + 1;
2407                 av_strlcpy(rt->app, path + 1, p - path);
2408             } else {
2409                 fname++;
2410                 av_strlcpy(rt->app, path + 1, fname - path - 1);
2411             }
2412         }
2413     }
2414
2415     if (old_app) {
2416         // The name of application has been defined by the user, override it.
2417         av_free(rt->app);
2418         rt->app = old_app;
2419     }
2420
2421     if (!rt->playpath) {
2422         int len = strlen(fname);
2423
2424         rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2425         if (!rt->playpath) {
2426             ret = AVERROR(ENOMEM);
2427             goto fail;
2428         }
2429
2430         if (!strchr(fname, ':') && len >= 4 &&
2431             (!strcmp(fname + len - 4, ".f4v") ||
2432              !strcmp(fname + len - 4, ".mp4"))) {
2433             memcpy(rt->playpath, "mp4:", 5);
2434         } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
2435             fname[len - 4] = '\0';
2436         } else {
2437             rt->playpath[0] = 0;
2438         }
2439         av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
2440     }
2441
2442     if (!rt->tcurl) {
2443         rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2444         if (!rt->tcurl) {
2445             ret = AVERROR(ENOMEM);
2446             goto fail;
2447         }
2448         ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2449                     port, "/%s", rt->app);
2450     }
2451
2452     if (!rt->flashver) {
2453         rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2454         if (!rt->flashver) {
2455             ret = AVERROR(ENOMEM);
2456             goto fail;
2457         }
2458         if (rt->is_input) {
2459             snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2460                     RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2461                     RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2462         } else {
2463             snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2464                     "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2465         }
2466     }
2467
2468     rt->client_report_size = 1048576;
2469     rt->bytes_read = 0;
2470     rt->last_bytes_read = 0;
2471     rt->server_bw = 2500000;
2472
2473     av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2474            proto, path, rt->app, rt->playpath);
2475     if (!rt->listen) {
2476         if ((ret = gen_connect(s, rt)) < 0)
2477             goto fail;
2478     } else {
2479         if (read_connect(s, s->priv_data) < 0)
2480             goto fail;
2481         rt->is_input = 1;
2482     }
2483
2484     do {
2485         ret = get_packet(s, 1);
2486     } while (ret == EAGAIN);
2487     if (ret < 0)
2488         goto fail;
2489
2490     if (rt->do_reconnect) {
2491         ffurl_close(rt->stream);
2492         rt->stream       = NULL;
2493         rt->do_reconnect = 0;
2494         rt->nb_invokes   = 0;
2495         memset(rt->prev_pkt, 0, sizeof(rt->prev_pkt));
2496         free_tracked_methods(rt);
2497         goto reconnect;
2498     }
2499
2500     if (rt->is_input) {
2501         // generate FLV header for demuxer
2502         rt->flv_size = 13;
2503         rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2504         rt->flv_off  = 0;
2505         memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
2506     } else {
2507         rt->flv_size = 0;
2508         rt->flv_data = NULL;
2509         rt->flv_off  = 0;
2510         rt->skip_bytes = 13;
2511     }
2512
2513     s->max_packet_size = rt->stream->max_packet_size;
2514     s->is_streamed     = 1;
2515     return 0;
2516
2517 fail:
2518     av_dict_free(&opts);
2519     rtmp_close(s);
2520     return ret;
2521 }
2522
2523 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2524 {
2525     RTMPContext *rt = s->priv_data;
2526     int orig_size = size;
2527     int ret;
2528
2529     while (size > 0) {
2530         int data_left = rt->flv_size - rt->flv_off;
2531
2532         if (data_left >= size) {
2533             memcpy(buf, rt->flv_data + rt->flv_off, size);
2534             rt->flv_off += size;
2535             return orig_size;
2536         }
2537         if (data_left > 0) {
2538             memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2539             buf  += data_left;
2540             size -= data_left;
2541             rt->flv_off = rt->flv_size;
2542             return data_left;
2543         }
2544         if ((ret = get_packet(s, 0)) < 0)
2545            return ret;
2546     }
2547     return orig_size;
2548 }
2549
2550 static int64_t rtmp_seek(URLContext *s, int stream_index, int64_t timestamp,
2551                          int flags)
2552 {
2553     RTMPContext *rt = s->priv_data;
2554     int ret;
2555     av_log(s, AV_LOG_DEBUG,
2556            "Seek on stream index %d at timestamp %"PRId64" with flags %08x\n",
2557            stream_index, timestamp, flags);
2558     if ((ret = gen_seek(s, rt, timestamp)) < 0) {
2559         av_log(s, AV_LOG_ERROR,
2560                "Unable to send seek command on stream index %d at timestamp "
2561                "%"PRId64" with flags %08x\n",
2562                stream_index, timestamp, flags);
2563         return ret;
2564     }
2565     rt->flv_off = rt->flv_size;
2566     rt->state = STATE_SEEKING;
2567     return timestamp;
2568 }
2569
2570 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2571 {
2572     RTMPContext *rt = s->priv_data;
2573     int size_temp = size;
2574     int pktsize, pkttype;
2575     uint32_t ts;
2576     const uint8_t *buf_temp = buf;
2577     uint8_t c;
2578     int ret;
2579
2580     do {
2581         if (rt->skip_bytes) {
2582             int skip = FFMIN(rt->skip_bytes, size_temp);
2583             buf_temp       += skip;
2584             size_temp      -= skip;
2585             rt->skip_bytes -= skip;
2586             continue;
2587         }
2588
2589         if (rt->flv_header_bytes < 11) {
2590             const uint8_t *header = rt->flv_header;
2591             int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
2592             bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2593             rt->flv_header_bytes += copy;
2594             size_temp            -= copy;
2595             if (rt->flv_header_bytes < 11)
2596                 break;
2597
2598             pkttype = bytestream_get_byte(&header);
2599             pktsize = bytestream_get_be24(&header);
2600             ts = bytestream_get_be24(&header);
2601             ts |= bytestream_get_byte(&header) << 24;
2602             bytestream_get_be24(&header);
2603             rt->flv_size = pktsize;
2604
2605             //force 12bytes header
2606             if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2607                 pkttype == RTMP_PT_NOTIFY) {
2608                 if (pkttype == RTMP_PT_NOTIFY)
2609                     pktsize += 16;
2610                 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
2611             }
2612
2613             //this can be a big packet, it's better to send it right here
2614             if ((ret = ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL,
2615                                              pkttype, ts, pktsize)) < 0)
2616                 return ret;
2617
2618             rt->out_pkt.extra = rt->main_channel_id;
2619             rt->flv_data = rt->out_pkt.data;
2620
2621             if (pkttype == RTMP_PT_NOTIFY)
2622                 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2623         }
2624
2625         if (rt->flv_size - rt->flv_off > size_temp) {
2626             bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2627             rt->flv_off += size_temp;
2628             size_temp = 0;
2629         } else {
2630             bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2631             size_temp   -= rt->flv_size - rt->flv_off;
2632             rt->flv_off += rt->flv_size - rt->flv_off;
2633         }
2634
2635         if (rt->flv_off == rt->flv_size) {
2636             rt->skip_bytes = 4;
2637
2638             if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2639                 return ret;
2640             rt->flv_size = 0;
2641             rt->flv_off = 0;
2642             rt->flv_header_bytes = 0;
2643             rt->flv_nb_packets++;
2644         }
2645     } while (buf_temp - buf < size);
2646
2647     if (rt->flv_nb_packets < rt->flush_interval)
2648         return size;
2649     rt->flv_nb_packets = 0;
2650
2651     /* set stream into nonblocking mode */
2652     rt->stream->flags |= AVIO_FLAG_NONBLOCK;
2653
2654     /* try to read one byte from the stream */
2655     ret = ffurl_read(rt->stream, &c, 1);
2656
2657     /* switch the stream back into blocking mode */
2658     rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2659
2660     if (ret == AVERROR(EAGAIN)) {
2661         /* no incoming data to handle */
2662         return size;
2663     } else if (ret < 0) {
2664         return ret;
2665     } else if (ret == 1) {
2666         RTMPPacket rpkt = { 0 };
2667
2668         if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2669                                                 rt->in_chunk_size,
2670                                                 rt->prev_pkt[0], c)) <= 0)
2671              return ret;
2672
2673         if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2674             return ret;
2675
2676         ff_rtmp_packet_destroy(&rpkt);
2677     }
2678
2679     return size;
2680 }
2681
2682 #define OFFSET(x) offsetof(RTMPContext, x)
2683 #define DEC AV_OPT_FLAG_DECODING_PARAM
2684 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2685
2686 static const AVOption rtmp_options[] = {
2687     {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2688     {"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},
2689     {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2690     {"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},
2691     {"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},
2692     {"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"},
2693     {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
2694     {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
2695     {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
2696     {"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},
2697     {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2698     {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2699     {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2700     {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
2701     {"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},
2702     {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2703     {"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},
2704     {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2705     {"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" },
2706     { NULL },
2707 };
2708
2709 #define RTMP_PROTOCOL(flavor)                    \
2710 static const AVClass flavor##_class = {          \
2711     .class_name = #flavor,                       \
2712     .item_name  = av_default_item_name,          \
2713     .option     = rtmp_options,                  \
2714     .version    = LIBAVUTIL_VERSION_INT,         \
2715 };                                               \
2716                                                  \
2717 URLProtocol ff_##flavor##_protocol = {           \
2718     .name           = #flavor,                   \
2719     .url_open       = rtmp_open,                 \
2720     .url_read       = rtmp_read,                 \
2721     .url_read_seek  = rtmp_seek,                 \
2722     .url_write      = rtmp_write,                \
2723     .url_close      = rtmp_close,                \
2724     .priv_data_size = sizeof(RTMPContext),       \
2725     .flags          = URL_PROTOCOL_FLAG_NETWORK, \
2726     .priv_data_class= &flavor##_class,           \
2727 };
2728
2729
2730 RTMP_PROTOCOL(rtmp)
2731 RTMP_PROTOCOL(rtmpe)
2732 RTMP_PROTOCOL(rtmps)
2733 RTMP_PROTOCOL(rtmpt)
2734 RTMP_PROTOCOL(rtmpte)
2735 RTMP_PROTOCOL(rtmpts)