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