rtmp: Add support for SWFVerification
[ffmpeg.git] / 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/intfloat.h"
30 #include "libavutil/lfg.h"
31 #include "libavutil/opt.h"
32 #include "libavutil/sha.h"
33 #include "avformat.h"
34 #include "internal.h"
35
36 #include "network.h"
37
38 #include "flv.h"
39 #include "rtmp.h"
40 #include "rtmpcrypt.h"
41 #include "rtmppkt.h"
42 #include "url.h"
43
44 //#define DEBUG
45
46 #define APP_MAX_LENGTH 128
47 #define PLAYPATH_MAX_LENGTH 256
48 #define TCURL_MAX_LENGTH 512
49 #define FLASHVER_MAX_LENGTH 64
50
51 /** RTMP protocol handler state */
52 typedef enum {
53     STATE_START,      ///< client has not done anything yet
54     STATE_HANDSHAKED, ///< client has performed handshake
55     STATE_FCPUBLISH,  ///< client FCPublishing stream (for output)
56     STATE_PLAYING,    ///< client has started receiving multimedia data from server
57     STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
58     STATE_STOPPED,    ///< the broadcast has been stopped
59 } ClientState;
60
61 typedef struct TrackedMethod {
62     char *name;
63     int id;
64 } TrackedMethod;
65
66 /** protocol handler context */
67 typedef struct RTMPContext {
68     const AVClass *class;
69     URLContext*   stream;                     ///< TCP stream used in interactions with RTMP server
70     RTMPPacket    prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets
71     int           in_chunk_size;              ///< size of the chunks incoming RTMP packets are divided into
72     int           out_chunk_size;             ///< size of the chunks outgoing RTMP packets are divided into
73     int           is_input;                   ///< input/output flag
74     char          *playpath;                  ///< stream identifier to play (with possible "mp4:" prefix)
75     int           live;                       ///< 0: recorded, -1: live, -2: both
76     char          *app;                       ///< name of application
77     char          *conn;                      ///< append arbitrary AMF data to the Connect message
78     ClientState   state;                      ///< current state
79     int           main_channel_id;            ///< an additional channel ID which is used for some invocations
80     uint8_t*      flv_data;                   ///< buffer with data for demuxer
81     int           flv_size;                   ///< current buffer size
82     int           flv_off;                    ///< number of bytes read from current buffer
83     int           flv_nb_packets;             ///< number of flv packets published
84     RTMPPacket    out_pkt;                    ///< rtmp packet, created from flv a/v or metadata (for output)
85     uint32_t      client_report_size;         ///< number of bytes after which client should report to server
86     uint32_t      bytes_read;                 ///< number of bytes read from server
87     uint32_t      last_bytes_read;            ///< number of bytes read last reported to server
88     int           skip_bytes;                 ///< number of bytes to skip from the input FLV stream in the next write call
89     uint8_t       flv_header[11];             ///< partial incoming flv packet header
90     int           flv_header_bytes;           ///< number of initialized bytes in flv_header
91     int           nb_invokes;                 ///< keeps track of invoke messages
92     char*         tcurl;                      ///< url of the target stream
93     char*         flashver;                   ///< version of the flash plugin
94     char*         swfhash;                    ///< SHA256 hash of the decompressed SWF file (32 bytes)
95     int           swfhash_len;                ///< length of the SHA256 hash
96     int           swfsize;                    ///< size of the decompressed SWF file
97     char*         swfurl;                     ///< url of the swf player
98     char          swfverification[42];        ///< hash of the SWF verification
99     char*         pageurl;                    ///< url of the web page
100     char*         subscribe;                  ///< name of live stream to subscribe
101     int           server_bw;                  ///< server bandwidth
102     int           client_buffer_time;         ///< client buffer time in ms
103     int           flush_interval;             ///< number of packets flushed in the same request (RTMPT only)
104     int           encrypted;                  ///< use an encrypted connection (RTMPE only)
105     TrackedMethod*tracked_methods;            ///< tracked methods buffer
106     int           nb_tracked_methods;         ///< number of tracked methods
107     int           tracked_methods_size;       ///< size of the tracked methods buffer
108 } RTMPContext;
109
110 #define PLAYER_KEY_OPEN_PART_LEN 30   ///< length of partial key used for first client digest signing
111 /** Client key used for digest signing */
112 static const uint8_t rtmp_player_key[] = {
113     'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
114     'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
115
116     0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
117     0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
118     0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
119 };
120
121 #define SERVER_KEY_OPEN_PART_LEN 36   ///< length of partial key used for first server digest signing
122 /** Key used for RTMP server digest signing */
123 static const uint8_t rtmp_server_key[] = {
124     'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
125     'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
126     'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
127
128     0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
129     0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
130     0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
131 };
132
133 static int add_tracked_method(RTMPContext *rt, const char *name, int id)
134 {
135     void *ptr;
136
137     if (rt->nb_tracked_methods + 1 > rt->tracked_methods_size) {
138         rt->tracked_methods_size = (rt->nb_tracked_methods + 1) * 2;
139         ptr = av_realloc(rt->tracked_methods,
140                          rt->tracked_methods_size * sizeof(*rt->tracked_methods));
141         if (!ptr)
142             return AVERROR(ENOMEM);
143         rt->tracked_methods = ptr;
144     }
145
146     rt->tracked_methods[rt->nb_tracked_methods].name = av_strdup(name);
147     if (!rt->tracked_methods[rt->nb_tracked_methods].name)
148         return AVERROR(ENOMEM);
149     rt->tracked_methods[rt->nb_tracked_methods].id = id;
150     rt->nb_tracked_methods++;
151
152     return 0;
153 }
154
155 static void del_tracked_method(RTMPContext *rt, int index)
156 {
157     memmove(&rt->tracked_methods[index], &rt->tracked_methods[index + 1],
158             sizeof(*rt->tracked_methods) * (rt->nb_tracked_methods - index - 1));
159     rt->nb_tracked_methods--;
160 }
161
162 static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset,
163                                char **tracked_method)
164 {
165     RTMPContext *rt = s->priv_data;
166     GetByteContext gbc;
167     double pkt_id;
168     int ret;
169     int i;
170
171     bytestream2_init(&gbc, pkt->data + offset, pkt->data_size - offset);
172     if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
173         return ret;
174
175     for (i = 0; i < rt->nb_tracked_methods; i++) {
176         if (rt->tracked_methods[i].id != pkt_id)
177             continue;
178
179         *tracked_method = rt->tracked_methods[i].name;
180         del_tracked_method(rt, i);
181         break;
182     }
183
184     return 0;
185 }
186
187 static void free_tracked_methods(RTMPContext *rt)
188 {
189     int i;
190
191     for (i = 0; i < rt->nb_tracked_methods; i ++)
192         av_free(rt->tracked_methods[i].name);
193     av_free(rt->tracked_methods);
194 }
195
196 static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
197 {
198     int ret;
199
200     if (pkt->type == RTMP_PT_INVOKE && track) {
201         GetByteContext gbc;
202         char name[128];
203         double pkt_id;
204         int len;
205
206         bytestream2_init(&gbc, pkt->data, pkt->data_size);
207         if ((ret = ff_amf_read_string(&gbc, name, sizeof(name), &len)) < 0)
208             goto fail;
209
210         if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
211             goto fail;
212
213         if ((ret = add_tracked_method(rt, name, pkt_id)) < 0)
214             goto fail;
215     }
216
217     ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
218                                rt->prev_pkt[1]);
219 fail:
220     ff_rtmp_packet_destroy(pkt);
221     return ret;
222 }
223
224 static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
225 {
226     char *field, *value;
227     char type;
228
229     /* The type must be B for Boolean, N for number, S for string, O for
230      * object, or Z for null. For Booleans the data must be either 0 or 1 for
231      * FALSE or TRUE, respectively. Likewise for Objects the data must be
232      * 0 or 1 to end or begin an object, respectively. Data items in subobjects
233      * may be named, by prefixing the type with 'N' and specifying the name
234      * before the value (ie. NB:myFlag:1). This option may be used multiple times
235      * to construct arbitrary AMF sequences. */
236     if (param[0] && param[1] == ':') {
237         type = param[0];
238         value = param + 2;
239     } else if (param[0] == 'N' && param[1] && param[2] == ':') {
240         type = param[1];
241         field = param + 3;
242         value = strchr(field, ':');
243         if (!value)
244             goto fail;
245         *value = '\0';
246         value++;
247
248         if (!field || !value)
249             goto fail;
250
251         ff_amf_write_field_name(p, field);
252     } else {
253         goto fail;
254     }
255
256     switch (type) {
257     case 'B':
258         ff_amf_write_bool(p, value[0] != '0');
259         break;
260     case 'S':
261         ff_amf_write_string(p, value);
262         break;
263     case 'N':
264         ff_amf_write_number(p, strtod(value, NULL));
265         break;
266     case 'Z':
267         ff_amf_write_null(p);
268         break;
269     case 'O':
270         if (value[0] != '0')
271             ff_amf_write_object_start(p);
272         else
273             ff_amf_write_object_end(p);
274         break;
275     default:
276         goto fail;
277         break;
278     }
279
280     return 0;
281
282 fail:
283     av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
284     return AVERROR(EINVAL);
285 }
286
287 /**
288  * Generate 'connect' call and send it to the server.
289  */
290 static int gen_connect(URLContext *s, RTMPContext *rt)
291 {
292     RTMPPacket pkt;
293     uint8_t *p;
294     int ret;
295
296     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
297                                      0, 4096)) < 0)
298         return ret;
299
300     p = pkt.data;
301
302     ff_amf_write_string(&p, "connect");
303     ff_amf_write_number(&p, ++rt->nb_invokes);
304     ff_amf_write_object_start(&p);
305     ff_amf_write_field_name(&p, "app");
306     ff_amf_write_string(&p, rt->app);
307
308     if (!rt->is_input) {
309         ff_amf_write_field_name(&p, "type");
310         ff_amf_write_string(&p, "nonprivate");
311     }
312     ff_amf_write_field_name(&p, "flashVer");
313     ff_amf_write_string(&p, rt->flashver);
314
315     if (rt->swfurl) {
316         ff_amf_write_field_name(&p, "swfUrl");
317         ff_amf_write_string(&p, rt->swfurl);
318     }
319
320     ff_amf_write_field_name(&p, "tcUrl");
321     ff_amf_write_string(&p, rt->tcurl);
322     if (rt->is_input) {
323         ff_amf_write_field_name(&p, "fpad");
324         ff_amf_write_bool(&p, 0);
325         ff_amf_write_field_name(&p, "capabilities");
326         ff_amf_write_number(&p, 15.0);
327
328         /* Tell the server we support all the audio codecs except
329          * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
330          * which are unused in the RTMP protocol implementation. */
331         ff_amf_write_field_name(&p, "audioCodecs");
332         ff_amf_write_number(&p, 4071.0);
333         ff_amf_write_field_name(&p, "videoCodecs");
334         ff_amf_write_number(&p, 252.0);
335         ff_amf_write_field_name(&p, "videoFunction");
336         ff_amf_write_number(&p, 1.0);
337
338         if (rt->pageurl) {
339             ff_amf_write_field_name(&p, "pageUrl");
340             ff_amf_write_string(&p, rt->pageurl);
341         }
342     }
343     ff_amf_write_object_end(&p);
344
345     if (rt->conn) {
346         char *param = rt->conn;
347
348         // Write arbitrary AMF data to the Connect message.
349         while (param != NULL) {
350             char *sep;
351             param += strspn(param, " ");
352             if (!*param)
353                 break;
354             sep = strchr(param, ' ');
355             if (sep)
356                 *sep = '\0';
357             if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
358                 // Invalid AMF parameter.
359                 ff_rtmp_packet_destroy(&pkt);
360                 return ret;
361             }
362
363             if (sep)
364                 param = sep + 1;
365             else
366                 break;
367         }
368     }
369
370     pkt.data_size = p - pkt.data;
371
372     return rtmp_send_packet(rt, &pkt, 1);
373 }
374
375 /**
376  * Generate 'releaseStream' call and send it to the server. It should make
377  * the server release some channel for media streams.
378  */
379 static int gen_release_stream(URLContext *s, RTMPContext *rt)
380 {
381     RTMPPacket pkt;
382     uint8_t *p;
383     int ret;
384
385     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
386                                      0, 29 + strlen(rt->playpath))) < 0)
387         return ret;
388
389     av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
390     p = pkt.data;
391     ff_amf_write_string(&p, "releaseStream");
392     ff_amf_write_number(&p, ++rt->nb_invokes);
393     ff_amf_write_null(&p);
394     ff_amf_write_string(&p, rt->playpath);
395
396     return rtmp_send_packet(rt, &pkt, 0);
397 }
398
399 /**
400  * Generate 'FCPublish' call and send it to the server. It should make
401  * the server preapare for receiving media streams.
402  */
403 static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
404 {
405     RTMPPacket pkt;
406     uint8_t *p;
407     int ret;
408
409     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
410                                      0, 25 + strlen(rt->playpath))) < 0)
411         return ret;
412
413     av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
414     p = pkt.data;
415     ff_amf_write_string(&p, "FCPublish");
416     ff_amf_write_number(&p, ++rt->nb_invokes);
417     ff_amf_write_null(&p);
418     ff_amf_write_string(&p, rt->playpath);
419
420     return rtmp_send_packet(rt, &pkt, 0);
421 }
422
423 /**
424  * Generate 'FCUnpublish' call and send it to the server. It should make
425  * the server destroy stream.
426  */
427 static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
428 {
429     RTMPPacket pkt;
430     uint8_t *p;
431     int ret;
432
433     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
434                                      0, 27 + strlen(rt->playpath))) < 0)
435         return ret;
436
437     av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
438     p = pkt.data;
439     ff_amf_write_string(&p, "FCUnpublish");
440     ff_amf_write_number(&p, ++rt->nb_invokes);
441     ff_amf_write_null(&p);
442     ff_amf_write_string(&p, rt->playpath);
443
444     return rtmp_send_packet(rt, &pkt, 0);
445 }
446
447 /**
448  * Generate 'createStream' call and send it to the server. It should make
449  * the server allocate some channel for media streams.
450  */
451 static int gen_create_stream(URLContext *s, RTMPContext *rt)
452 {
453     RTMPPacket pkt;
454     uint8_t *p;
455     int ret;
456
457     av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
458
459     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
460                                      0, 25)) < 0)
461         return ret;
462
463     p = pkt.data;
464     ff_amf_write_string(&p, "createStream");
465     ff_amf_write_number(&p, ++rt->nb_invokes);
466     ff_amf_write_null(&p);
467
468     return rtmp_send_packet(rt, &pkt, 1);
469 }
470
471
472 /**
473  * Generate 'deleteStream' call and send it to the server. It should make
474  * the server remove some channel for media streams.
475  */
476 static int gen_delete_stream(URLContext *s, RTMPContext *rt)
477 {
478     RTMPPacket pkt;
479     uint8_t *p;
480     int ret;
481
482     av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
483
484     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
485                                      0, 34)) < 0)
486         return ret;
487
488     p = pkt.data;
489     ff_amf_write_string(&p, "deleteStream");
490     ff_amf_write_number(&p, ++rt->nb_invokes);
491     ff_amf_write_null(&p);
492     ff_amf_write_number(&p, rt->main_channel_id);
493
494     return rtmp_send_packet(rt, &pkt, 0);
495 }
496
497 /**
498  * Generate client buffer time and send it to the server.
499  */
500 static int gen_buffer_time(URLContext *s, RTMPContext *rt)
501 {
502     RTMPPacket pkt;
503     uint8_t *p;
504     int ret;
505
506     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
507                                      1, 10)) < 0)
508         return ret;
509
510     p = pkt.data;
511     bytestream_put_be16(&p, 3);
512     bytestream_put_be32(&p, rt->main_channel_id);
513     bytestream_put_be32(&p, rt->client_buffer_time);
514
515     return rtmp_send_packet(rt, &pkt, 0);
516 }
517
518 /**
519  * Generate 'play' call and send it to the server, then ping the server
520  * to start actual playing.
521  */
522 static int gen_play(URLContext *s, RTMPContext *rt)
523 {
524     RTMPPacket pkt;
525     uint8_t *p;
526     int ret;
527
528     av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
529
530     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE,
531                                      0, 29 + strlen(rt->playpath))) < 0)
532         return ret;
533
534     pkt.extra = rt->main_channel_id;
535
536     p = pkt.data;
537     ff_amf_write_string(&p, "play");
538     ff_amf_write_number(&p, ++rt->nb_invokes);
539     ff_amf_write_null(&p);
540     ff_amf_write_string(&p, rt->playpath);
541     ff_amf_write_number(&p, rt->live);
542
543     return rtmp_send_packet(rt, &pkt, 1);
544 }
545
546 /**
547  * Generate 'publish' call and send it to the server.
548  */
549 static int gen_publish(URLContext *s, RTMPContext *rt)
550 {
551     RTMPPacket pkt;
552     uint8_t *p;
553     int ret;
554
555     av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
556
557     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
558                                      0, 30 + strlen(rt->playpath))) < 0)
559         return ret;
560
561     pkt.extra = rt->main_channel_id;
562
563     p = pkt.data;
564     ff_amf_write_string(&p, "publish");
565     ff_amf_write_number(&p, ++rt->nb_invokes);
566     ff_amf_write_null(&p);
567     ff_amf_write_string(&p, rt->playpath);
568     ff_amf_write_string(&p, "live");
569
570     return rtmp_send_packet(rt, &pkt, 1);
571 }
572
573 /**
574  * Generate ping reply and send it to the server.
575  */
576 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
577 {
578     RTMPPacket pkt;
579     uint8_t *p;
580     int ret;
581
582     if (ppkt->data_size < 6) {
583         av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
584                ppkt->data_size);
585         return AVERROR_INVALIDDATA;
586     }
587
588     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
589                                      ppkt->timestamp + 1, 6)) < 0)
590         return ret;
591
592     p = pkt.data;
593     bytestream_put_be16(&p, 7);
594     bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
595
596     return rtmp_send_packet(rt, &pkt, 0);
597 }
598
599 /**
600  * Generate SWF verification message and send it to the server.
601  */
602 static int gen_swf_verification(URLContext *s, RTMPContext *rt)
603 {
604     RTMPPacket pkt;
605     uint8_t *p;
606     int ret;
607
608     av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
609     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
610                                      0, 44)) < 0)
611         return ret;
612
613     p = pkt.data;
614     bytestream_put_be16(&p, 27);
615     memcpy(p, rt->swfverification, 42);
616
617     return rtmp_send_packet(rt, &pkt, 0);
618 }
619
620 /**
621  * Generate server bandwidth message and send it to the server.
622  */
623 static int gen_server_bw(URLContext *s, RTMPContext *rt)
624 {
625     RTMPPacket pkt;
626     uint8_t *p;
627     int ret;
628
629     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
630                                      0, 4)) < 0)
631         return ret;
632
633     p = pkt.data;
634     bytestream_put_be32(&p, rt->server_bw);
635
636     return rtmp_send_packet(rt, &pkt, 0);
637 }
638
639 /**
640  * Generate check bandwidth message and send it to the server.
641  */
642 static int gen_check_bw(URLContext *s, RTMPContext *rt)
643 {
644     RTMPPacket pkt;
645     uint8_t *p;
646     int ret;
647
648     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
649                                      0, 21)) < 0)
650         return ret;
651
652     p = pkt.data;
653     ff_amf_write_string(&p, "_checkbw");
654     ff_amf_write_number(&p, ++rt->nb_invokes);
655     ff_amf_write_null(&p);
656
657     return rtmp_send_packet(rt, &pkt, 1);
658 }
659
660 /**
661  * Generate report on bytes read so far and send it to the server.
662  */
663 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
664 {
665     RTMPPacket pkt;
666     uint8_t *p;
667     int ret;
668
669     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
670                                      ts, 4)) < 0)
671         return ret;
672
673     p = pkt.data;
674     bytestream_put_be32(&p, rt->bytes_read);
675
676     return rtmp_send_packet(rt, &pkt, 0);
677 }
678
679 static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
680                                   const char *subscribe)
681 {
682     RTMPPacket pkt;
683     uint8_t *p;
684     int ret;
685
686     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
687                                      0, 27 + strlen(subscribe))) < 0)
688         return ret;
689
690     p = pkt.data;
691     ff_amf_write_string(&p, "FCSubscribe");
692     ff_amf_write_number(&p, ++rt->nb_invokes);
693     ff_amf_write_null(&p);
694     ff_amf_write_string(&p, subscribe);
695
696     return rtmp_send_packet(rt, &pkt, 1);
697 }
698
699 int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
700                         const uint8_t *key, int keylen, uint8_t *dst)
701 {
702     struct AVSHA *sha;
703     uint8_t hmac_buf[64+32] = {0};
704     int i;
705
706     sha = av_mallocz(av_sha_size);
707     if (!sha)
708         return AVERROR(ENOMEM);
709
710     if (keylen < 64) {
711         memcpy(hmac_buf, key, keylen);
712     } else {
713         av_sha_init(sha, 256);
714         av_sha_update(sha,key, keylen);
715         av_sha_final(sha, hmac_buf);
716     }
717     for (i = 0; i < 64; i++)
718         hmac_buf[i] ^= HMAC_IPAD_VAL;
719
720     av_sha_init(sha, 256);
721     av_sha_update(sha, hmac_buf, 64);
722     if (gap <= 0) {
723         av_sha_update(sha, src, len);
724     } else { //skip 32 bytes used for storing digest
725         av_sha_update(sha, src, gap);
726         av_sha_update(sha, src + gap + 32, len - gap - 32);
727     }
728     av_sha_final(sha, hmac_buf + 64);
729
730     for (i = 0; i < 64; i++)
731         hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
732     av_sha_init(sha, 256);
733     av_sha_update(sha, hmac_buf, 64+32);
734     av_sha_final(sha, dst);
735
736     av_free(sha);
737
738     return 0;
739 }
740
741 int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
742                             int add_val)
743 {
744     int i, digest_pos = 0;
745
746     for (i = 0; i < 4; i++)
747         digest_pos += buf[i + off];
748     digest_pos = digest_pos % mod_val + add_val;
749
750     return digest_pos;
751 }
752
753 /**
754  * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
755  * will be stored) into that packet.
756  *
757  * @param buf handshake data (1536 bytes)
758  * @param encrypted use an encrypted connection (RTMPE)
759  * @return offset to the digest inside input data
760  */
761 static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
762 {
763     int ret, digest_pos;
764
765     if (encrypted)
766         digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
767     else
768         digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
769
770     ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
771                               rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
772                               buf + digest_pos);
773     if (ret < 0)
774         return ret;
775
776     return digest_pos;
777 }
778
779 /**
780  * Verify that the received server response has the expected digest value.
781  *
782  * @param buf handshake data received from the server (1536 bytes)
783  * @param off position to search digest offset from
784  * @return 0 if digest is valid, digest position otherwise
785  */
786 static int rtmp_validate_digest(uint8_t *buf, int off)
787 {
788     uint8_t digest[32];
789     int ret, digest_pos;
790
791     digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
792
793     ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
794                               rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
795                               digest);
796     if (ret < 0)
797         return ret;
798
799     if (!memcmp(digest, buf + digest_pos, 32))
800         return digest_pos;
801     return 0;
802 }
803
804 static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
805                                       uint8_t *buf)
806 {
807     uint8_t *p;
808     int ret;
809
810     if (rt->swfhash_len != 32) {
811         av_log(s, AV_LOG_ERROR,
812                "Hash of the decompressed SWF file is not 32 bytes long.\n");
813         return AVERROR(EINVAL);
814     }
815
816     p = &rt->swfverification[0];
817     bytestream_put_byte(&p, 1);
818     bytestream_put_byte(&p, 1);
819     bytestream_put_be32(&p, rt->swfsize);
820     bytestream_put_be32(&p, rt->swfsize);
821
822     if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
823         return ret;
824
825     return 0;
826 }
827
828 /**
829  * Perform handshake with the server by means of exchanging pseudorandom data
830  * signed with HMAC-SHA2 digest.
831  *
832  * @return 0 if handshake succeeds, negative value otherwise
833  */
834 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
835 {
836     AVLFG rnd;
837     uint8_t tosend    [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
838         3,                // unencrypted data
839         0, 0, 0, 0,       // client uptime
840         RTMP_CLIENT_VER1,
841         RTMP_CLIENT_VER2,
842         RTMP_CLIENT_VER3,
843         RTMP_CLIENT_VER4,
844     };
845     uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
846     uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
847     int i;
848     int server_pos, client_pos;
849     uint8_t digest[32], signature[32];
850     int ret, type = 0;
851
852     av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
853
854     av_lfg_init(&rnd, 0xDEADC0DE);
855     // generate handshake packet - 1536 bytes of pseudorandom data
856     for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
857         tosend[i] = av_lfg_get(&rnd) >> 24;
858
859     if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
860         /* When the client wants to use RTMPE, we have to change the command
861          * byte to 0x06 which means to use encrypted data and we have to set
862          * the flash version to at least 9.0.115.0. */
863         tosend[0] = 6;
864         tosend[5] = 128;
865         tosend[6] = 0;
866         tosend[7] = 3;
867         tosend[8] = 2;
868
869         /* Initialize the Diffie-Hellmann context and generate the public key
870          * to send to the server. */
871         if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
872             return ret;
873     }
874
875     client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
876     if (client_pos < 0)
877         return client_pos;
878
879     if ((ret = ffurl_write(rt->stream, tosend,
880                            RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
881         av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
882         return ret;
883     }
884
885     if ((ret = ffurl_read_complete(rt->stream, serverdata,
886                                    RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
887         av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
888         return ret;
889     }
890
891     if ((ret = ffurl_read_complete(rt->stream, clientdata,
892                                    RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
893         av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
894         return ret;
895     }
896
897     av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
898     av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
899            serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
900
901     if (rt->is_input && serverdata[5] >= 3) {
902         server_pos = rtmp_validate_digest(serverdata + 1, 772);
903         if (server_pos < 0)
904             return server_pos;
905
906         if (!server_pos) {
907             type = 1;
908             server_pos = rtmp_validate_digest(serverdata + 1, 8);
909             if (server_pos < 0)
910                 return server_pos;
911
912             if (!server_pos) {
913                 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
914                 return AVERROR(EIO);
915             }
916         }
917
918         /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
919          * key are the last 32 bytes of the server handshake. */
920         if (rt->swfsize) {
921             if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
922                                                   RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
923                 return ret;
924         }
925
926         ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
927                                   rtmp_server_key, sizeof(rtmp_server_key),
928                                   digest);
929         if (ret < 0)
930             return ret;
931
932         ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
933                                   0, digest, 32, signature);
934         if (ret < 0)
935             return ret;
936
937         if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
938             /* Compute the shared secret key sent by the server and initialize
939              * the RC4 encryption. */
940             if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
941                                                    tosend + 1, type)) < 0)
942                 return ret;
943
944             /* Encrypt the signature received by the server. */
945             ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
946         }
947
948         if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
949             av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
950             return AVERROR(EIO);
951         }
952
953         for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
954             tosend[i] = av_lfg_get(&rnd) >> 24;
955         ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
956                                   rtmp_player_key, sizeof(rtmp_player_key),
957                                   digest);
958         if (ret < 0)
959             return ret;
960
961         ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
962                                   digest, 32,
963                                   tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
964         if (ret < 0)
965             return ret;
966
967         if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
968             /* Encrypt the signature to be send to the server. */
969             ff_rtmpe_encrypt_sig(rt->stream, tosend +
970                                  RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
971                                  serverdata[0]);
972         }
973
974         // write reply back to the server
975         if ((ret = ffurl_write(rt->stream, tosend,
976                                RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
977             return ret;
978
979         if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
980             /* Set RC4 keys for encryption and update the keystreams. */
981             if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
982                 return ret;
983         }
984     } else {
985         if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
986             /* Compute the shared secret key sent by the server and initialize
987              * the RC4 encryption. */
988             if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
989                             tosend + 1, 1)) < 0)
990                 return ret;
991
992             if (serverdata[0] == 9) {
993                 /* Encrypt the signature received by the server. */
994                 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
995                                      serverdata[0]);
996             }
997         }
998
999         if ((ret = ffurl_write(rt->stream, serverdata + 1,
1000                                RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1001             return ret;
1002
1003         if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1004             /* Set RC4 keys for encryption and update the keystreams. */
1005             if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1006                 return ret;
1007         }
1008     }
1009
1010     return 0;
1011 }
1012
1013 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1014 {
1015     RTMPContext *rt = s->priv_data;
1016     int ret;
1017
1018     if (pkt->data_size < 4) {
1019         av_log(s, AV_LOG_ERROR,
1020                "Too short chunk size change packet (%d)\n",
1021                pkt->data_size);
1022         return AVERROR_INVALIDDATA;
1023     }
1024
1025     if (!rt->is_input) {
1026         /* Send the same chunk size change packet back to the server,
1027          * setting the outgoing chunk size to the same as the incoming one. */
1028         if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1029                                         rt->prev_pkt[1])) < 0)
1030             return ret;
1031         rt->out_chunk_size = AV_RB32(pkt->data);
1032     }
1033
1034     rt->in_chunk_size = AV_RB32(pkt->data);
1035     if (rt->in_chunk_size <= 0) {
1036         av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1037                rt->in_chunk_size);
1038         return AVERROR_INVALIDDATA;
1039     }
1040     av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1041            rt->in_chunk_size);
1042
1043     return 0;
1044 }
1045
1046 static int handle_ping(URLContext *s, RTMPPacket *pkt)
1047 {
1048     RTMPContext *rt = s->priv_data;
1049     int t, ret;
1050
1051     if (pkt->data_size < 2) {
1052         av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
1053                pkt->data_size);
1054         return AVERROR_INVALIDDATA;
1055     }
1056
1057     t = AV_RB16(pkt->data);
1058     if (t == 6) {
1059         if ((ret = gen_pong(s, rt, pkt)) < 0)
1060             return ret;
1061     } else if (t == 26) {
1062         if (rt->swfsize) {
1063             if ((ret = gen_swf_verification(s, rt)) < 0)
1064                 return ret;
1065         } else {
1066             av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1067         }
1068     }
1069
1070     return 0;
1071 }
1072
1073 static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
1074 {
1075     RTMPContext *rt = s->priv_data;
1076
1077     if (pkt->data_size < 4) {
1078         av_log(s, AV_LOG_ERROR,
1079                "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1080                pkt->data_size);
1081         return AVERROR_INVALIDDATA;
1082     }
1083
1084     rt->client_report_size = AV_RB32(pkt->data);
1085     if (rt->client_report_size <= 0) {
1086         av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
1087                 rt->client_report_size);
1088         return AVERROR_INVALIDDATA;
1089
1090     }
1091     av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
1092     rt->client_report_size >>= 1;
1093
1094     return 0;
1095 }
1096
1097 static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
1098 {
1099     RTMPContext *rt = s->priv_data;
1100
1101     if (pkt->data_size < 4) {
1102         av_log(s, AV_LOG_ERROR,
1103                "Too short server bandwidth report packet (%d)\n",
1104                pkt->data_size);
1105         return AVERROR_INVALIDDATA;
1106     }
1107
1108     rt->server_bw = AV_RB32(pkt->data);
1109     if (rt->server_bw <= 0) {
1110         av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
1111                rt->server_bw);
1112         return AVERROR_INVALIDDATA;
1113     }
1114     av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
1115
1116     return 0;
1117 }
1118
1119 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1120 {
1121     const uint8_t *data_end = pkt->data + pkt->data_size;
1122     char *tracked_method = NULL;
1123     int level = AV_LOG_ERROR;
1124     uint8_t tmpstr[256];
1125     int ret;
1126
1127     if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1128         return ret;
1129
1130     if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1131                                 "description", tmpstr, sizeof(tmpstr))) {
1132         if (tracked_method && !strcmp(tracked_method, "_checkbw")) {
1133             /* Ignore _checkbw errors. */
1134             level = AV_LOG_WARNING;
1135             ret = 0;
1136         } else
1137             ret = -1;
1138         av_log(s, level, "Server error: %s\n", tmpstr);
1139     }
1140
1141     av_free(tracked_method);
1142     return ret;
1143 }
1144
1145 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1146 {
1147     RTMPContext *rt = s->priv_data;
1148     char *tracked_method = NULL;
1149     int ret = 0;
1150
1151     if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1152         return ret;
1153
1154     if (!tracked_method) {
1155         /* Ignore this reply when the current method is not tracked. */
1156         return ret;
1157     }
1158
1159     if (!memcmp(tracked_method, "connect", 7)) {
1160         if (!rt->is_input) {
1161             if ((ret = gen_release_stream(s, rt)) < 0)
1162                 goto fail;
1163
1164             if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1165                 goto fail;
1166         } else {
1167             if ((ret = gen_server_bw(s, rt)) < 0)
1168                 goto fail;
1169         }
1170
1171         if ((ret = gen_create_stream(s, rt)) < 0)
1172             goto fail;
1173
1174         if (rt->is_input) {
1175             /* Send the FCSubscribe command when the name of live
1176              * stream is defined by the user or if it's a live stream. */
1177             if (rt->subscribe) {
1178                 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1179                     goto fail;
1180             } else if (rt->live == -1) {
1181                 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1182                     goto fail;
1183             }
1184         }
1185     } else if (!memcmp(tracked_method, "createStream", 12)) {
1186         //extract a number from the result
1187         if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1188             av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
1189         } else {
1190             rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
1191         }
1192
1193         if (!rt->is_input) {
1194             if ((ret = gen_publish(s, rt)) < 0)
1195                 goto fail;
1196         } else {
1197             if ((ret = gen_play(s, rt)) < 0)
1198                 goto fail;
1199             if ((ret = gen_buffer_time(s, rt)) < 0)
1200                 goto fail;
1201         }
1202     }
1203
1204 fail:
1205     av_free(tracked_method);
1206     return ret;
1207 }
1208
1209 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
1210 {
1211     RTMPContext *rt = s->priv_data;
1212     const uint8_t *data_end = pkt->data + pkt->data_size;
1213     const uint8_t *ptr = pkt->data + 11;
1214     uint8_t tmpstr[256];
1215     int i, t;
1216
1217     for (i = 0; i < 2; i++) {
1218         t = ff_amf_tag_size(ptr, data_end);
1219         if (t < 0)
1220             return 1;
1221         ptr += t;
1222     }
1223
1224     t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
1225     if (!t && !strcmp(tmpstr, "error")) {
1226         if (!ff_amf_get_field_value(ptr, data_end,
1227                                     "description", tmpstr, sizeof(tmpstr)))
1228             av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
1229         return -1;
1230     }
1231
1232     t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
1233     if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
1234     if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
1235     if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
1236     if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
1237
1238     return 0;
1239 }
1240
1241 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
1242 {
1243     RTMPContext *rt = s->priv_data;
1244     int ret = 0;
1245
1246     //TODO: check for the messages sent for wrong state?
1247     if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
1248         if ((ret = handle_invoke_error(s, pkt)) < 0)
1249             return ret;
1250     } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
1251         if ((ret = handle_invoke_result(s, pkt)) < 0)
1252             return ret;
1253     } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
1254         if ((ret = handle_invoke_status(s, pkt)) < 0)
1255             return ret;
1256     } else if (!memcmp(pkt->data, "\002\000\010onBWDone", 11)) {
1257         if ((ret = gen_check_bw(s, rt)) < 0)
1258             return ret;
1259     }
1260
1261     return ret;
1262 }
1263
1264 /**
1265  * Parse received packet and possibly perform some action depending on
1266  * the packet contents.
1267  * @return 0 for no errors, negative values for serious errors which prevent
1268  *         further communications, positive values for uncritical errors
1269  */
1270 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
1271 {
1272     int ret;
1273
1274 #ifdef DEBUG
1275     ff_rtmp_packet_dump(s, pkt);
1276 #endif
1277
1278     switch (pkt->type) {
1279     case RTMP_PT_BYTES_READ:
1280         av_dlog(s, "received bytes read report\n");
1281         break;
1282     case RTMP_PT_CHUNK_SIZE:
1283         if ((ret = handle_chunk_size(s, pkt)) < 0)
1284             return ret;
1285         break;
1286     case RTMP_PT_PING:
1287         if ((ret = handle_ping(s, pkt)) < 0)
1288             return ret;
1289         break;
1290     case RTMP_PT_CLIENT_BW:
1291         if ((ret = handle_client_bw(s, pkt)) < 0)
1292             return ret;
1293         break;
1294     case RTMP_PT_SERVER_BW:
1295         if ((ret = handle_server_bw(s, pkt)) < 0)
1296             return ret;
1297         break;
1298     case RTMP_PT_INVOKE:
1299         if ((ret = handle_invoke(s, pkt)) < 0)
1300             return ret;
1301         break;
1302     case RTMP_PT_VIDEO:
1303     case RTMP_PT_AUDIO:
1304     case RTMP_PT_METADATA:
1305         /* Audio, Video and Metadata packets are parsed in get_packet() */
1306         break;
1307     default:
1308         av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
1309         break;
1310     }
1311     return 0;
1312 }
1313
1314 /**
1315  * Interact with the server by receiving and sending RTMP packets until
1316  * there is some significant data (media data or expected status notification).
1317  *
1318  * @param s          reading context
1319  * @param for_header non-zero value tells function to work until it
1320  * gets notification from the server that playing has been started,
1321  * otherwise function will work until some media data is received (or
1322  * an error happens)
1323  * @return 0 for successful operation, negative value in case of error
1324  */
1325 static int get_packet(URLContext *s, int for_header)
1326 {
1327     RTMPContext *rt = s->priv_data;
1328     int ret;
1329     uint8_t *p;
1330     const uint8_t *next;
1331     uint32_t data_size;
1332     uint32_t ts, cts, pts=0;
1333
1334     if (rt->state == STATE_STOPPED)
1335         return AVERROR_EOF;
1336
1337     for (;;) {
1338         RTMPPacket rpkt = { 0 };
1339         if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
1340                                        rt->in_chunk_size, rt->prev_pkt[0])) <= 0) {
1341             if (ret == 0) {
1342                 return AVERROR(EAGAIN);
1343             } else {
1344                 return AVERROR(EIO);
1345             }
1346         }
1347         rt->bytes_read += ret;
1348         if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
1349             av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
1350             if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
1351                 return ret;
1352             rt->last_bytes_read = rt->bytes_read;
1353         }
1354
1355         ret = rtmp_parse_result(s, rt, &rpkt);
1356         if (ret < 0) {//serious error in current packet
1357             ff_rtmp_packet_destroy(&rpkt);
1358             return ret;
1359         }
1360         if (rt->state == STATE_STOPPED) {
1361             ff_rtmp_packet_destroy(&rpkt);
1362             return AVERROR_EOF;
1363         }
1364         if (for_header && (rt->state == STATE_PLAYING || rt->state == STATE_PUBLISHING)) {
1365             ff_rtmp_packet_destroy(&rpkt);
1366             return 0;
1367         }
1368         if (!rpkt.data_size || !rt->is_input) {
1369             ff_rtmp_packet_destroy(&rpkt);
1370             continue;
1371         }
1372         if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
1373            (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
1374             ts = rpkt.timestamp;
1375
1376             // generate packet header and put data into buffer for FLV demuxer
1377             rt->flv_off  = 0;
1378             rt->flv_size = rpkt.data_size + 15;
1379             rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
1380             bytestream_put_byte(&p, rpkt.type);
1381             bytestream_put_be24(&p, rpkt.data_size);
1382             bytestream_put_be24(&p, ts);
1383             bytestream_put_byte(&p, ts >> 24);
1384             bytestream_put_be24(&p, 0);
1385             bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);
1386             bytestream_put_be32(&p, 0);
1387             ff_rtmp_packet_destroy(&rpkt);
1388             return 0;
1389         } else if (rpkt.type == RTMP_PT_METADATA) {
1390             // we got raw FLV data, make it available for FLV demuxer
1391             rt->flv_off  = 0;
1392             rt->flv_size = rpkt.data_size;
1393             rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
1394             /* rewrite timestamps */
1395             next = rpkt.data;
1396             ts = rpkt.timestamp;
1397             while (next - rpkt.data < rpkt.data_size - 11) {
1398                 next++;
1399                 data_size = bytestream_get_be24(&next);
1400                 p=next;
1401                 cts = bytestream_get_be24(&next);
1402                 cts |= bytestream_get_byte(&next) << 24;
1403                 if (pts==0)
1404                     pts=cts;
1405                 ts += cts - pts;
1406                 pts = cts;
1407                 bytestream_put_be24(&p, ts);
1408                 bytestream_put_byte(&p, ts >> 24);
1409                 next += data_size + 3 + 4;
1410             }
1411             memcpy(rt->flv_data, rpkt.data, rpkt.data_size);
1412             ff_rtmp_packet_destroy(&rpkt);
1413             return 0;
1414         }
1415         ff_rtmp_packet_destroy(&rpkt);
1416     }
1417 }
1418
1419 static int rtmp_close(URLContext *h)
1420 {
1421     RTMPContext *rt = h->priv_data;
1422     int ret = 0;
1423
1424     if (!rt->is_input) {
1425         rt->flv_data = NULL;
1426         if (rt->out_pkt.data_size)
1427             ff_rtmp_packet_destroy(&rt->out_pkt);
1428         if (rt->state > STATE_FCPUBLISH)
1429             ret = gen_fcunpublish_stream(h, rt);
1430     }
1431     if (rt->state > STATE_HANDSHAKED)
1432         ret = gen_delete_stream(h, rt);
1433
1434     free_tracked_methods(rt);
1435     av_freep(&rt->flv_data);
1436     ffurl_close(rt->stream);
1437     return ret;
1438 }
1439
1440 /**
1441  * Open RTMP connection and verify that the stream can be played.
1442  *
1443  * URL syntax: rtmp://server[:port][/app][/playpath]
1444  *             where 'app' is first one or two directories in the path
1445  *             (e.g. /ondemand/, /flash/live/, etc.)
1446  *             and 'playpath' is a file name (the rest of the path,
1447  *             may be prefixed with "mp4:")
1448  */
1449 static int rtmp_open(URLContext *s, const char *uri, int flags)
1450 {
1451     RTMPContext *rt = s->priv_data;
1452     char proto[8], hostname[256], path[1024], *fname;
1453     char *old_app;
1454     uint8_t buf[2048];
1455     int port;
1456     AVDictionary *opts = NULL;
1457     int ret;
1458
1459     rt->is_input = !(flags & AVIO_FLAG_WRITE);
1460
1461     av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
1462                  path, sizeof(path), s->filename);
1463
1464     if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
1465         if (!strcmp(proto, "rtmpts"))
1466             av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
1467
1468         /* open the http tunneling connection */
1469         ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
1470     } else if (!strcmp(proto, "rtmps")) {
1471         /* open the tls connection */
1472         if (port < 0)
1473             port = RTMPS_DEFAULT_PORT;
1474         ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
1475     } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
1476         if (!strcmp(proto, "rtmpte"))
1477             av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
1478
1479         /* open the encrypted connection */
1480         ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
1481         rt->encrypted = 1;
1482     } else {
1483         /* open the tcp connection */
1484         if (port < 0)
1485             port = RTMP_DEFAULT_PORT;
1486         ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
1487     }
1488
1489     if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
1490                           &s->interrupt_callback, &opts)) < 0) {
1491         av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
1492         goto fail;
1493     }
1494
1495     rt->state = STATE_START;
1496     if ((ret = rtmp_handshake(s, rt)) < 0)
1497         goto fail;
1498
1499     rt->out_chunk_size = 128;
1500     rt->in_chunk_size  = 128; // Probably overwritten later
1501     rt->state = STATE_HANDSHAKED;
1502
1503     // Keep the application name when it has been defined by the user.
1504     old_app = rt->app;
1505
1506     rt->app = av_malloc(APP_MAX_LENGTH);
1507     if (!rt->app) {
1508         ret = AVERROR(ENOMEM);
1509         goto fail;
1510     }
1511
1512     //extract "app" part from path
1513     if (!strncmp(path, "/ondemand/", 10)) {
1514         fname = path + 10;
1515         memcpy(rt->app, "ondemand", 9);
1516     } else {
1517         char *next = *path ? path + 1 : path;
1518         char *p = strchr(next, '/');
1519         if (!p) {
1520             fname = next;
1521             rt->app[0] = '\0';
1522         } else {
1523             // make sure we do not mismatch a playpath for an application instance
1524             char *c = strchr(p + 1, ':');
1525             fname = strchr(p + 1, '/');
1526             if (!fname || (c && c < fname)) {
1527                 fname = p + 1;
1528                 av_strlcpy(rt->app, path + 1, p - path);
1529             } else {
1530                 fname++;
1531                 av_strlcpy(rt->app, path + 1, fname - path - 1);
1532             }
1533         }
1534     }
1535
1536     if (old_app) {
1537         // The name of application has been defined by the user, override it.
1538         av_free(rt->app);
1539         rt->app = old_app;
1540     }
1541
1542     if (!rt->playpath) {
1543         int len = strlen(fname);
1544
1545         rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
1546         if (!rt->playpath) {
1547             ret = AVERROR(ENOMEM);
1548             goto fail;
1549         }
1550
1551         if (!strchr(fname, ':') && len >= 4 &&
1552             (!strcmp(fname + len - 4, ".f4v") ||
1553              !strcmp(fname + len - 4, ".mp4"))) {
1554             memcpy(rt->playpath, "mp4:", 5);
1555         } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
1556             fname[len - 4] = '\0';
1557         } else {
1558             rt->playpath[0] = 0;
1559         }
1560         strncat(rt->playpath, fname, PLAYPATH_MAX_LENGTH - 5);
1561     }
1562
1563     if (!rt->tcurl) {
1564         rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
1565         if (!rt->tcurl) {
1566             ret = AVERROR(ENOMEM);
1567             goto fail;
1568         }
1569         ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
1570                     port, "/%s", rt->app);
1571     }
1572
1573     if (!rt->flashver) {
1574         rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
1575         if (!rt->flashver) {
1576             ret = AVERROR(ENOMEM);
1577             goto fail;
1578         }
1579         if (rt->is_input) {
1580             snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
1581                     RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
1582                     RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
1583         } else {
1584             snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
1585                     "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
1586         }
1587     }
1588
1589     rt->client_report_size = 1048576;
1590     rt->bytes_read = 0;
1591     rt->last_bytes_read = 0;
1592     rt->server_bw = 2500000;
1593
1594     av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
1595            proto, path, rt->app, rt->playpath);
1596     if ((ret = gen_connect(s, rt)) < 0)
1597         goto fail;
1598
1599     do {
1600         ret = get_packet(s, 1);
1601     } while (ret == EAGAIN);
1602     if (ret < 0)
1603         goto fail;
1604
1605     if (rt->is_input) {
1606         // generate FLV header for demuxer
1607         rt->flv_size = 13;
1608         rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
1609         rt->flv_off  = 0;
1610         memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
1611     } else {
1612         rt->flv_size = 0;
1613         rt->flv_data = NULL;
1614         rt->flv_off  = 0;
1615         rt->skip_bytes = 13;
1616     }
1617
1618     s->max_packet_size = rt->stream->max_packet_size;
1619     s->is_streamed     = 1;
1620     return 0;
1621
1622 fail:
1623     av_dict_free(&opts);
1624     rtmp_close(s);
1625     return ret;
1626 }
1627
1628 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
1629 {
1630     RTMPContext *rt = s->priv_data;
1631     int orig_size = size;
1632     int ret;
1633
1634     while (size > 0) {
1635         int data_left = rt->flv_size - rt->flv_off;
1636
1637         if (data_left >= size) {
1638             memcpy(buf, rt->flv_data + rt->flv_off, size);
1639             rt->flv_off += size;
1640             return orig_size;
1641         }
1642         if (data_left > 0) {
1643             memcpy(buf, rt->flv_data + rt->flv_off, data_left);
1644             buf  += data_left;
1645             size -= data_left;
1646             rt->flv_off = rt->flv_size;
1647             return data_left;
1648         }
1649         if ((ret = get_packet(s, 0)) < 0)
1650            return ret;
1651     }
1652     return orig_size;
1653 }
1654
1655 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
1656 {
1657     RTMPContext *rt = s->priv_data;
1658     int size_temp = size;
1659     int pktsize, pkttype;
1660     uint32_t ts;
1661     const uint8_t *buf_temp = buf;
1662     uint8_t c;
1663     int ret;
1664
1665     do {
1666         if (rt->skip_bytes) {
1667             int skip = FFMIN(rt->skip_bytes, size_temp);
1668             buf_temp       += skip;
1669             size_temp      -= skip;
1670             rt->skip_bytes -= skip;
1671             continue;
1672         }
1673
1674         if (rt->flv_header_bytes < 11) {
1675             const uint8_t *header = rt->flv_header;
1676             int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
1677             bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
1678             rt->flv_header_bytes += copy;
1679             size_temp            -= copy;
1680             if (rt->flv_header_bytes < 11)
1681                 break;
1682
1683             pkttype = bytestream_get_byte(&header);
1684             pktsize = bytestream_get_be24(&header);
1685             ts = bytestream_get_be24(&header);
1686             ts |= bytestream_get_byte(&header) << 24;
1687             bytestream_get_be24(&header);
1688             rt->flv_size = pktsize;
1689
1690             //force 12bytes header
1691             if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
1692                 pkttype == RTMP_PT_NOTIFY) {
1693                 if (pkttype == RTMP_PT_NOTIFY)
1694                     pktsize += 16;
1695                 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
1696             }
1697
1698             //this can be a big packet, it's better to send it right here
1699             if ((ret = ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL,
1700                                              pkttype, ts, pktsize)) < 0)
1701                 return ret;
1702
1703             rt->out_pkt.extra = rt->main_channel_id;
1704             rt->flv_data = rt->out_pkt.data;
1705
1706             if (pkttype == RTMP_PT_NOTIFY)
1707                 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
1708         }
1709
1710         if (rt->flv_size - rt->flv_off > size_temp) {
1711             bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
1712             rt->flv_off += size_temp;
1713             size_temp = 0;
1714         } else {
1715             bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
1716             size_temp   -= rt->flv_size - rt->flv_off;
1717             rt->flv_off += rt->flv_size - rt->flv_off;
1718         }
1719
1720         if (rt->flv_off == rt->flv_size) {
1721             rt->skip_bytes = 4;
1722
1723             if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
1724                 return ret;
1725             rt->flv_size = 0;
1726             rt->flv_off = 0;
1727             rt->flv_header_bytes = 0;
1728             rt->flv_nb_packets++;
1729         }
1730     } while (buf_temp - buf < size);
1731
1732     if (rt->flv_nb_packets < rt->flush_interval)
1733         return size;
1734     rt->flv_nb_packets = 0;
1735
1736     /* set stream into nonblocking mode */
1737     rt->stream->flags |= AVIO_FLAG_NONBLOCK;
1738
1739     /* try to read one byte from the stream */
1740     ret = ffurl_read(rt->stream, &c, 1);
1741
1742     /* switch the stream back into blocking mode */
1743     rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
1744
1745     if (ret == AVERROR(EAGAIN)) {
1746         /* no incoming data to handle */
1747         return size;
1748     } else if (ret < 0) {
1749         return ret;
1750     } else if (ret == 1) {
1751         RTMPPacket rpkt = { 0 };
1752
1753         if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
1754                                                 rt->in_chunk_size,
1755                                                 rt->prev_pkt[0], c)) <= 0)
1756              return ret;
1757
1758         if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
1759             return ret;
1760
1761         ff_rtmp_packet_destroy(&rpkt);
1762     }
1763
1764     return size;
1765 }
1766
1767 #define OFFSET(x) offsetof(RTMPContext, x)
1768 #define DEC AV_OPT_FLAG_DECODING_PARAM
1769 #define ENC AV_OPT_FLAG_ENCODING_PARAM
1770
1771 static const AVOption rtmp_options[] = {
1772     {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
1773     {"rtmp_buffer", "Set buffer time in milliseconds. The default is 3000.", OFFSET(client_buffer_time), AV_OPT_TYPE_INT, {3000}, 0, INT_MAX, DEC|ENC},
1774     {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
1775     {"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},
1776     {"rtmp_flush_interval", "Number of packets flushed in the same request (RTMPT only).", OFFSET(flush_interval), AV_OPT_TYPE_INT, {10}, 0, INT_MAX, ENC},
1777     {"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {-2}, INT_MIN, INT_MAX, DEC, "rtmp_live"},
1778     {"any", "both", 0, AV_OPT_TYPE_CONST, {-2}, 0, 0, DEC, "rtmp_live"},
1779     {"live", "live stream", 0, AV_OPT_TYPE_CONST, {-1}, 0, 0, DEC, "rtmp_live"},
1780     {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {0}, 0, 0, DEC, "rtmp_live"},
1781     {"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},
1782     {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
1783     {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
1784     {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
1785     {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {0}, 0, INT_MAX, DEC},
1786     {"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},
1787     {"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},
1788     { NULL },
1789 };
1790
1791 #define RTMP_PROTOCOL(flavor)                    \
1792 static const AVClass flavor##_class = {          \
1793     .class_name = #flavor,                       \
1794     .item_name  = av_default_item_name,          \
1795     .option     = rtmp_options,                  \
1796     .version    = LIBAVUTIL_VERSION_INT,         \
1797 };                                               \
1798                                                  \
1799 URLProtocol ff_##flavor##_protocol = {           \
1800     .name           = #flavor,                   \
1801     .url_open       = rtmp_open,                 \
1802     .url_read       = rtmp_read,                 \
1803     .url_write      = rtmp_write,                \
1804     .url_close      = rtmp_close,                \
1805     .priv_data_size = sizeof(RTMPContext),       \
1806     .flags          = URL_PROTOCOL_FLAG_NETWORK, \
1807     .priv_data_class= &flavor##_class,           \
1808 };
1809
1810
1811 RTMP_PROTOCOL(rtmp)
1812 RTMP_PROTOCOL(rtmpe)
1813 RTMP_PROTOCOL(rtmps)
1814 RTMP_PROTOCOL(rtmpt)
1815 RTMP_PROTOCOL(rtmpte)
1816 RTMP_PROTOCOL(rtmpts)