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