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