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;
80  RTMPPacket *prev_pkt[2];
81  int nb_prev_pkt[2];
84  int is_input;
85  char *playpath;
86  int live;
87  char *app;
88  char *conn;
90  int stream_id;
92  int flv_size;
93  int flv_off;
96  uint32_t client_report_size;
97  uint32_t bytes_read;
98  uint32_t last_bytes_read;
99  int skip_bytes;
100  int has_audio;
101  int has_video;
103  uint8_t flv_header[RTMP_HEADER];
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[128];
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  if (ret) {
1888  if (ret == AVERROR(EINVAL))
1889  av_log(s, AV_LOG_ERROR, "Unable to parse stream name - name too long?\n");
1890  else
1891  av_log(s, AV_LOG_ERROR, "Unable to parse stream name\n");
1892  return ret;
1893  }
1894  // check with url
1895  if (s->filename) {
1896  pchar = strrchr(s->filename, '/');
1897  if (!pchar) {
1899  "Unable to find / in url %s, bad format\n",
1900  s->filename);
1901  pchar = s->filename;
1902  }
1903  pchar++;
1904  if (strcmp(pchar, filename))
1905  av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1906  " %s\n", filename, pchar);
1907  }
1908  rt->state = STATE_RECEIVING;
1909  }
1910 
1911  if (!strcmp(command, "FCPublish")) {
1912  if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1913  RTMP_PT_INVOKE, 0,
1914  RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1915  av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1916  return ret;
1917  }
1918  pp = spkt.data;
1919  ff_amf_write_string(&pp, "onFCPublish");
1920  } else if (!strcmp(command, "publish")) {
1921  ret = write_begin(s);
1922  if (ret < 0)
1923  return ret;
1924 
1925  // Send onStatus(NetStream.Publish.Start)
1926  return write_status(s, pkt, "NetStream.Publish.Start",
1927  filename);
1928  } else if (!strcmp(command, "play")) {
1929  ret = write_begin(s);
1930  if (ret < 0)
1931  return ret;
1932  rt->state = STATE_SENDING;
1933  return write_status(s, pkt, "NetStream.Play.Start",
1934  filename);
1935  } else {
1936  if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1937  RTMP_PT_INVOKE, 0,
1938  RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1939  av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1940  return ret;
1941  }
1942  pp = spkt.data;
1943  ff_amf_write_string(&pp, "_result");
1944  ff_amf_write_number(&pp, seqnum);
1945  ff_amf_write_null(&pp);
1946  if (!strcmp(command, "createStream")) {
1947  rt->nb_streamid++;
1948  if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1949  rt->nb_streamid++; /* Values 0 and 2 are reserved */
1950  ff_amf_write_number(&pp, rt->nb_streamid);
1951  /* By now we don't control which streams are removed in
1952  * deleteStream. There is no stream creation control
1953  * if a client creates more than 2^32 - 2 streams. */
1954  }
1955  }
1956  spkt.size = pp - spkt.data;
1957  ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1958  &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1959  ff_rtmp_packet_destroy(&spkt);
1960  return ret;
1961 }
1962 
1964 {
1965  RTMPContext *rt = s->priv_data;
1966  char *tracked_method = NULL;
1967  int ret = 0;
1968 
1969  if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1970  return ret;
1971 
1972  if (!tracked_method) {
1973  /* Ignore this reply when the current method is not tracked. */
1974  return ret;
1975  }
1976 
1977  if (!strcmp(tracked_method, "connect")) {
1978  if (!rt->is_input) {
1979  if ((ret = gen_release_stream(s, rt)) < 0)
1980  goto fail;
1981 
1982  if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1983  goto fail;
1984  } else {
1985  if ((ret = gen_server_bw(s, rt)) < 0)
1986  goto fail;
1987  }
1988 
1989  if ((ret = gen_create_stream(s, rt)) < 0)
1990  goto fail;
1991 
1992  if (rt->is_input) {
1993  /* Send the FCSubscribe command when the name of live
1994  * stream is defined by the user or if it's a live stream. */
1995  if (rt->subscribe) {
1996  if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1997  goto fail;
1998  } else if (rt->live == -1) {
1999  if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
2000  goto fail;
2001  }
2002  }
2003  } else if (!strcmp(tracked_method, "createStream")) {
2004  //extract a number from the result
2005  if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
2006  av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
2007  } else {
2008  rt->stream_id = av_int2double(AV_RB64(pkt->data + 21));
2009  }
2010 
2011  if (!rt->is_input) {
2012  if ((ret = gen_publish(s, rt)) < 0)
2013  goto fail;
2014  } else {
2015  if ((ret = gen_play(s, rt)) < 0)
2016  goto fail;
2017  if ((ret = gen_buffer_time(s, rt)) < 0)
2018  goto fail;
2019  }
2020  }
2021 
2022 fail:
2023  av_free(tracked_method);
2024  return ret;
2025 }
2026 
2028 {
2029  RTMPContext *rt = s->priv_data;
2030  const uint8_t *data_end = pkt->data + pkt->size;
2031  const uint8_t *ptr = pkt->data + RTMP_HEADER;
2032  uint8_t tmpstr[256];
2033  int i, t;
2034 
2035  for (i = 0; i < 2; i++) {
2036  t = ff_amf_tag_size(ptr, data_end);
2037  if (t < 0)
2038  return 1;
2039  ptr += t;
2040  }
2041 
2042  t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
2043  if (!t && !strcmp(tmpstr, "error")) {
2044  t = ff_amf_get_field_value(ptr, data_end,
2045  "description", tmpstr, sizeof(tmpstr));
2046  if (t || !tmpstr[0])
2047  t = ff_amf_get_field_value(ptr, data_end, "code",
2048  tmpstr, sizeof(tmpstr));
2049  if (!t)
2050  av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
2051  return -1;
2052  }
2053 
2054  t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
2055  if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
2056  if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
2057  if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
2058  if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
2059  if (!t && !strcmp(tmpstr, "NetStream.Seek.Notify")) rt->state = STATE_PLAYING;
2060 
2061  return 0;
2062 }
2063 
2065 {
2066  RTMPContext *rt = s->priv_data;
2067  int ret = 0;
2068 
2069  //TODO: check for the messages sent for wrong state?
2070  if (ff_amf_match_string(pkt->data, pkt->size, "_error")) {
2071  if ((ret = handle_invoke_error(s, pkt)) < 0)
2072  return ret;
2073  } else if (ff_amf_match_string(pkt->data, pkt->size, "_result")) {
2074  if ((ret = handle_invoke_result(s, pkt)) < 0)
2075  return ret;
2076  } else if (ff_amf_match_string(pkt->data, pkt->size, "onStatus")) {
2077  if ((ret = handle_invoke_status(s, pkt)) < 0)
2078  return ret;
2079  } else if (ff_amf_match_string(pkt->data, pkt->size, "onBWDone")) {
2080  if ((ret = gen_check_bw(s, rt)) < 0)
2081  return ret;
2082  } else if (ff_amf_match_string(pkt->data, pkt->size, "releaseStream") ||
2083  ff_amf_match_string(pkt->data, pkt->size, "FCPublish") ||
2084  ff_amf_match_string(pkt->data, pkt->size, "publish") ||
2085  ff_amf_match_string(pkt->data, pkt->size, "play") ||
2086  ff_amf_match_string(pkt->data, pkt->size, "_checkbw") ||
2087  ff_amf_match_string(pkt->data, pkt->size, "createStream")) {
2088  if ((ret = send_invoke_response(s, pkt)) < 0)
2089  return ret;
2090  }
2091 
2092  return ret;
2093 }
2094 
2095 static int update_offset(RTMPContext *rt, int size)
2096 {
2097  int old_flv_size;
2098 
2099  // generate packet header and put data into buffer for FLV demuxer
2100  if (rt->flv_off < rt->flv_size) {
2101  // There is old unread data in the buffer, thus append at the end
2102  old_flv_size = rt->flv_size;
2103  rt->flv_size += size;
2104  } else {
2105  // All data has been read, write the new data at the start of the buffer
2106  old_flv_size = 0;
2107  rt->flv_size = size;
2108  rt->flv_off = 0;
2109  }
2110 
2111  return old_flv_size;
2112 }
2113 
2114 static int append_flv_data(RTMPContext *rt, RTMPPacket *pkt, int skip)
2115 {
2116  int old_flv_size, ret;
2117  PutByteContext pbc;
2118  const uint8_t *data = pkt->data + skip;
2119  const int size = pkt->size - skip;
2120  uint32_t ts = pkt->timestamp;
2121 
2122  if (pkt->type == RTMP_PT_AUDIO) {
2123  rt->has_audio = 1;
2124  } else if (pkt->type == RTMP_PT_VIDEO) {
2125  rt->has_video = 1;
2126  }
2127 
2128  old_flv_size = update_offset(rt, size + 15);
2129 
2130  if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) {
2131  rt->flv_size = rt->flv_off = 0;
2132  return ret;
2133  }
2134  bytestream2_init_writer(&pbc, rt->flv_data, rt->flv_size);
2135  bytestream2_skip_p(&pbc, old_flv_size);
2136  bytestream2_put_byte(&pbc, pkt->type);
2137  bytestream2_put_be24(&pbc, size);
2138  bytestream2_put_be24(&pbc, ts);
2139  bytestream2_put_byte(&pbc, ts >> 24);
2140  bytestream2_put_be24(&pbc, 0);
2141  bytestream2_put_buffer(&pbc, data, size);
2142  bytestream2_put_be32(&pbc, 0);
2143 
2144  return 0;
2145 }
2146 
2148 {
2149  RTMPContext *rt = s->priv_data;
2150  uint8_t commandbuffer[64];
2151  char statusmsg[128];
2152  int stringlen, ret, skip = 0;
2153  GetByteContext gbc;
2154 
2155  bytestream2_init(&gbc, pkt->data, pkt->size);
2156  if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2157  &stringlen))
2158  return AVERROR_INVALIDDATA;
2159 
2160  if (!strcmp(commandbuffer, "onMetaData")) {
2161  // metadata properties should be stored in a mixed array
2162  if (bytestream2_get_byte(&gbc) == AMF_DATA_TYPE_MIXEDARRAY) {
2163  // We have found a metaData Array so flv can determine the streams
2164  // from this.
2165  rt->received_metadata = 1;
2166  // skip 32-bit max array index
2167  bytestream2_skip(&gbc, 4);
2168  while (bytestream2_get_bytes_left(&gbc) > 3) {
2169  if (ff_amf_get_string(&gbc, statusmsg, sizeof(statusmsg),
2170  &stringlen))
2171  return AVERROR_INVALIDDATA;
2172  // We do not care about the content of the property (yet).
2173  stringlen = ff_amf_tag_size(gbc.buffer, gbc.buffer_end);
2174  if (stringlen < 0)
2175  return AVERROR_INVALIDDATA;
2176  bytestream2_skip(&gbc, stringlen);
2177 
2178  // The presence of the following properties indicates that the
2179  // respective streams are present.
2180  if (!strcmp(statusmsg, "videocodecid")) {
2181  rt->has_video = 1;
2182  }
2183  if (!strcmp(statusmsg, "audiocodecid")) {
2184  rt->has_audio = 1;
2185  }
2186  }
2187  if (bytestream2_get_be24(&gbc) != AMF_END_OF_OBJECT)
2188  return AVERROR_INVALIDDATA;
2189  }
2190  }
2191 
2192  // Skip the @setDataFrame string and validate it is a notification
2193  if (!strcmp(commandbuffer, "@setDataFrame")) {
2194  skip = gbc.buffer - pkt->data;
2195  ret = ff_amf_read_string(&gbc, statusmsg,
2196  sizeof(statusmsg), &stringlen);
2197  if (ret < 0)
2198  return AVERROR_INVALIDDATA;
2199  }
2200 
2201  return append_flv_data(rt, pkt, skip);
2202 }
2203 
2211 {
2212  int ret;
2213 
2214 #ifdef DEBUG
2215  ff_rtmp_packet_dump(s, pkt);
2216 #endif
2217 
2218  switch (pkt->type) {
2219  case RTMP_PT_BYTES_READ:
2220  av_dlog(s, "received bytes read report\n");
2221  break;
2222  case RTMP_PT_CHUNK_SIZE:
2223  if ((ret = handle_chunk_size(s, pkt)) < 0)
2224  return ret;
2225  break;
2226  case RTMP_PT_PING:
2227  if ((ret = handle_ping(s, pkt)) < 0)
2228  return ret;
2229  break;
2230  case RTMP_PT_CLIENT_BW:
2231  if ((ret = handle_client_bw(s, pkt)) < 0)
2232  return ret;
2233  break;
2234  case RTMP_PT_SERVER_BW:
2235  if ((ret = handle_server_bw(s, pkt)) < 0)
2236  return ret;
2237  break;
2238  case RTMP_PT_INVOKE:
2239  if ((ret = handle_invoke(s, pkt)) < 0)
2240  return ret;
2241  break;
2242  case RTMP_PT_VIDEO:
2243  case RTMP_PT_AUDIO:
2244  case RTMP_PT_METADATA:
2245  case RTMP_PT_NOTIFY:
2246  /* Audio, Video and Metadata packets are parsed in get_packet() */
2247  break;
2248  default:
2249  av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2250  break;
2251  }
2252  return 0;
2253 }
2254 
2256 {
2257  int ret, old_flv_size, type;
2258  const uint8_t *next;
2259  uint8_t *p;
2260  uint32_t size;
2261  uint32_t ts, cts, pts = 0;
2262 
2263  old_flv_size = update_offset(rt, pkt->size);
2264 
2265  if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) {
2266  rt->flv_size = rt->flv_off = 0;
2267  return ret;
2268  }
2269 
2270  next = pkt->data;
2271  p = rt->flv_data + old_flv_size;
2272 
2273  /* copy data while rewriting timestamps */
2274  ts = pkt->timestamp;
2275 
2276  while (next - pkt->data < pkt->size - RTMP_HEADER) {
2277  type = bytestream_get_byte(&next);
2278  size = bytestream_get_be24(&next);
2279  cts = bytestream_get_be24(&next);
2280  cts |= bytestream_get_byte(&next) << 24;
2281  if (!pts)
2282  pts = cts;
2283  ts += cts - pts;
2284  pts = cts;
2285  if (size + 3 + 4 > pkt->data + pkt->size - next)
2286  break;
2287  bytestream_put_byte(&p, type);
2288  bytestream_put_be24(&p, size);
2289  bytestream_put_be24(&p, ts);
2290  bytestream_put_byte(&p, ts >> 24);
2291  memcpy(p, next, size + 3 + 4);
2292  next += size + 3 + 4;
2293  p += size + 3 + 4;
2294  }
2295  if (p != rt->flv_data + rt->flv_size) {
2296  av_log(NULL, AV_LOG_WARNING, "Incomplete flv packets in "
2297  "RTMP_PT_METADATA packet\n");
2298  rt->flv_size = p - rt->flv_data;
2299  }
2300 
2301  return 0;
2302 }
2303 
2315 static int get_packet(URLContext *s, int for_header)
2316 {
2317  RTMPContext *rt = s->priv_data;
2318  int ret;
2319 
2320  if (rt->state == STATE_STOPPED)
2321  return AVERROR_EOF;
2322 
2323  for (;;) {
2324  RTMPPacket rpkt = { 0 };
2325  if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2326  rt->in_chunk_size, &rt->prev_pkt[0],
2327  &rt->nb_prev_pkt[0])) <= 0) {
2328  if (ret == 0) {
2329  return AVERROR(EAGAIN);
2330  } else {
2331  return AVERROR(EIO);
2332  }
2333  }
2334  rt->bytes_read += ret;
2335  if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
2336  av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2337  if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2338  return ret;
2339  rt->last_bytes_read = rt->bytes_read;
2340  }
2341 
2342  ret = rtmp_parse_result(s, rt, &rpkt);
2343 
2344  // At this point we must check if we are in the seek state and continue
2345  // with the next packet. handle_invoke will get us out of this state
2346  // when the right message is encountered
2347  if (rt->state == STATE_SEEKING) {
2348  ff_rtmp_packet_destroy(&rpkt);
2349  // We continue, let the natural flow of things happen:
2350  // AVERROR(EAGAIN) or handle_invoke gets us out of here
2351  continue;
2352  }
2353 
2354  if (ret < 0) {//serious error in current packet
2355  ff_rtmp_packet_destroy(&rpkt);
2356  return ret;
2357  }
2358  if (rt->do_reconnect && for_header) {
2359  ff_rtmp_packet_destroy(&rpkt);
2360  return 0;
2361  }
2362  if (rt->state == STATE_STOPPED) {
2363  ff_rtmp_packet_destroy(&rpkt);
2364  return AVERROR_EOF;
2365  }
2366  if (for_header && (rt->state == STATE_PLAYING ||
2367  rt->state == STATE_PUBLISHING ||
2368  rt->state == STATE_SENDING ||
2369  rt->state == STATE_RECEIVING)) {
2370  ff_rtmp_packet_destroy(&rpkt);
2371  return 0;
2372  }
2373  if (!rpkt.size || !rt->is_input) {
2374  ff_rtmp_packet_destroy(&rpkt);
2375  continue;
2376  }
2377  if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO) {
2378  ret = append_flv_data(rt, &rpkt, 0);
2379  ff_rtmp_packet_destroy(&rpkt);
2380  return ret;
2381  } else if (rpkt.type == RTMP_PT_NOTIFY) {
2382  ret = handle_notify(s, &rpkt);
2383  ff_rtmp_packet_destroy(&rpkt);
2384  return ret;
2385  } else if (rpkt.type == RTMP_PT_METADATA) {
2386  ret = handle_metadata(rt, &rpkt);
2387  ff_rtmp_packet_destroy(&rpkt);
2388  return 0;
2389  }
2390  ff_rtmp_packet_destroy(&rpkt);
2391  }
2392 }
2393 
2394 static int rtmp_close(URLContext *h)
2395 {
2396  RTMPContext *rt = h->priv_data;
2397  int ret = 0, i, j;
2398 
2399  if (!rt->is_input) {
2400  rt->flv_data = NULL;
2401  if (rt->out_pkt.size)
2403  if (rt->state > STATE_FCPUBLISH)
2404  ret = gen_fcunpublish_stream(h, rt);
2405  }
2406  if (rt->state > STATE_HANDSHAKED)
2407  ret = gen_delete_stream(h, rt);
2408  for (i = 0; i < 2; i++) {
2409  for (j = 0; j < rt->nb_prev_pkt[i]; j++)
2410  ff_rtmp_packet_destroy(&rt->prev_pkt[i][j]);
2411  av_freep(&rt->prev_pkt[i]);
2412  }
2413 
2415  av_freep(&rt->flv_data);
2416  ffurl_close(rt->stream);
2417  return ret;
2418 }
2419 
2429 static int rtmp_open(URLContext *s, const char *uri, int flags)
2430 {
2431  RTMPContext *rt = s->priv_data;
2432  char proto[8], hostname[256], path[1024], auth[100], *fname;
2433  char *old_app, *qmark, fname_buffer[1024];
2434  uint8_t buf[2048];
2435  int port;
2436  AVDictionary *opts = NULL;
2437  int ret;
2438 
2439  if (rt->listen_timeout > 0)
2440  rt->listen = 1;
2441 
2442  rt->is_input = !(flags & AVIO_FLAG_WRITE);
2443 
2444  av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2445  hostname, sizeof(hostname), &port,
2446  path, sizeof(path), s->filename);
2447 
2448  if (strchr(path, ' ')) {
2450  "Detected librtmp style URL parameters, these aren't supported "
2451  "by the libavformat internal RTMP handler currently enabled. "
2452  "See the documentation for the correct way to pass parameters.\n");
2453  }
2454 
2455  if (auth[0]) {
2456  char *ptr = strchr(auth, ':');
2457  if (ptr) {
2458  *ptr = '\0';
2459  av_strlcpy(rt->username, auth, sizeof(rt->username));
2460  av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2461  }
2462  }
2463 
2464  if (rt->listen && strcmp(proto, "rtmp")) {
2465  av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2466  proto);
2467  return AVERROR(EINVAL);
2468  }
2469  if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2470  if (!strcmp(proto, "rtmpts"))
2471  av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2472 
2473  /* open the http tunneling connection */
2474  ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2475  } else if (!strcmp(proto, "rtmps")) {
2476  /* open the tls connection */
2477  if (port < 0)
2478  port = RTMPS_DEFAULT_PORT;
2479  ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2480  } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2481  if (!strcmp(proto, "rtmpte"))
2482  av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2483 
2484  /* open the encrypted connection */
2485  ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2486  rt->encrypted = 1;
2487  } else {
2488  /* open the tcp connection */
2489  if (port < 0)
2490  port = RTMP_DEFAULT_PORT;
2491  if (rt->listen)
2492  ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2493  "?listen&listen_timeout=%d",
2494  rt->listen_timeout * 1000);
2495  else
2496  ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2497  }
2498 
2499 reconnect:
2500  if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2501  &s->interrupt_callback, &opts)) < 0) {
2502  av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2503  goto fail;
2504  }
2505 
2506  if (rt->swfverify) {
2507  if ((ret = rtmp_calc_swfhash(s)) < 0)
2508  goto fail;
2509  }
2510 
2511  rt->state = STATE_START;
2512  if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2513  goto fail;
2514  if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2515  goto fail;
2516 
2517  rt->out_chunk_size = 128;
2518  rt->in_chunk_size = 128; // Probably overwritten later
2519  rt->state = STATE_HANDSHAKED;
2520 
2521  // Keep the application name when it has been defined by the user.
2522  old_app = rt->app;
2523 
2524  rt->app = av_malloc(APP_MAX_LENGTH);
2525  if (!rt->app) {
2526  ret = AVERROR(ENOMEM);
2527  goto fail;
2528  }
2529 
2530  //extract "app" part from path
2531  qmark = strchr(path, '?');
2532  if (qmark && strstr(qmark, "slist=")) {
2533  char* amp;
2534  // After slist we have the playpath, before the params, the app
2535  av_strlcpy(rt->app, path + 1, FFMIN(qmark - path, APP_MAX_LENGTH));
2536  fname = strstr(path, "slist=") + 6;
2537  // Strip any further query parameters from fname
2538  amp = strchr(fname, '&');
2539  if (amp) {
2540  av_strlcpy(fname_buffer, fname, FFMIN(amp - fname + 1,
2541  sizeof(fname_buffer)));
2542  fname = fname_buffer;
2543  }
2544  } else if (!strncmp(path, "/ondemand/", 10)) {
2545  fname = path + 10;
2546  memcpy(rt->app, "ondemand", 9);
2547  } else {
2548  char *next = *path ? path + 1 : path;
2549  char *p = strchr(next, '/');
2550  if (!p) {
2551  fname = next;
2552  rt->app[0] = '\0';
2553  } else {
2554  // make sure we do not mismatch a playpath for an application instance
2555  char *c = strchr(p + 1, ':');
2556  fname = strchr(p + 1, '/');
2557  if (!fname || (c && c < fname)) {
2558  fname = p + 1;
2559  av_strlcpy(rt->app, path + 1, FFMIN(p - path, APP_MAX_LENGTH));
2560  } else {
2561  fname++;
2562  av_strlcpy(rt->app, path + 1, FFMIN(fname - path - 1, APP_MAX_LENGTH));
2563  }
2564  }
2565  }
2566 
2567  if (old_app) {
2568  // The name of application has been defined by the user, override it.
2569  av_free(rt->app);
2570  rt->app = old_app;
2571  }
2572 
2573  if (!rt->playpath) {
2574  int len = strlen(fname);
2575 
2577  if (!rt->playpath) {
2578  ret = AVERROR(ENOMEM);
2579  goto fail;
2580  }
2581 
2582  if (!strchr(fname, ':') && len >= 4 &&
2583  (!strcmp(fname + len - 4, ".f4v") ||
2584  !strcmp(fname + len - 4, ".mp4"))) {
2585  memcpy(rt->playpath, "mp4:", 5);
2586  } else {
2587  if (len >= 4 && !strcmp(fname + len - 4, ".flv"))
2588  fname[len - 4] = '\0';
2589  rt->playpath[0] = 0;
2590  }
2592  }
2593 
2594  if (!rt->tcurl) {
2596  if (!rt->tcurl) {
2597  ret = AVERROR(ENOMEM);
2598  goto fail;
2599  }
2600  ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2601  port, "/%s", rt->app);
2602  }
2603 
2604  if (!rt->flashver) {
2606  if (!rt->flashver) {
2607  ret = AVERROR(ENOMEM);
2608  goto fail;
2609  }
2610  if (rt->is_input) {
2611  snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2614  } else {
2615  snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2616  "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2617  }
2618  }
2619 
2620  rt->client_report_size = 1048576;
2621  rt->bytes_read = 0;
2622  rt->has_audio = 0;
2623  rt->has_video = 0;
2624  rt->received_metadata = 0;
2625  rt->last_bytes_read = 0;
2626  rt->server_bw = 2500000;
2627 
2628  av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2629  proto, path, rt->app, rt->playpath);
2630  if (!rt->listen) {
2631  if ((ret = gen_connect(s, rt)) < 0)
2632  goto fail;
2633  } else {
2634  if ((ret = read_connect(s, s->priv_data)) < 0)
2635  goto fail;
2636  }
2637 
2638  do {
2639  ret = get_packet(s, 1);
2640  } while (ret == AVERROR(EAGAIN));
2641  if (ret < 0)
2642  goto fail;
2643 
2644  if (rt->do_reconnect) {
2645  int i;
2646  ffurl_close(rt->stream);
2647  rt->stream = NULL;
2648  rt->do_reconnect = 0;
2649  rt->nb_invokes = 0;
2650  for (i = 0; i < 2; i++)
2651  memset(rt->prev_pkt[i], 0,
2652  sizeof(**rt->prev_pkt) * rt->nb_prev_pkt[i]);
2654  goto reconnect;
2655  }
2656 
2657  if (rt->is_input) {
2658  int err;
2659  // generate FLV header for demuxer
2660  rt->flv_size = 13;
2661  if ((err = av_reallocp(&rt->flv_data, rt->flv_size)) < 0)
2662  return err;
2663  rt->flv_off = 0;
2664  memcpy(rt->flv_data, "FLV\1\0\0\0\0\011\0\0\0\0", rt->flv_size);
2665 
2666  // Read packets until we reach the first A/V packet or read metadata.
2667  // If there was a metadata package in front of the A/V packets, we can
2668  // build the FLV header from this. If we do not receive any metadata,
2669  // the FLV decoder will allocate the needed streams when their first
2670  // audio or video packet arrives.
2671  while (!rt->has_audio && !rt->has_video && !rt->received_metadata) {
2672  if ((ret = get_packet(s, 0)) < 0)
2673  return ret;
2674  }
2675 
2676  // Either after we have read the metadata or (if there is none) the
2677  // first packet of an A/V stream, we have a better knowledge about the
2678  // streams, so set the FLV header accordingly.
2679  if (rt->has_audio) {
2681  }
2682  if (rt->has_video) {
2684  }
2685  } else {
2686  rt->flv_size = 0;
2687  rt->flv_data = NULL;
2688  rt->flv_off = 0;
2689  rt->skip_bytes = 13;
2690  }
2691 
2693  s->is_streamed = 1;
2694  return 0;
2695 
2696 fail:
2697  av_dict_free(&opts);
2698  rtmp_close(s);
2699  return ret;
2700 }
2701 
2702 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2703 {
2704  RTMPContext *rt = s->priv_data;
2705  int orig_size = size;
2706  int ret;
2707 
2708  while (size > 0) {
2709  int data_left = rt->flv_size - rt->flv_off;
2710 
2711  if (data_left >= size) {
2712  memcpy(buf, rt->flv_data + rt->flv_off, size);
2713  rt->flv_off += size;
2714  return orig_size;
2715  }
2716  if (data_left > 0) {
2717  memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2718  buf += data_left;
2719  size -= data_left;
2720  rt->flv_off = rt->flv_size;
2721  return data_left;
2722  }
2723  if ((ret = get_packet(s, 0)) < 0)
2724  return ret;
2725  }
2726  return orig_size;
2727 }
2728 
2729 static int64_t rtmp_seek(URLContext *s, int stream_index, int64_t timestamp,
2730  int flags)
2731 {
2732  RTMPContext *rt = s->priv_data;
2733  int ret;
2734  av_log(s, AV_LOG_DEBUG,
2735  "Seek on stream index %d at timestamp %"PRId64" with flags %08x\n",
2736  stream_index, timestamp, flags);
2737  if ((ret = gen_seek(s, rt, timestamp)) < 0) {
2738  av_log(s, AV_LOG_ERROR,
2739  "Unable to send seek command on stream index %d at timestamp "
2740  "%"PRId64" with flags %08x\n",
2741  stream_index, timestamp, flags);
2742  return ret;
2743  }
2744  rt->flv_off = rt->flv_size;
2745  rt->state = STATE_SEEKING;
2746  return timestamp;
2747 }
2748 
2749 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2750 {
2751  RTMPContext *rt = s->priv_data;
2752  int size_temp = size;
2753  int pktsize, pkttype;
2754  uint32_t ts;
2755  const uint8_t *buf_temp = buf;
2756  uint8_t c;
2757  int ret;
2758 
2759  do {
2760  if (rt->skip_bytes) {
2761  int skip = FFMIN(rt->skip_bytes, size_temp);
2762  buf_temp += skip;
2763  size_temp -= skip;
2764  rt->skip_bytes -= skip;
2765  continue;
2766  }
2767 
2768  if (rt->flv_header_bytes < RTMP_HEADER) {
2769  const uint8_t *header = rt->flv_header;
2770  int copy = FFMIN(RTMP_HEADER - rt->flv_header_bytes, size_temp);
2771  int channel = RTMP_AUDIO_CHANNEL;
2772  bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2773  rt->flv_header_bytes += copy;
2774  size_temp -= copy;
2775  if (rt->flv_header_bytes < RTMP_HEADER)
2776  break;
2777 
2778  pkttype = bytestream_get_byte(&header);
2779  pktsize = bytestream_get_be24(&header);
2780  ts = bytestream_get_be24(&header);
2781  ts |= bytestream_get_byte(&header) << 24;
2782  bytestream_get_be24(&header);
2783  rt->flv_size = pktsize;
2784 
2785  if (pkttype == RTMP_PT_VIDEO)
2786  channel = RTMP_VIDEO_CHANNEL;
2787 
2788  //force 12bytes header
2789  if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2790  pkttype == RTMP_PT_NOTIFY) {
2791  if (pkttype == RTMP_PT_NOTIFY)
2792  pktsize += 16;
2793  if ((ret = ff_rtmp_check_alloc_array(&rt->prev_pkt[1],
2794  &rt->nb_prev_pkt[1],
2795  channel)) < 0)
2796  return ret;
2797  rt->prev_pkt[1][channel].channel_id = 0;
2798  }
2799 
2800  //this can be a big packet, it's better to send it right here
2801  if ((ret = ff_rtmp_packet_create(&rt->out_pkt, channel,
2802  pkttype, ts, pktsize)) < 0)
2803  return ret;
2804 
2805  rt->out_pkt.extra = rt->stream_id;
2806  rt->flv_data = rt->out_pkt.data;
2807 
2808  if (pkttype == RTMP_PT_NOTIFY)
2809  ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2810  }
2811 
2812  if (rt->flv_size - rt->flv_off > size_temp) {
2813  bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2814  rt->flv_off += size_temp;
2815  size_temp = 0;
2816  } else {
2817  bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2818  size_temp -= rt->flv_size - rt->flv_off;
2819  rt->flv_off += rt->flv_size - rt->flv_off;
2820  }
2821 
2822  if (rt->flv_off == rt->flv_size) {
2823  rt->skip_bytes = 4;
2824 
2825  if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2826  return ret;
2827  rt->flv_size = 0;
2828  rt->flv_off = 0;
2829  rt->flv_header_bytes = 0;
2830  rt->flv_nb_packets++;
2831  }
2832  } while (buf_temp - buf < size);
2833 
2834  if (rt->flv_nb_packets < rt->flush_interval)
2835  return size;
2836  rt->flv_nb_packets = 0;
2837 
2838  /* set stream into nonblocking mode */
2840 
2841  /* try to read one byte from the stream */
2842  ret = ffurl_read(rt->stream, &c, 1);
2843 
2844  /* switch the stream back into blocking mode */
2845  rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2846 
2847  if (ret == AVERROR(EAGAIN)) {
2848  /* no incoming data to handle */
2849  return size;
2850  } else if (ret < 0) {
2851  return ret;
2852  } else if (ret == 1) {
2853  RTMPPacket rpkt = { 0 };
2854 
2855  if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2856  rt->in_chunk_size,
2857  &rt->prev_pkt[0],
2858  &rt->nb_prev_pkt[0], c)) <= 0)
2859  return ret;
2860 
2861  if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2862  return ret;
2863 
2864  ff_rtmp_packet_destroy(&rpkt);
2865  }
2866 
2867  return size;
2868 }
2869 
2870 #define OFFSET(x) offsetof(RTMPContext, x)
2871 #define DEC AV_OPT_FLAG_DECODING_PARAM
2872 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2873 
2874 static const AVOption rtmp_options[] = {
2875  {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2876  {"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},
2877  {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2878  {"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},
2879  {"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},
2880  {"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"},
2881  {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
2882  {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
2883  {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
2884  {"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},
2885  {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2886  {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2887  {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2888  {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
2889  {"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},
2890  {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2891  {"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},
2892  {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2893  {"listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2894  {"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" },
2895  { NULL },
2896 };
2897 
2898 #define RTMP_PROTOCOL(flavor) \
2899 static const AVClass flavor##_class = { \
2900  .class_name = #flavor, \
2901  .item_name = av_default_item_name, \
2902  .option = rtmp_options, \
2903  .version = LIBAVUTIL_VERSION_INT, \
2904 }; \
2905  \
2906 URLProtocol ff_##flavor##_protocol = { \
2907  .name = #flavor, \
2908  .url_open = rtmp_open, \
2909  .url_read = rtmp_read, \
2910  .url_read_seek = rtmp_seek, \
2911  .url_write = rtmp_write, \
2912  .url_close = rtmp_close, \
2913  .priv_data_size = sizeof(RTMPContext), \
2914  .flags = URL_PROTOCOL_FLAG_NETWORK, \
2915  .priv_data_class= &flavor##_class, \
2916 };
2917 
2918 
2919 RTMP_PROTOCOL(rtmp)
2920 RTMP_PROTOCOL(rtmpe)
2921 RTMP_PROTOCOL(rtmps)
2922 RTMP_PROTOCOL(rtmpt)
2923 RTMP_PROTOCOL(rtmpte)
2924 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:2702
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:2749
static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
Definition: rtmpproto.c:1748
client bandwidth
Definition: rtmppkt.h:52
static int handle_invoke(URLContext *s, RTMPPacket *pkt)
Definition: rtmpproto.c:2064
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:141
#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 &#39;createStream&#39; 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:132
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
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:2871
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
av_dlog(ac->avr, "%d samples - audio_convert: %s to %s (%s)\, len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt), use_generic ? ac->func_descr_generic :ac->func_descr)
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:2114
#define CONFIG_FFRTMPCRYPT_PROTOCOL
Definition: config.h:1327
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 &#39;FCUnpublish&#39; call and send it to the server.
Definition: rtmpproto.c:611
#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:2027
ClientState
RTMP protocol handler state.
Definition: rtmpproto.c:59
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:161
char * swfurl
url of the swf player
Definition: rtmpproto.c: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 &#39;FCPublish&#39; 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:151
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:169
static int gen_delete_stream(URLContext *s, RTMPContext *rt)
Generate &#39;deleteStream&#39; 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:2898
#define OFFSET(x)
Definition: rtmpproto.c:2870
client has performed handshake
Definition: rtmpproto.c:61
static int gen_play(URLContext *s, RTMPContext *rt)
Generate &#39;play&#39; call and send it to the server, then ping the server to start actual playing...
Definition: rtmpproto.c: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:173
#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:2210
#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 &#39;publish&#39; 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:2394
int nb_streamid
The next stream id to return on createStream calls.
Definition: rtmpproto.c:125
#define ENC
Definition: rtmpproto.c:2872
#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:2729
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:356
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:279
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:212
#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 &#39;connect&#39; call and send it to the server.
Definition: rtmpproto.c:319
static int gen_release_stream(URLContext *s, RTMPContext *rt)
Generate &#39;releaseStream&#39; 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:228
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:2147
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:2255
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:2429
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:2874
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:2315
static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
Definition: rtmpproto.c:1963
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 nb_prev_pkt[2]
number of elements in prev_pkt
Definition: rtmpproto.c:81
int swfsize
size of the decompressed SWF file
Definition: rtmpproto.c:110
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:2095
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