]> git.sesse.net Git - ffmpeg/blob - libavformat/rtmpproto.c
avio: make url_write() internal.
[ffmpeg] / libavformat / rtmpproto.c
1 /*
2  * RTMP network protocol
3  * Copyright (c) 2009 Kostya 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/lfg.h"
30 #include "libavutil/sha.h"
31 #include "avformat.h"
32 #include "internal.h"
33
34 #include "network.h"
35
36 #include "flv.h"
37 #include "rtmp.h"
38 #include "rtmppkt.h"
39 #include "url.h"
40
41 /* we can't use av_log() with URLContext yet... */
42 #if FF_API_URL_CLASS
43 #define LOG_CONTEXT s
44 #else
45 #define LOG_CONTEXT NULL
46 #endif
47
48 //#define DEBUG
49
50 /** RTMP protocol handler state */
51 typedef enum {
52     STATE_START,      ///< client has not done anything yet
53     STATE_HANDSHAKED, ///< client has performed handshake
54     STATE_RELEASING,  ///< client releasing stream before publish it (for output)
55     STATE_FCPUBLISH,  ///< client FCPublishing stream (for output)
56     STATE_CONNECTING, ///< client connected to server successfully
57     STATE_READY,      ///< client has sent all needed commands and waits for server reply
58     STATE_PLAYING,    ///< client has started receiving multimedia data from server
59     STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
60     STATE_STOPPED,    ///< the broadcast has been stopped
61 } ClientState;
62
63 /** protocol handler context */
64 typedef struct RTMPContext {
65     URLContext*   stream;                     ///< TCP stream used in interactions with RTMP server
66     RTMPPacket    prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets
67     int           chunk_size;                 ///< size of the chunks RTMP packets are divided into
68     int           is_input;                   ///< input/output flag
69     char          playpath[256];              ///< path to filename to play (with possible "mp4:" prefix)
70     char          app[128];                   ///< application
71     ClientState   state;                      ///< current state
72     int           main_channel_id;            ///< an additional channel ID which is used for some invocations
73     uint8_t*      flv_data;                   ///< buffer with data for demuxer
74     int           flv_size;                   ///< current buffer size
75     int           flv_off;                    ///< number of bytes read from current buffer
76     RTMPPacket    out_pkt;                    ///< rtmp packet, created from flv a/v or metadata (for output)
77     uint32_t      client_report_size;         ///< number of bytes after which client should report to server
78     uint32_t      bytes_read;                 ///< number of bytes read from server
79     uint32_t      last_bytes_read;            ///< number of bytes read last reported to server
80 } RTMPContext;
81
82 #define PLAYER_KEY_OPEN_PART_LEN 30   ///< length of partial key used for first client digest signing
83 /** Client key used for digest signing */
84 static const uint8_t rtmp_player_key[] = {
85     'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
86     'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
87
88     0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
89     0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
90     0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
91 };
92
93 #define SERVER_KEY_OPEN_PART_LEN 36   ///< length of partial key used for first server digest signing
94 /** Key used for RTMP server digest signing */
95 static const uint8_t rtmp_server_key[] = {
96     'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
97     'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
98     'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
99
100     0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
101     0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
102     0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
103 };
104
105 /**
106  * Generate 'connect' call and send it to the server.
107  */
108 static void gen_connect(URLContext *s, RTMPContext *rt, const char *proto,
109                         const char *host, int port)
110 {
111     RTMPPacket pkt;
112     uint8_t ver[64], *p;
113     char tcurl[512];
114
115     ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 4096);
116     p = pkt.data;
117
118     ff_url_join(tcurl, sizeof(tcurl), proto, NULL, host, port, "/%s", rt->app);
119     ff_amf_write_string(&p, "connect");
120     ff_amf_write_number(&p, 1.0);
121     ff_amf_write_object_start(&p);
122     ff_amf_write_field_name(&p, "app");
123     ff_amf_write_string(&p, rt->app);
124
125     if (rt->is_input) {
126         snprintf(ver, sizeof(ver), "%s %d,%d,%d,%d", RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1,
127                  RTMP_CLIENT_VER2, RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
128     } else {
129         snprintf(ver, sizeof(ver), "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
130         ff_amf_write_field_name(&p, "type");
131         ff_amf_write_string(&p, "nonprivate");
132     }
133     ff_amf_write_field_name(&p, "flashVer");
134     ff_amf_write_string(&p, ver);
135     ff_amf_write_field_name(&p, "tcUrl");
136     ff_amf_write_string(&p, tcurl);
137     if (rt->is_input) {
138         ff_amf_write_field_name(&p, "fpad");
139         ff_amf_write_bool(&p, 0);
140         ff_amf_write_field_name(&p, "capabilities");
141         ff_amf_write_number(&p, 15.0);
142         ff_amf_write_field_name(&p, "audioCodecs");
143         ff_amf_write_number(&p, 1639.0);
144         ff_amf_write_field_name(&p, "videoCodecs");
145         ff_amf_write_number(&p, 252.0);
146         ff_amf_write_field_name(&p, "videoFunction");
147         ff_amf_write_number(&p, 1.0);
148     }
149     ff_amf_write_object_end(&p);
150
151     pkt.data_size = p - pkt.data;
152
153     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
154     ff_rtmp_packet_destroy(&pkt);
155 }
156
157 /**
158  * Generate 'releaseStream' call and send it to the server. It should make
159  * the server release some channel for media streams.
160  */
161 static void gen_release_stream(URLContext *s, RTMPContext *rt)
162 {
163     RTMPPacket pkt;
164     uint8_t *p;
165
166     ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0,
167                           29 + strlen(rt->playpath));
168
169     av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Releasing stream...\n");
170     p = pkt.data;
171     ff_amf_write_string(&p, "releaseStream");
172     ff_amf_write_number(&p, 2.0);
173     ff_amf_write_null(&p);
174     ff_amf_write_string(&p, rt->playpath);
175
176     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
177     ff_rtmp_packet_destroy(&pkt);
178 }
179
180 /**
181  * Generate 'FCPublish' call and send it to the server. It should make
182  * the server preapare for receiving media streams.
183  */
184 static void gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
185 {
186     RTMPPacket pkt;
187     uint8_t *p;
188
189     ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0,
190                           25 + strlen(rt->playpath));
191
192     av_log(LOG_CONTEXT, AV_LOG_DEBUG, "FCPublish stream...\n");
193     p = pkt.data;
194     ff_amf_write_string(&p, "FCPublish");
195     ff_amf_write_number(&p, 3.0);
196     ff_amf_write_null(&p);
197     ff_amf_write_string(&p, rt->playpath);
198
199     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
200     ff_rtmp_packet_destroy(&pkt);
201 }
202
203 /**
204  * Generate 'FCUnpublish' call and send it to the server. It should make
205  * the server destroy stream.
206  */
207 static void gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
208 {
209     RTMPPacket pkt;
210     uint8_t *p;
211
212     ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0,
213                           27 + strlen(rt->playpath));
214
215     av_log(LOG_CONTEXT, AV_LOG_DEBUG, "UnPublishing stream...\n");
216     p = pkt.data;
217     ff_amf_write_string(&p, "FCUnpublish");
218     ff_amf_write_number(&p, 5.0);
219     ff_amf_write_null(&p);
220     ff_amf_write_string(&p, rt->playpath);
221
222     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
223     ff_rtmp_packet_destroy(&pkt);
224 }
225
226 /**
227  * Generate 'createStream' call and send it to the server. It should make
228  * the server allocate some channel for media streams.
229  */
230 static void gen_create_stream(URLContext *s, RTMPContext *rt)
231 {
232     RTMPPacket pkt;
233     uint8_t *p;
234
235     av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Creating stream...\n");
236     ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 25);
237
238     p = pkt.data;
239     ff_amf_write_string(&p, "createStream");
240     ff_amf_write_number(&p, rt->is_input ? 3.0 : 4.0);
241     ff_amf_write_null(&p);
242
243     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
244     ff_rtmp_packet_destroy(&pkt);
245 }
246
247
248 /**
249  * Generate 'deleteStream' call and send it to the server. It should make
250  * the server remove some channel for media streams.
251  */
252 static void gen_delete_stream(URLContext *s, RTMPContext *rt)
253 {
254     RTMPPacket pkt;
255     uint8_t *p;
256
257     av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Deleting stream...\n");
258     ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 34);
259
260     p = pkt.data;
261     ff_amf_write_string(&p, "deleteStream");
262     ff_amf_write_number(&p, 0.0);
263     ff_amf_write_null(&p);
264     ff_amf_write_number(&p, rt->main_channel_id);
265
266     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
267     ff_rtmp_packet_destroy(&pkt);
268 }
269
270 /**
271  * Generate 'play' call and send it to the server, then ping the server
272  * to start actual playing.
273  */
274 static void gen_play(URLContext *s, RTMPContext *rt)
275 {
276     RTMPPacket pkt;
277     uint8_t *p;
278
279     av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
280     ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE, 0,
281                           20 + strlen(rt->playpath));
282     pkt.extra = rt->main_channel_id;
283
284     p = pkt.data;
285     ff_amf_write_string(&p, "play");
286     ff_amf_write_number(&p, 0.0);
287     ff_amf_write_null(&p);
288     ff_amf_write_string(&p, rt->playpath);
289
290     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
291     ff_rtmp_packet_destroy(&pkt);
292
293     // set client buffer time disguised in ping packet
294     ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING, 1, 10);
295
296     p = pkt.data;
297     bytestream_put_be16(&p, 3);
298     bytestream_put_be32(&p, 1);
299     bytestream_put_be32(&p, 256); //TODO: what is a good value here?
300
301     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
302     ff_rtmp_packet_destroy(&pkt);
303 }
304
305 /**
306  * Generate 'publish' call and send it to the server.
307  */
308 static void gen_publish(URLContext *s, RTMPContext *rt)
309 {
310     RTMPPacket pkt;
311     uint8_t *p;
312
313     av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
314     ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE, 0,
315                           30 + strlen(rt->playpath));
316     pkt.extra = rt->main_channel_id;
317
318     p = pkt.data;
319     ff_amf_write_string(&p, "publish");
320     ff_amf_write_number(&p, 0.0);
321     ff_amf_write_null(&p);
322     ff_amf_write_string(&p, rt->playpath);
323     ff_amf_write_string(&p, "live");
324
325     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
326     ff_rtmp_packet_destroy(&pkt);
327 }
328
329 /**
330  * Generate ping reply and send it to the server.
331  */
332 static void gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
333 {
334     RTMPPacket pkt;
335     uint8_t *p;
336
337     ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING, ppkt->timestamp + 1, 6);
338     p = pkt.data;
339     bytestream_put_be16(&p, 7);
340     bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
341     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
342     ff_rtmp_packet_destroy(&pkt);
343 }
344
345 /**
346  * Generate report on bytes read so far and send it to the server.
347  */
348 static void gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
349 {
350     RTMPPacket pkt;
351     uint8_t *p;
352
353     ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ, ts, 4);
354     p = pkt.data;
355     bytestream_put_be32(&p, rt->bytes_read);
356     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
357     ff_rtmp_packet_destroy(&pkt);
358 }
359
360 //TODO: Move HMAC code somewhere. Eventually.
361 #define HMAC_IPAD_VAL 0x36
362 #define HMAC_OPAD_VAL 0x5C
363
364 /**
365  * Calculate HMAC-SHA2 digest for RTMP handshake packets.
366  *
367  * @param src    input buffer
368  * @param len    input buffer length (should be 1536)
369  * @param gap    offset in buffer where 32 bytes should not be taken into account
370  *               when calculating digest (since it will be used to store that digest)
371  * @param key    digest key
372  * @param keylen digest key length
373  * @param dst    buffer where calculated digest will be stored (32 bytes)
374  */
375 static void rtmp_calc_digest(const uint8_t *src, int len, int gap,
376                              const uint8_t *key, int keylen, uint8_t *dst)
377 {
378     struct AVSHA *sha;
379     uint8_t hmac_buf[64+32] = {0};
380     int i;
381
382     sha = av_mallocz(av_sha_size);
383
384     if (keylen < 64) {
385         memcpy(hmac_buf, key, keylen);
386     } else {
387         av_sha_init(sha, 256);
388         av_sha_update(sha,key, keylen);
389         av_sha_final(sha, hmac_buf);
390     }
391     for (i = 0; i < 64; i++)
392         hmac_buf[i] ^= HMAC_IPAD_VAL;
393
394     av_sha_init(sha, 256);
395     av_sha_update(sha, hmac_buf, 64);
396     if (gap <= 0) {
397         av_sha_update(sha, src, len);
398     } else { //skip 32 bytes used for storing digest
399         av_sha_update(sha, src, gap);
400         av_sha_update(sha, src + gap + 32, len - gap - 32);
401     }
402     av_sha_final(sha, hmac_buf + 64);
403
404     for (i = 0; i < 64; i++)
405         hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
406     av_sha_init(sha, 256);
407     av_sha_update(sha, hmac_buf, 64+32);
408     av_sha_final(sha, dst);
409
410     av_free(sha);
411 }
412
413 /**
414  * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
415  * will be stored) into that packet.
416  *
417  * @param buf handshake data (1536 bytes)
418  * @return offset to the digest inside input data
419  */
420 static int rtmp_handshake_imprint_with_digest(uint8_t *buf)
421 {
422     int i, digest_pos = 0;
423
424     for (i = 8; i < 12; i++)
425         digest_pos += buf[i];
426     digest_pos = (digest_pos % 728) + 12;
427
428     rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
429                      rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
430                      buf + digest_pos);
431     return digest_pos;
432 }
433
434 /**
435  * Verify that the received server response has the expected digest value.
436  *
437  * @param buf handshake data received from the server (1536 bytes)
438  * @param off position to search digest offset from
439  * @return 0 if digest is valid, digest position otherwise
440  */
441 static int rtmp_validate_digest(uint8_t *buf, int off)
442 {
443     int i, digest_pos = 0;
444     uint8_t digest[32];
445
446     for (i = 0; i < 4; i++)
447         digest_pos += buf[i + off];
448     digest_pos = (digest_pos % 728) + off + 4;
449
450     rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
451                      rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
452                      digest);
453     if (!memcmp(digest, buf + digest_pos, 32))
454         return digest_pos;
455     return 0;
456 }
457
458 /**
459  * Perform handshake with the server by means of exchanging pseudorandom data
460  * signed with HMAC-SHA2 digest.
461  *
462  * @return 0 if handshake succeeds, negative value otherwise
463  */
464 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
465 {
466     AVLFG rnd;
467     uint8_t tosend    [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
468         3,                // unencrypted data
469         0, 0, 0, 0,       // client uptime
470         RTMP_CLIENT_VER1,
471         RTMP_CLIENT_VER2,
472         RTMP_CLIENT_VER3,
473         RTMP_CLIENT_VER4,
474     };
475     uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
476     uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
477     int i;
478     int server_pos, client_pos;
479     uint8_t digest[32];
480
481     av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Handshaking...\n");
482
483     av_lfg_init(&rnd, 0xDEADC0DE);
484     // generate handshake packet - 1536 bytes of pseudorandom data
485     for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
486         tosend[i] = av_lfg_get(&rnd) >> 24;
487     client_pos = rtmp_handshake_imprint_with_digest(tosend + 1);
488
489     ffurl_write(rt->stream, tosend, RTMP_HANDSHAKE_PACKET_SIZE + 1);
490     i = ffurl_read_complete(rt->stream, serverdata, RTMP_HANDSHAKE_PACKET_SIZE + 1);
491     if (i != RTMP_HANDSHAKE_PACKET_SIZE + 1) {
492         av_log(LOG_CONTEXT, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
493         return -1;
494     }
495     i = ffurl_read_complete(rt->stream, clientdata, RTMP_HANDSHAKE_PACKET_SIZE);
496     if (i != RTMP_HANDSHAKE_PACKET_SIZE) {
497         av_log(LOG_CONTEXT, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
498         return -1;
499     }
500
501     av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
502            serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
503
504     if (rt->is_input && serverdata[5] >= 3) {
505         server_pos = rtmp_validate_digest(serverdata + 1, 772);
506         if (!server_pos) {
507             server_pos = rtmp_validate_digest(serverdata + 1, 8);
508             if (!server_pos) {
509                 av_log(LOG_CONTEXT, AV_LOG_ERROR, "Server response validating failed\n");
510                 return -1;
511             }
512         }
513
514         rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
515                          rtmp_server_key, sizeof(rtmp_server_key),
516                          digest);
517         rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE-32, 0,
518                          digest, 32,
519                          digest);
520         if (memcmp(digest, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
521             av_log(LOG_CONTEXT, AV_LOG_ERROR, "Signature mismatch\n");
522             return -1;
523         }
524
525         for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
526             tosend[i] = av_lfg_get(&rnd) >> 24;
527         rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
528                          rtmp_player_key, sizeof(rtmp_player_key),
529                          digest);
530         rtmp_calc_digest(tosend,  RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
531                          digest, 32,
532                          tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
533
534         // write reply back to the server
535         ffurl_write(rt->stream, tosend, RTMP_HANDSHAKE_PACKET_SIZE);
536     } else {
537         ffurl_write(rt->stream, serverdata+1, RTMP_HANDSHAKE_PACKET_SIZE);
538     }
539
540     return 0;
541 }
542
543 /**
544  * Parse received packet and possibly perform some action depending on
545  * the packet contents.
546  * @return 0 for no errors, negative values for serious errors which prevent
547  *         further communications, positive values for uncritical errors
548  */
549 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
550 {
551     int i, t;
552     const uint8_t *data_end = pkt->data + pkt->data_size;
553
554 #ifdef DEBUG
555     ff_rtmp_packet_dump(LOG_CONTEXT, pkt);
556 #endif
557
558     switch (pkt->type) {
559     case RTMP_PT_CHUNK_SIZE:
560         if (pkt->data_size != 4) {
561             av_log(LOG_CONTEXT, AV_LOG_ERROR,
562                    "Chunk size change packet is not 4 bytes long (%d)\n", pkt->data_size);
563             return -1;
564         }
565         if (!rt->is_input)
566             ff_rtmp_packet_write(rt->stream, pkt, rt->chunk_size, rt->prev_pkt[1]);
567         rt->chunk_size = AV_RB32(pkt->data);
568         if (rt->chunk_size <= 0) {
569             av_log(LOG_CONTEXT, AV_LOG_ERROR, "Incorrect chunk size %d\n", rt->chunk_size);
570             return -1;
571         }
572         av_log(LOG_CONTEXT, AV_LOG_DEBUG, "New chunk size = %d\n", rt->chunk_size);
573         break;
574     case RTMP_PT_PING:
575         t = AV_RB16(pkt->data);
576         if (t == 6)
577             gen_pong(s, rt, pkt);
578         break;
579     case RTMP_PT_CLIENT_BW:
580         if (pkt->data_size < 4) {
581             av_log(LOG_CONTEXT, AV_LOG_ERROR,
582                    "Client bandwidth report packet is less than 4 bytes long (%d)\n",
583                    pkt->data_size);
584             return -1;
585         }
586         av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Client bandwidth = %d\n", AV_RB32(pkt->data));
587         rt->client_report_size = AV_RB32(pkt->data) >> 1;
588         break;
589     case RTMP_PT_INVOKE:
590         //TODO: check for the messages sent for wrong state?
591         if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
592             uint8_t tmpstr[256];
593
594             if (!ff_amf_get_field_value(pkt->data + 9, data_end,
595                                         "description", tmpstr, sizeof(tmpstr)))
596                 av_log(LOG_CONTEXT, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
597             return -1;
598         } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
599             switch (rt->state) {
600             case STATE_HANDSHAKED:
601                 if (!rt->is_input) {
602                     gen_release_stream(s, rt);
603                     gen_fcpublish_stream(s, rt);
604                     rt->state = STATE_RELEASING;
605                 } else {
606                     rt->state = STATE_CONNECTING;
607                 }
608                 gen_create_stream(s, rt);
609                 break;
610             case STATE_FCPUBLISH:
611                 rt->state = STATE_CONNECTING;
612                 break;
613             case STATE_RELEASING:
614                 rt->state = STATE_FCPUBLISH;
615                 /* hack for Wowza Media Server, it does not send result for
616                  * releaseStream and FCPublish calls */
617                 if (!pkt->data[10]) {
618                     int pkt_id = (int) av_int2dbl(AV_RB64(pkt->data + 11));
619                     if (pkt_id == 4)
620                         rt->state = STATE_CONNECTING;
621                 }
622                 if (rt->state != STATE_CONNECTING)
623                     break;
624             case STATE_CONNECTING:
625                 //extract a number from the result
626                 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
627                     av_log(LOG_CONTEXT, AV_LOG_WARNING, "Unexpected reply on connect()\n");
628                 } else {
629                     rt->main_channel_id = (int) av_int2dbl(AV_RB64(pkt->data + 21));
630                 }
631                 if (rt->is_input) {
632                     gen_play(s, rt);
633                 } else {
634                     gen_publish(s, rt);
635                 }
636                 rt->state = STATE_READY;
637                 break;
638             }
639         } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
640             const uint8_t* ptr = pkt->data + 11;
641             uint8_t tmpstr[256];
642
643             for (i = 0; i < 2; i++) {
644                 t = ff_amf_tag_size(ptr, data_end);
645                 if (t < 0)
646                     return 1;
647                 ptr += t;
648             }
649             t = ff_amf_get_field_value(ptr, data_end,
650                                        "level", tmpstr, sizeof(tmpstr));
651             if (!t && !strcmp(tmpstr, "error")) {
652                 if (!ff_amf_get_field_value(ptr, data_end,
653                                             "description", tmpstr, sizeof(tmpstr)))
654                     av_log(LOG_CONTEXT, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
655                 return -1;
656             }
657             t = ff_amf_get_field_value(ptr, data_end,
658                                        "code", tmpstr, sizeof(tmpstr));
659             if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
660             if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
661             if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
662             if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
663         }
664         break;
665     }
666     return 0;
667 }
668
669 /**
670  * Interact with the server by receiving and sending RTMP packets until
671  * there is some significant data (media data or expected status notification).
672  *
673  * @param s          reading context
674  * @param for_header non-zero value tells function to work until it
675  * gets notification from the server that playing has been started,
676  * otherwise function will work until some media data is received (or
677  * an error happens)
678  * @return 0 for successful operation, negative value in case of error
679  */
680 static int get_packet(URLContext *s, int for_header)
681 {
682     RTMPContext *rt = s->priv_data;
683     int ret;
684     uint8_t *p;
685     const uint8_t *next;
686     uint32_t data_size;
687     uint32_t ts, cts, pts=0;
688
689     if (rt->state == STATE_STOPPED)
690         return AVERROR_EOF;
691
692     for (;;) {
693         RTMPPacket rpkt;
694         if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
695                                        rt->chunk_size, rt->prev_pkt[0])) <= 0) {
696             if (ret == 0) {
697                 return AVERROR(EAGAIN);
698             } else {
699                 return AVERROR(EIO);
700             }
701         }
702         rt->bytes_read += ret;
703         if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
704             av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Sending bytes read report\n");
705             gen_bytes_read(s, rt, rpkt.timestamp + 1);
706             rt->last_bytes_read = rt->bytes_read;
707         }
708
709         ret = rtmp_parse_result(s, rt, &rpkt);
710         if (ret < 0) {//serious error in current packet
711             ff_rtmp_packet_destroy(&rpkt);
712             return -1;
713         }
714         if (rt->state == STATE_STOPPED) {
715             ff_rtmp_packet_destroy(&rpkt);
716             return AVERROR_EOF;
717         }
718         if (for_header && (rt->state == STATE_PLAYING || rt->state == STATE_PUBLISHING)) {
719             ff_rtmp_packet_destroy(&rpkt);
720             return 0;
721         }
722         if (!rpkt.data_size || !rt->is_input) {
723             ff_rtmp_packet_destroy(&rpkt);
724             continue;
725         }
726         if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
727            (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
728             ts = rpkt.timestamp;
729
730             // generate packet header and put data into buffer for FLV demuxer
731             rt->flv_off  = 0;
732             rt->flv_size = rpkt.data_size + 15;
733             rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
734             bytestream_put_byte(&p, rpkt.type);
735             bytestream_put_be24(&p, rpkt.data_size);
736             bytestream_put_be24(&p, ts);
737             bytestream_put_byte(&p, ts >> 24);
738             bytestream_put_be24(&p, 0);
739             bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);
740             bytestream_put_be32(&p, 0);
741             ff_rtmp_packet_destroy(&rpkt);
742             return 0;
743         } else if (rpkt.type == RTMP_PT_METADATA) {
744             // we got raw FLV data, make it available for FLV demuxer
745             rt->flv_off  = 0;
746             rt->flv_size = rpkt.data_size;
747             rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
748             /* rewrite timestamps */
749             next = rpkt.data;
750             ts = rpkt.timestamp;
751             while (next - rpkt.data < rpkt.data_size - 11) {
752                 next++;
753                 data_size = bytestream_get_be24(&next);
754                 p=next;
755                 cts = bytestream_get_be24(&next);
756                 cts |= bytestream_get_byte(&next) << 24;
757                 if (pts==0)
758                     pts=cts;
759                 ts += cts - pts;
760                 pts = cts;
761                 bytestream_put_be24(&p, ts);
762                 bytestream_put_byte(&p, ts >> 24);
763                 next += data_size + 3 + 4;
764             }
765             memcpy(rt->flv_data, rpkt.data, rpkt.data_size);
766             ff_rtmp_packet_destroy(&rpkt);
767             return 0;
768         }
769         ff_rtmp_packet_destroy(&rpkt);
770     }
771     return 0;
772 }
773
774 static int rtmp_close(URLContext *h)
775 {
776     RTMPContext *rt = h->priv_data;
777
778     if (!rt->is_input) {
779         rt->flv_data = NULL;
780         if (rt->out_pkt.data_size)
781             ff_rtmp_packet_destroy(&rt->out_pkt);
782         if (rt->state > STATE_FCPUBLISH)
783             gen_fcunpublish_stream(h, rt);
784     }
785     if (rt->state > STATE_HANDSHAKED)
786         gen_delete_stream(h, rt);
787
788     av_freep(&rt->flv_data);
789     url_close(rt->stream);
790     av_free(rt);
791     return 0;
792 }
793
794 /**
795  * Open RTMP connection and verify that the stream can be played.
796  *
797  * URL syntax: rtmp://server[:port][/app][/playpath]
798  *             where 'app' is first one or two directories in the path
799  *             (e.g. /ondemand/, /flash/live/, etc.)
800  *             and 'playpath' is a file name (the rest of the path,
801  *             may be prefixed with "mp4:")
802  */
803 static int rtmp_open(URLContext *s, const char *uri, int flags)
804 {
805     RTMPContext *rt;
806     char proto[8], hostname[256], path[1024], *fname;
807     uint8_t buf[2048];
808     int port;
809     int ret;
810
811     rt = av_mallocz(sizeof(RTMPContext));
812     if (!rt)
813         return AVERROR(ENOMEM);
814     s->priv_data = rt;
815     rt->is_input = !(flags & URL_WRONLY);
816
817     av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
818                  path, sizeof(path), s->filename);
819
820     if (port < 0)
821         port = RTMP_DEFAULT_PORT;
822     ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
823
824     if (ffurl_open(&rt->stream, buf, URL_RDWR) < 0) {
825         av_log(LOG_CONTEXT, AV_LOG_ERROR, "Cannot open connection %s\n", buf);
826         goto fail;
827     }
828
829     rt->state = STATE_START;
830     if (rtmp_handshake(s, rt))
831         return -1;
832
833     rt->chunk_size = 128;
834     rt->state = STATE_HANDSHAKED;
835     //extract "app" part from path
836     if (!strncmp(path, "/ondemand/", 10)) {
837         fname = path + 10;
838         memcpy(rt->app, "ondemand", 9);
839     } else {
840         char *p = strchr(path + 1, '/');
841         if (!p) {
842             fname = path + 1;
843             rt->app[0] = '\0';
844         } else {
845             char *c = strchr(p + 1, ':');
846             fname = strchr(p + 1, '/');
847             if (!fname || c < fname) {
848                 fname = p + 1;
849                 av_strlcpy(rt->app, path + 1, p - path);
850             } else {
851                 fname++;
852                 av_strlcpy(rt->app, path + 1, fname - path - 1);
853             }
854         }
855     }
856     if (!strchr(fname, ':') &&
857         (!strcmp(fname + strlen(fname) - 4, ".f4v") ||
858          !strcmp(fname + strlen(fname) - 4, ".mp4"))) {
859         memcpy(rt->playpath, "mp4:", 5);
860     } else {
861         rt->playpath[0] = 0;
862     }
863     strncat(rt->playpath, fname, sizeof(rt->playpath) - 5);
864
865     rt->client_report_size = 1048576;
866     rt->bytes_read = 0;
867     rt->last_bytes_read = 0;
868
869     av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
870            proto, path, rt->app, rt->playpath);
871     gen_connect(s, rt, proto, hostname, port);
872
873     do {
874         ret = get_packet(s, 1);
875     } while (ret == EAGAIN);
876     if (ret < 0)
877         goto fail;
878
879     if (rt->is_input) {
880         // generate FLV header for demuxer
881         rt->flv_size = 13;
882         rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
883         rt->flv_off  = 0;
884         memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
885     } else {
886         rt->flv_size = 0;
887         rt->flv_data = NULL;
888         rt->flv_off  = 0;
889     }
890
891     s->max_packet_size = url_get_max_packet_size(rt->stream);
892     s->is_streamed     = 1;
893     return 0;
894
895 fail:
896     rtmp_close(s);
897     return AVERROR(EIO);
898 }
899
900 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
901 {
902     RTMPContext *rt = s->priv_data;
903     int orig_size = size;
904     int ret;
905
906     while (size > 0) {
907         int data_left = rt->flv_size - rt->flv_off;
908
909         if (data_left >= size) {
910             memcpy(buf, rt->flv_data + rt->flv_off, size);
911             rt->flv_off += size;
912             return orig_size;
913         }
914         if (data_left > 0) {
915             memcpy(buf, rt->flv_data + rt->flv_off, data_left);
916             buf  += data_left;
917             size -= data_left;
918             rt->flv_off = rt->flv_size;
919             return data_left;
920         }
921         if ((ret = get_packet(s, 0)) < 0)
922            return ret;
923     }
924     return orig_size;
925 }
926
927 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
928 {
929     RTMPContext *rt = s->priv_data;
930     int size_temp = size;
931     int pktsize, pkttype;
932     uint32_t ts;
933     const uint8_t *buf_temp = buf;
934
935     if (size < 11) {
936         av_log(LOG_CONTEXT, AV_LOG_DEBUG, "FLV packet too small %d\n", size);
937         return 0;
938     }
939
940     do {
941         if (!rt->flv_off) {
942             //skip flv header
943             if (buf_temp[0] == 'F' && buf_temp[1] == 'L' && buf_temp[2] == 'V') {
944                 buf_temp += 9 + 4;
945                 size_temp -= 9 + 4;
946             }
947
948             pkttype = bytestream_get_byte(&buf_temp);
949             pktsize = bytestream_get_be24(&buf_temp);
950             ts = bytestream_get_be24(&buf_temp);
951             ts |= bytestream_get_byte(&buf_temp) << 24;
952             bytestream_get_be24(&buf_temp);
953             size_temp -= 11;
954             rt->flv_size = pktsize;
955
956             //force 12bytes header
957             if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
958                 pkttype == RTMP_PT_NOTIFY) {
959                 if (pkttype == RTMP_PT_NOTIFY)
960                     pktsize += 16;
961                 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
962             }
963
964             //this can be a big packet, it's better to send it right here
965             ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL, pkttype, ts, pktsize);
966             rt->out_pkt.extra = rt->main_channel_id;
967             rt->flv_data = rt->out_pkt.data;
968
969             if (pkttype == RTMP_PT_NOTIFY)
970                 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
971         }
972
973         if (rt->flv_size - rt->flv_off > size_temp) {
974             bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
975             rt->flv_off += size_temp;
976         } else {
977             bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
978             rt->flv_off += rt->flv_size - rt->flv_off;
979         }
980
981         if (rt->flv_off == rt->flv_size) {
982             bytestream_get_be32(&buf_temp);
983
984             ff_rtmp_packet_write(rt->stream, &rt->out_pkt, rt->chunk_size, rt->prev_pkt[1]);
985             ff_rtmp_packet_destroy(&rt->out_pkt);
986             rt->flv_size = 0;
987             rt->flv_off = 0;
988         }
989     } while (buf_temp - buf < size_temp);
990     return size;
991 }
992
993 URLProtocol ff_rtmp_protocol = {
994     "rtmp",
995     rtmp_open,
996     rtmp_read,
997     rtmp_write,
998     NULL, /* seek */
999     rtmp_close,
1000 };