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