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