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