LCOV - code coverage report
Current view: top level - netwerk/protocol/http - nsHttpChunkedDecoder.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 63 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 2 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : // HttpLog.h should generally be included first
       7             : #include "HttpLog.h"
       8             : 
       9             : #include <errno.h>
      10             : #include "nsHttpChunkedDecoder.h"
      11             : #include <algorithm>
      12             : #include "plstr.h"
      13             : 
      14             : #include "mozilla/Unused.h"
      15             : 
      16             : namespace mozilla {
      17             : namespace net {
      18             : 
      19             : //-----------------------------------------------------------------------------
      20             : // nsHttpChunkedDecoder <public>
      21             : //-----------------------------------------------------------------------------
      22             : 
      23             : nsresult
      24           0 : nsHttpChunkedDecoder::HandleChunkedContent(char *buf,
      25             :                                            uint32_t count,
      26             :                                            uint32_t *contentRead,
      27             :                                            uint32_t *contentRemaining)
      28             : {
      29           0 :     LOG(("nsHttpChunkedDecoder::HandleChunkedContent [count=%u]\n", count));
      30             : 
      31           0 :     *contentRead = 0;
      32             : 
      33             :     // from RFC2616 section 3.6.1, the chunked transfer coding is defined as:
      34             :     //
      35             :     //   Chunked-Body    = *chunk
      36             :     //                     last-chunk
      37             :     //                     trailer
      38             :     //                     CRLF
      39             :     //   chunk           = chunk-size [ chunk-extension ] CRLF
      40             :     //                     chunk-data CRLF
      41             :     //   chunk-size      = 1*HEX
      42             :     //   last-chunk      = 1*("0") [ chunk-extension ] CRLF
      43             :     //
      44             :     //   chunk-extension = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
      45             :     //   chunk-ext-name  = token
      46             :     //   chunk-ext-val   = token | quoted-string
      47             :     //   chunk-data      = chunk-size(OCTET)
      48             :     //   trailer         = *(entity-header CRLF)
      49             :     //
      50             :     // the chunk-size field is a string of hex digits indicating the size of the
      51             :     // chunk.  the chunked encoding is ended by any chunk whose size is zero,
      52             :     // followed by the trailer, which is terminated by an empty line.
      53             : 
      54           0 :     while (count) {
      55           0 :         if (mChunkRemaining) {
      56           0 :             uint32_t amt = std::min(mChunkRemaining, count);
      57             : 
      58           0 :             count -= amt;
      59           0 :             mChunkRemaining -= amt;
      60             : 
      61           0 :             *contentRead += amt;
      62           0 :             buf += amt;
      63             :         }
      64           0 :         else if (mReachedEOF)
      65           0 :             break; // done
      66             :         else {
      67           0 :             uint32_t bytesConsumed = 0;
      68             : 
      69           0 :             nsresult rv = ParseChunkRemaining(buf, count, &bytesConsumed);
      70           0 :             if (NS_FAILED(rv)) return rv;
      71             : 
      72           0 :             count -= bytesConsumed;
      73             : 
      74           0 :             if (count) {
      75             :                 // shift buf by bytesConsumed
      76           0 :                 memmove(buf, buf + bytesConsumed, count);
      77             :             }
      78             :         }
      79             :     }
      80             : 
      81           0 :     *contentRemaining = count;
      82           0 :     return NS_OK;
      83             : }
      84             : 
      85             : //-----------------------------------------------------------------------------
      86             : // nsHttpChunkedDecoder <private>
      87             : //-----------------------------------------------------------------------------
      88             : 
      89             : nsresult
      90           0 : nsHttpChunkedDecoder::ParseChunkRemaining(char *buf,
      91             :                                           uint32_t count,
      92             :                                           uint32_t *bytesConsumed)
      93             : {
      94           0 :     NS_PRECONDITION(mChunkRemaining == 0, "chunk remaining should be zero");
      95           0 :     NS_PRECONDITION(count, "unexpected");
      96             : 
      97           0 :     *bytesConsumed = 0;
      98             : 
      99           0 :     char *p = static_cast<char *>(memchr(buf, '\n', count));
     100           0 :     if (p) {
     101           0 :         *p = 0;
     102           0 :         count = p - buf; // new length
     103           0 :         *bytesConsumed = count + 1; // length + newline
     104           0 :         if ((p > buf) && (*(p-1) == '\r')) { // eliminate a preceding CR
     105           0 :             *(p-1) = 0;
     106           0 :             count--;
     107             :         }
     108             : 
     109             :         // make buf point to the full line buffer to parse
     110           0 :         if (!mLineBuf.IsEmpty()) {
     111           0 :             mLineBuf.Append(buf, count);
     112           0 :             buf = (char *) mLineBuf.get();
     113           0 :             count = mLineBuf.Length();
     114             :         }
     115             : 
     116           0 :         if (mWaitEOF) {
     117           0 :             if (*buf) {
     118           0 :                 LOG(("got trailer: %s\n", buf));
     119             :                 // allocate a header array for the trailers on demand
     120           0 :                 if (!mTrailers) {
     121           0 :                     mTrailers = new nsHttpHeaderArray();
     122             :                 }
     123           0 :                 Unused << mTrailers->ParseHeaderLine(nsDependentCSubstring(buf, count));
     124             :             }
     125             :             else {
     126           0 :                 mWaitEOF = false;
     127           0 :                 mReachedEOF = true;
     128           0 :                 LOG(("reached end of chunked-body\n"));
     129             :             }
     130             :         }
     131           0 :         else if (*buf) {
     132             :             char *endptr;
     133             :             unsigned long parsedval; // could be 64 bit, could be 32
     134             : 
     135             :             // ignore any chunk-extensions
     136           0 :             if ((p = PL_strchr(buf, ';')) != nullptr)
     137           0 :                 *p = 0;
     138             : 
     139             :             // mChunkRemaining is an uint32_t!
     140           0 :             parsedval = strtoul(buf, &endptr, 16);
     141           0 :             mChunkRemaining = (uint32_t) parsedval;
     142             : 
     143           0 :             if ((endptr == buf) ||
     144           0 :                 ((errno == ERANGE) && (parsedval == ULONG_MAX))  ||
     145           0 :                 (parsedval != mChunkRemaining) ) {
     146           0 :                 LOG(("failed parsing hex on string [%s]\n", buf));
     147           0 :                 return NS_ERROR_UNEXPECTED;
     148             :             }
     149             : 
     150             :             // we've discovered the last chunk
     151           0 :             if (mChunkRemaining == 0)
     152           0 :                 mWaitEOF = true;
     153             :         }
     154             : 
     155             :         // ensure that the line buffer is clear
     156           0 :         mLineBuf.Truncate();
     157             :     }
     158             :     else {
     159             :         // save the partial line; wait for more data
     160           0 :         *bytesConsumed = count;
     161             :         // ignore a trailing CR
     162           0 :         if (buf[count-1] == '\r')
     163           0 :             count--;
     164           0 :         mLineBuf.Append(buf, count);
     165             :     }
     166             : 
     167           0 :     return NS_OK;
     168             : }
     169             : 
     170             : } // namespace net
     171             : } // namespace mozilla

Generated by: LCOV version 1.13