Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Private Member Functions | Private Attributes
nsHttpChunkedDecoder Class Reference

#include <nsHttpChunkedDecoder.h>

Collaboration diagram for nsHttpChunkedDecoder:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 nsHttpChunkedDecoder ()
 ~nsHttpChunkedDecoder ()
PRBool ReachedEOF ()
nsresult HandleChunkedContent (char *buf, PRUint32 count, PRUint32 *contentRead, PRUint32 *contentRemaining)
nsHttpHeaderArrayTrailers ()
nsHttpHeaderArrayTakeTrailers ()

Private Member Functions

nsresult ParseChunkRemaining (char *buf, PRUint32 count, PRUint32 *countRead)

Private Attributes

nsHttpHeaderArraymTrailers
PRUint32 mChunkRemaining
nsCString mLineBuf
PRPackedBool mReachedEOF
PRPackedBool mWaitEOF

Detailed Description

Definition at line 46 of file nsHttpChunkedDecoder.h.


Constructor & Destructor Documentation

Definition at line 53 of file nsHttpChunkedDecoder.h.

{ delete mTrailers; }

Member Function Documentation

nsresult nsHttpChunkedDecoder::HandleChunkedContent ( char *  buf,
PRUint32  count,
PRUint32 contentRead,
PRUint32 contentRemaining 
)

Definition at line 47 of file nsHttpChunkedDecoder.cpp.

{
    LOG(("nsHttpChunkedDecoder::HandleChunkedContent [count=%u]\n", count));

    *contentRead = 0;
    
    // from RFC2617 section 3.6.1, the chunked transfer coding is defined as:
    //
    //   Chunked-Body    = *chunk
    //                     last-chunk
    //                     trailer
    //                     CRLF
    //   chunk           = chunk-size [ chunk-extension ] CRLF
    //                     chunk-data CRLF
    //   chunk-size      = 1*HEX
    //   last-chunk      = 1*("0") [ chunk-extension ] CRLF
    //       
    //   chunk-extension = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
    //   chunk-ext-name  = token
    //   chunk-ext-val   = token | quoted-string
    //   chunk-data      = chunk-size(OCTET)
    //   trailer         = *(entity-header CRLF)
    //
    // the chunk-size field is a string of hex digits indicating the size of the
    // chunk.  the chunked encoding is ended by any chunk whose size is zero, 
    // followed by the trailer, which is terminated by an empty line.

    while (count) {
        if (mChunkRemaining) {
            PRUint32 amt = PR_MIN(mChunkRemaining, count);

            count -= amt;
            mChunkRemaining -= amt;

            *contentRead += amt;
            buf += amt;
        }
        else if (mReachedEOF)
            break; // done
        else {
            PRUint32 bytesConsumed = 0;

            nsresult rv = ParseChunkRemaining(buf, count, &bytesConsumed);
            if (NS_FAILED(rv)) return rv;

            count -= bytesConsumed;

            if (count) {
                // shift buf by bytesConsumed
                memmove(buf, buf + bytesConsumed, count);
            }
        }
    }
    
    *contentRemaining = count;
    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsHttpChunkedDecoder::ParseChunkRemaining ( char *  buf,
PRUint32  count,
PRUint32 countRead 
) [private]

Definition at line 113 of file nsHttpChunkedDecoder.cpp.

{
    NS_PRECONDITION(mChunkRemaining == 0, "chunk remaining should be zero");
    NS_PRECONDITION(count, "unexpected");

    *bytesConsumed = 0;
    
    char *p = NS_STATIC_CAST(char *, memchr(buf, '\n', count));
    if (p) {
        *p = 0;
        if ((p > buf) && (*(p-1) == '\r')) // eliminate a preceding CR
            *(p-1) = 0;
        *bytesConsumed = p - buf + 1;

        // make buf point to the full line buffer to parse
        if (!mLineBuf.IsEmpty()) {
            mLineBuf.Append(buf);
            buf = (char *) mLineBuf.get();
        }

        if (mWaitEOF) {
            if (*buf) {
                LOG(("got trailer: %s\n", buf));
                // allocate a header array for the trailers on demand
                if (!mTrailers) {
                    mTrailers = new nsHttpHeaderArray();
                    if (!mTrailers)
                        return NS_ERROR_OUT_OF_MEMORY;
                }
                mTrailers->ParseHeaderLine(buf);
            }
            else {
                mWaitEOF = PR_FALSE;
                mReachedEOF = PR_TRUE;
                LOG(("reached end of chunked-body\n"));
            }
        }
        else if (*buf) {
            // ignore any chunk-extensions
            if ((p = PL_strchr(buf, ';')) != nsnull)
                *p = 0;

            if (!sscanf(buf, "%x", &mChunkRemaining)) {
                LOG(("sscanf failed parsing hex on string [%s]\n", buf));
                return NS_ERROR_UNEXPECTED;
            }

            // we've discovered the last chunk
            if (mChunkRemaining == 0)
                mWaitEOF = PR_TRUE;
        }

        // ensure that the line buffer is clear
        mLineBuf.Truncate();
    }
    else {
        // save the partial line; wait for more data
        *bytesConsumed = count;
        // ignore a trailing CR
        if (buf[count-1] == '\r')
            count--;
        mLineBuf.Append(buf, count);
    }

    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 55 of file nsHttpChunkedDecoder.h.

{ return mReachedEOF; }

Here is the caller graph for this function:

Definition at line 65 of file nsHttpChunkedDecoder.h.

                                      { nsHttpHeaderArray *h = mTrailers;
                                        mTrailers = nsnull;
                                        return h; }

Definition at line 63 of file nsHttpChunkedDecoder.h.

{ return mTrailers; }

Member Data Documentation

Definition at line 76 of file nsHttpChunkedDecoder.h.

Definition at line 77 of file nsHttpChunkedDecoder.h.

Definition at line 78 of file nsHttpChunkedDecoder.h.

Definition at line 75 of file nsHttpChunkedDecoder.h.

Definition at line 79 of file nsHttpChunkedDecoder.h.


The documentation for this class was generated from the following files: