Merge commit '324b23dde1bc8638959eb32419c95a93906db272'
authorMichael Niedermayer <michaelni@gmx.at>
Fri, 17 Oct 2014 13:21:26 +0000 (15:21 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Fri, 17 Oct 2014 13:21:40 +0000 (15:21 +0200)
* commit '324b23dde1bc8638959eb32419c95a93906db272':
  rtmpproto: Add function to read a number response

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavformat/rtmpproto.c

diff --combined libavformat/rtmpproto.c
index f3ac812315ca746e23539d11db70087eccd166a2,44a9a0d06e4b29d8252fe866a1bd4d2bfb997e4b..94a4c8e34e0928c4adb499f65dd74e25848d994a
@@@ -2,20 -2,20 +2,20 @@@
   * RTMP network protocol
   * Copyright (c) 2009 Konstantin Shishkov
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -48,7 -48,7 +48,7 @@@
  #include <zlib.h>
  #endif
  
 -#define APP_MAX_LENGTH 128
 +#define APP_MAX_LENGTH 1024
  #define PLAYPATH_MAX_LENGTH 256
  #define TCURL_MAX_LENGTH 512
  #define FLASHVER_MAX_LENGTH 64
@@@ -274,6 -274,9 +274,6 @@@ static int rtmp_write_amf_data(URLConte
          *value = '\0';
          value++;
  
 -        if (!field || !value)
 -            goto fail;
 -
          ff_amf_write_field_name(p, field);
      } else {
          goto fail;
@@@ -320,7 -323,7 +320,7 @@@ static int gen_connect(URLContext *s, R
      int ret;
  
      if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
 -                                     0, 4096)) < 0)
 +                                     0, 4096 + APP_MAX_LENGTH)) < 0)
          return ret;
  
      p = pkt.data;
@@@ -417,7 -420,6 +417,7 @@@ static int read_connect(URLContext *s, 
      if (pkt.type == RTMP_PT_CHUNK_SIZE) {
          if ((ret = handle_chunk_size(s, &pkt)) < 0)
              return ret;
 +
          ff_rtmp_packet_destroy(&pkt);
          if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
                                         &rt->prev_pkt[0], &rt->nb_prev_pkt[0])) < 0)
@@@ -1715,23 -1717,18 +1715,23 @@@ static int handle_connect_error(URLCont
          char *value = strchr(ptr, '=');
          if (next)
              *next++ = '\0';
 -        if (value)
 +        if (value) {
              *value++ = '\0';
 -        if (!strcmp(ptr, "user")) {
 -            user = value;
 -        } else if (!strcmp(ptr, "salt")) {
 -            salt = value;
 -        } else if (!strcmp(ptr, "opaque")) {
 -            opaque = value;
 -        } else if (!strcmp(ptr, "challenge")) {
 -            challenge = value;
 -        } else if (!strcmp(ptr, "nonce")) {
 -            nonce = value;
 +            if (!strcmp(ptr, "user")) {
 +                user = value;
 +            } else if (!strcmp(ptr, "salt")) {
 +                salt = value;
 +            } else if (!strcmp(ptr, "opaque")) {
 +                opaque = value;
 +            } else if (!strcmp(ptr, "challenge")) {
 +                challenge = value;
 +            } else if (!strcmp(ptr, "nonce")) {
 +                nonce = value;
 +            } else {
 +                av_log(s, AV_LOG_INFO, "Ignoring unsupported var %s\n", ptr);
 +            }
 +        } else {
 +            av_log(s, AV_LOG_WARNING, "Variable %s has NULL value\n", ptr);
          }
          ptr = next;
      }
@@@ -1956,6 -1953,45 +1956,45 @@@ static int send_invoke_response(URLCont
      return ret;
  }
  
+ /**
+  * Read the AMF_NUMBER response ("_result") to a function call
+  * (e.g. createStream()). This response should be made up of the AMF_STRING
+  * "result", a NULL object and then the response encoded as AMF_NUMBER. On a
+  * successful response, we will return set the value to number (otherwise number
+  * will not be changed).
+  *
+  * @return 0 if reading the value succeeds, negative value otherwiss
+  */
+ static int read_number_result(RTMPPacket *pkt, double *number)
+ {
+     // We only need to fit "_result" in this.
+     uint8_t strbuffer[8];
+     int stringlen;
+     double numbuffer;
+     GetByteContext gbc;
+     bytestream2_init(&gbc, pkt->data, pkt->size);
+     // Value 1/4: "_result" as AMF_STRING
+     if (ff_amf_read_string(&gbc, strbuffer, sizeof(strbuffer), &stringlen))
+         return AVERROR_INVALIDDATA;
+     if (strcmp(strbuffer, "_result"))
+         return AVERROR_INVALIDDATA;
+     // Value 2/4: The callee reference number
+     if (ff_amf_read_number(&gbc, &numbuffer))
+         return AVERROR_INVALIDDATA;
+     // Value 3/4: Null
+     if (ff_amf_read_null(&gbc))
+         return AVERROR_INVALIDDATA;
+     // Value 4/4: The resonse as AMF_NUMBER
+     if (ff_amf_read_number(&gbc, &numbuffer))
+         return AVERROR_INVALIDDATA;
+     else
+         *number = numbuffer;
+     return 0;
+ }
  static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
  {
      RTMPContext *rt = s->priv_data;
              }
          }
      } else if (!strcmp(tracked_method, "createStream")) {
-         //extract a number from the result
-         if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
+         double stream_id;
+         if (read_number_result(pkt, &stream_id)) {
              av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
          } else {
-             rt->stream_id = av_int2double(AV_RB64(pkt->data + 21));
+             rt->stream_id = stream_id;
          }
  
          if (!rt->is_input) {
@@@ -2328,7 -2364,7 +2367,7 @@@ static int get_packet(URLContext *s, in
              }
          }
          rt->bytes_read += ret;
 -        if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
 +        if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
              av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
              if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
                  return ret;
@@@ -2562,10 -2598,6 +2601,10 @@@ reconnect
  
      if (old_app) {
          // The name of application has been defined by the user, override it.
 +        if (strlen(old_app) >= APP_MAX_LENGTH) {
 +            ret = AVERROR(EINVAL);
 +            goto fail;
 +        }
          av_free(rt->app);
          rt->app = old_app;
      }
          // audio or video packet arrives.
          while (!rt->has_audio && !rt->has_video && !rt->received_metadata) {
              if ((ret = get_packet(s, 0)) < 0)
 -               return ret;
 +               goto fail;
          }
  
          // Either after we have read the metadata or (if there is none) the