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