You are viewing a plain text version of this content. The canonical link for it is here.
Posted to axis-cvs@ws.apache.org by na...@apache.org on 2007/02/18 21:19:26 UTC
svn commit: r508976 - in /webservices/axis/trunk/c/src/transport/axis3:
HTTPTransport.cpp HTTPTransport.hpp
Author: nadiramra
Date: Sun Feb 18 12:19:25 2007
New Revision: 508976
URL: http://svn.apache.org/viewvc?view=rev&rev=508976
Log:
AXISCPP-930 - chunked processing not correct.
Modified:
webservices/axis/trunk/c/src/transport/axis3/HTTPTransport.cpp
webservices/axis/trunk/c/src/transport/axis3/HTTPTransport.hpp
Modified: webservices/axis/trunk/c/src/transport/axis3/HTTPTransport.cpp
URL: http://svn.apache.org/viewvc/webservices/axis/trunk/c/src/transport/axis3/HTTPTransport.cpp?view=diff&rev=508976&r1=508975&r2=508976
==============================================================================
--- webservices/axis/trunk/c/src/transport/axis3/HTTPTransport.cpp (original)
+++ webservices/axis/trunk/c/src/transport/axis3/HTTPTransport.cpp Sun Feb 18 12:19:25 2007
@@ -34,7 +34,9 @@
#include "../../soap/apr_base64.h"
#include <stdio.h>
-
+
+static int axtoi( char *pcHexString);
+
// =================================================================
// In order to parse the HTTP protocol data on an ebcdic system, we
// need to ensure that the various tokens we are looking for to distinguish
@@ -65,11 +67,8 @@
#define ASCII_S_CRLFCRLF "\x0d\x0a\x0d\x0a" // "\r\n\r\n"
#define ASCII_S_HTTP "\x48\x54\x54\x50" // "HTTP"
-#define ASCII_S_CONTENT_LENGTH "\x43\x6F\x6E\x74\x65\x6E\x74\x2D\x4c\x65\x6e\x67\x74\x68\x3a\x20" // "Content-Length: "
-#define ASCII_S_TRANSFERENCODING_CHUNKED "\x54\x72\x61\x6E\x73\x66\x65\x72\x2D\x45\x6E\x63\x6F\x64\x69\x6E\x67\x3A\x20\x63\x68\x75\x6e\x6b\x65\x64" // "Transfer-Encoding: chunked"
#define ASCII_S_LEFTPAREN "\x28" // "("
-#define ASCII_S_COLON "\x3A" // ":"
/*
* HTTPTransport constuctor
@@ -88,14 +87,11 @@
m_eProtocolType = APTHTTP1_1;
m_strBytesToSend = "";
m_strHeaderBytesToSend = "";
- m_iBytesLeft = 0;
- m_iContentLength = 0;
m_bChannelSecure = false;
m_pNormalChannel = 0;
m_pSecureChannel = 0;
m_pActiveChannel = 0;
m_pChannelFactory = new ChannelFactory();
- m_bMimeTrue = false;
m_viCurrentHeader = m_vHTTPHeaders.begin();
m_viCurrentResponseHeader = m_vResponseHTTPHeaders.begin();
m_pszRxBuffer = new char [BUF_SIZE];
@@ -109,7 +105,7 @@
m_pNormalChannel = m_pChannelFactory->createChannel(UnsecureChannel);
m_pSecureChannel = m_pChannelFactory->createChannel(SecureChannel);
- m_GetBytesState = eWaitingForHTTPHeader;
+ resetInputStateMachine();
}
/*
@@ -123,6 +119,19 @@
delete [] m_pszRxBuffer;
}
+void HTTPTransport::
+resetInputStateMachine()
+{
+ m_GetBytesState = eWaitingForHTTPHeader;
+
+ m_strReceived.erase(0);
+ m_iBytesLeft = 0;
+ m_iChunkedDataLeftToConsume = 0;
+ m_iNextChunkedDataSize = 0;
+ m_iContentLength = 0;
+ m_bMimeTrue = false;
+}
+
/*
* HTTPTransport::setEndpointUri( EndpointURI) sets the URI for the message.
* Everytime the endpoint changes then currently connected channel is closed
@@ -202,8 +211,11 @@
int HTTPTransport::
openConnection()
{
- if( m_bReopenConnection)
+ if( m_bReopenConnection || m_pActiveChannel->reopenRequired())
{
+ // Call closeConnection in order to reset various state variables.
+ closeConnection();
+
m_bReopenConnection = false;
if( m_pActiveChannel->open() != AXIS_SUCCESS)
@@ -221,14 +233,7 @@
void HTTPTransport::
closeConnection()
{
- // get ready for a new message.
- m_GetBytesState = eWaitingForHTTPHeader;
-
- //clear the message buffer in preperation of the next read.
- m_strReceived = "";
- m_iBytesLeft = 0;
-
- m_iContentLength = 0;
+ resetInputStateMachine();
// Samisa : closing the connection is done in setEndpointUri no need to close here Fix for AXISCPP-481
}
@@ -256,25 +261,21 @@
// The header is now complete. The message header and message can now be transmitted.
try
{
- const char *writeBuffer;
- int bytesToWrite;
-
// Generate HTTP header string
- writeBuffer = this->getHTTPHeaders ();
- bytesToWrite = strlen(writeBuffer);
+ generateHTTPHeaders ();
- // Send the data
+ // Send HTTP headers and body
#ifndef __OS400__
- m_pActiveChannel->writeBytes(writeBuffer, bytesToWrite);
- m_pActiveChannel->writeBytes(this->m_strBytesToSend.c_str(), m_strBytesToSend.length());
+ m_pActiveChannel->writeBytes(m_strHeaderBytesToSend.c_str(), m_strHeaderBytesToSend.length());
+ m_pActiveChannel->writeBytes(m_strBytesToSend.c_str(), m_strBytesToSend.length());
#else
// Ebcdic (OS/400) systems need to convert the data to UTF-8. Note that free()
// is correctly used and should not be changed to delete().
- utf8Buf = toUTF8((char *)writeBuffer, bytesToWrite+1);
+ utf8Buf = toUTF8((char *)m_strHeaderBytesToSend.c_str(), m_strHeaderBytesToSend.length()+1);
m_pActiveChannel->writeBytes(utf8Buf, strlen(utf8Buf));
free(utf8Buf);
utf8Buf = NULL;
- utf8Buf = toUTF8((char *)this->m_strBytesToSend.c_str(), this->m_strBytesToSend.length()+1);
+ utf8Buf = toUTF8((char *)m_strBytesToSend.c_str(), m_strBytesToSend.length()+1);
m_pActiveChannel->writeBytes(utf8Buf, strlen(utf8Buf));
free(utf8Buf);
utf8Buf = NULL;
@@ -307,7 +308,7 @@
* the HTTP header block of information.
*/
const char * HTTPTransport::
-getHTTPHeaders()
+generateHTTPHeaders()
{
URL & url = m_pActiveChannel->getURLObject();
unsigned short uiPort;
@@ -472,6 +473,15 @@
return TRANSPORT_IN_PROGRESS;
}
+bool HTTPTransport::
+isThereResponseData()
+{
+ // We do not want to consume any SOAP data, just find out if there is any data.
+ int bufLen = 0;
+ getBytes(NULL, &bufLen);
+ return (m_GetBytesState != eWaitingForHTTPHeader || m_iBytesLeft != 0);
+}
+
/* HTTPTransport::getBytes( ReceiveBuffer, Size) Is a public method that will
* receive the synchronous reply to the sent message.
*
@@ -486,172 +496,295 @@
AXIS_TRANSPORT_STATUS HTTPTransport::
getBytes( char * pcBuffer, int * piSize) throw (AxisException, HTTPTransportException)
{
- std::string nextChunk = "";
-
- // It is assumed that the constructor has initialised the following variables:-
- // Type Label Initial Value Description
- // enum m_eMsgState eHTTP_Header Message decode state.
- // int m_iBytesLeft 0 Size of string held in m_strReceived.
- // char * m_pszRxBuffer new char [BUF_SIZE] Local buffer with message read from channel.
- // std::string m_strReceived <uninitialised> Contains the concatination of all unprocessed message string parts.
-
// The method getBytes has three distinct states. These are defined as
// follows:-
- // eWaitingForHTTPHeader - Waiting for a 'valid' HTTP header. A header is
- // is valid when a 'HTTP' string is found that is
- // subsequently followed by a CRLFCRLF sequence.
- // The HTTP header is then read and if the message
- // number is incorrect an exception is thrown.
- // The header also contains information on whether
- // the accompanying message is or is not chunked.
- // eSOAPMessageIsChunked - When a message is chunked, it has been broken
- // into a number of blocks. Each block is
- // preceeded by a hex number. The number is the
- // chunk length. A zero length chunk represents
- // the end of the message.
- // NB: because AXIS uses a 'pull' parser, the last
- // chunk size should never be read as the
- // parser will return once it has encountered
- // '</envelope>'. If it does read the last
- // '0', this could indicate that there is a
- // problem in the message.
- // eSOAPMessageIsNotChunked - The message is read until the number of message
- // bytes read equals the HTTP header content
- // length value.
- switch( m_GetBytesState)
- {
- case eWaitingForHTTPHeader:
- {
- // If there is data in buffer, then drop out of the switch statement? Not sure.
- if( m_iBytesLeft > 0)
- break;
+ // eWaitingForHTTPHeader - Waiting for HTTP response header. Initiate processing
+ // that will read an HTTP header. One caveat.
+ // We can be in this state but still have data
+ // to be processed. So if there is data, it will
+ // be returned and we will not attempt to read
+ // an HTTP response.
+ // eSOAPMessageIsChunked - Keep reading until a zero length chunk is
+ // encountered, signifying end of response.
+ // eSOAPMessageIsNotChunked - Keep reading until the connection is closed.
+ // eSOAPMessageHasContentLength - Keep reading until content-length is zero. to zero.
- // Wait for a HTTP header to be located on the input stream.
- do
- {
- readHTTPHeader();
- processHTTPHeader();
- }
- while( m_iResponseHTTPStatusCode == 100);
+
+ // Read in an HTTP header if we are waiting for one. Now this is a bit tricky
+ // and I was fooled by this when I was fix problems in the code so here is
+ // the tricky part. If we have data in the buffer then we need to return
+ // the data - i.e. we will skip reading HTTP header until data has been
+ // consumed! Not the most elegant of designs, but it works. The reason is
+ // that we read in data later on and then change the state based on whether
+ // there is more data to read or not. The caller of this routine will have
+ // data copied into buffer, but the buffer may not be big enough to consume
+ // the data, so that is why we have data in the buffer left and thus must
+ // skip reading HTTP header until data has been consumed.
+ if (m_GetBytesState == eWaitingForHTTPHeader)
+ if (m_iBytesLeft == 0)
+ readHTTPHeader();
+
+ // Process data based on current state.
+ int iBytesToCopy = m_iBytesLeft;
+
+ if (m_GetBytesState == eSOAPMessageHasContentLength)
+ iBytesToCopy = getBytes_MessageHasContentLength(pcBuffer, piSize);
+ else if (m_GetBytesState == eSOAPMessageIsNotChunked)
+ iBytesToCopy = getBytes_MessageIsNotChunked(pcBuffer, piSize);
+ else if( m_GetBytesState == eSOAPMessageIsChunked)
+ iBytesToCopy = getBytes_MessageIsChunked(pcBuffer, piSize);
- // Check that the HTTP status code is valid.
- checkHTTPStatusCode();
+ // Copy as much of the message to the parser buffer as possible.
+ if (iBytesToCopy > 0 && *piSize > 0)
+ {
+ int iToCopy = (*piSize < iBytesToCopy) ? *piSize : iBytesToCopy;
- // Done with HTTP headers, get SOAP message.
- int iHTTPStart = m_strReceived.find( ASCII_S_HTTP);
- int iHTTPEnd = m_strReceived.find( ASCII_S_CRLFCRLF, iHTTPStart);
+ m_strReceived.copy(pcBuffer, iToCopy);
+ *piSize = iToCopy;
+ m_iBytesLeft -= iToCopy;
+ m_strReceived.erase(0, iToCopy);
+ }
+ else
+ *piSize = 0;
- m_strReceived = m_strReceived.substr( iHTTPEnd + strlen( ASCII_S_CRLFCRLF));
+ // Set transport status
+ return (m_iBytesLeft > 0 || (m_GetBytesState != eWaitingForHTTPHeader)) ?
+ TRANSPORT_IN_PROGRESS : TRANSPORT_FINISHED;
+}
- m_iBytesLeft = m_strReceived.length();
+/**
+ * getBytes_MessageHasContentLength() is used when the HTTP response
+ * includes the Content-Length HTTP header.
+ */
+int HTTPTransport::
+getBytes_MessageHasContentLength(char * pcBuffer, int * piSize)
+{
+ // If we do not have data to give back, read more.
+ if (m_iContentLength > 0 && m_iBytesLeft == 0)
+ {
+ getNextDataPacket( "No data available for message.");
- // This bit of code should not be necessary, but just in case...???
- if( m_GetBytesState == eWaitingForHTTPHeader)
- break;
- }
-
- case eSOAPMessageIsChunked:
+ // Check for Mime header
+ if( m_bMimeTrue)
{
- // We are processing a response that is chunked...
- if( m_GetBytesState == eSOAPMessageIsChunked)
- {
- if( m_iBytesLeft == 0)
- getNextDataPacket( "No data available for next chunk size.");
-
- m_iContentLength = getChunkSize();
+ processRootMimeBody();
+ m_iBytesLeft = m_strReceived.length();
+ }
+ }
+
+ // Subtract message length (so far) from expected content length.
+ if( m_iContentLength >= m_iBytesLeft)
+ m_iContentLength -= m_iBytesLeft;
+ else
+ m_iContentLength = 0;
+
+ // If all of the message has been received, then reset the process state
+ if (0 == m_iContentLength)
+ m_GetBytesState = eWaitingForHTTPHeader;
+
+ // Return number of bytes that can be copied
+ return m_iBytesLeft;
+}
- // If the chunk size is larger than the available data, then read in more data until all of the
- // chunk has been read.
- while( m_iContentLength > m_iBytesLeft)
- {
- getNextDataPacket( "No data available for next chunk.");
- }
-
- // If data read is longer than chunk size, then copy the extra data to a temporary variable and
- // process data just belonging to this chunk.
- if( m_iBytesLeft > m_iContentLength)
- {
- if( m_strReceived.length() > (m_iContentLength + strlen( ASCII_S_CRLF) + 1))
- nextChunk = m_strReceived.substr( m_iContentLength + strlen( ASCII_S_CRLF));
- else
- nextChunk = "";
-
- m_strReceived = m_strReceived.substr( 0, m_iContentLength);
- m_iBytesLeft = m_iContentLength;
-
- // Check to see if the next chunk size is zero. If it is then change the state.
- if( peekChunkLength( nextChunk) == 0)
- m_GetBytesState = eWaitingForHTTPHeader;
- }
- else
- nextChunk = "";
-
- // Now have at least chunk size worth of data. The chunk may contain Mime data (this depends on
- // information in the HTTP header). If Mime data is expected, process it first.
- if( m_bMimeTrue)
- {
- processRootMimeBody();
- m_iBytesLeft = m_strReceived.length();
- }
+/**
+ * getBytes_MessageIsNotChunked() is used when the HTTP response
+ * is not chunked and does not include the Content-Length HTTP header.
+ * Thus, the only way we know that the data has been read is to read
+ * from the input stream until a zero length read completes.
+ */
+int HTTPTransport::
+getBytes_MessageIsNotChunked(char * pcBuffer, int * piSize)
+{
+ // Keep reading until the connection is closed by the server.
+ getNextDataPacket( "Expecting server connection to close.");
- break;
- }
- }
+ // Check for Mime header
+ if( m_bMimeTrue)
+ {
+ processRootMimeBody();
+ m_iBytesLeft = m_strReceived.length();
+ }
+
+ // Return number of bytes that can be copied
+ return m_iBytesLeft;
+}
- case eSOAPMessageIsNotChunked:
+/**
+ * getBytes_MessageIsChunked() is used when the HTTP response
+ * is chunked. The chunked encoding modifies the body of a message
+ * in order to transfer it as a series of chunks, each with its own
+ * size indicator, followed by an OPTIONAL trailer containing
+ * entity-header fields. This allows dynamically produced content to
+ * be transferred along with the information necessary for the recipient
+ * to verify that it has received the full message. Format is as follows:
+ *
+ * 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. The
+ * trailer is ignored by this routine.
+ */
+int HTTPTransport::
+getBytes_MessageIsChunked(char * pcBuffer, int * piSize)
+{
+ // We only read the next chunk if the chunk we have has been consumed.
+ if (m_iChunkedDataLeftToConsume == 0)
+ {
+ // First, ensure that we remove any leading CRLF. This would be the
+ // ending CRLF for a chunk. A chunk has this form:
+ // chunk-data CRLF
+ if (m_iBytesLeft > 1
+ && m_strReceived[0] == ASCII_C_CR && m_strReceived[1] == ASCII_C_LF)
{
- // Check that there is more message to read. Or, if the message has no length defined,
- // keep reading until the connection is closed by the server.
- if( m_iContentLength > 0 || (m_bReopenConnection && m_pActiveChannel->getSocket()))
+ m_strReceived.erase(0, 2);
+ m_iBytesLeft = m_strReceived.length();
+ }
+
+ // Get chunk size. We may already have it. It is set to zero only if we have
+ // not obtained it. It is also set to zero for end of chunk size of zero, but we should
+ // never be coming down to read it.
+ if (m_iNextChunkedDataSize > 0)
+ {
+ // Need to remove the chunk-size line since it has been already processed.
+ // Should never be the case where we get npos, but we check just in case.
+ string::size_type iEndOfChunkSize = m_strReceived.find(ASCII_S_CRLF);
+ if (iEndOfChunkSize != std::string::npos)
{
- if( m_iContentLength > 0)
- getNextDataPacket( "No data available for message.");
- else
- getNextDataPacket( "Expecting server connection to close.");
-
- // Check for Mime header
- if( m_bMimeTrue)
- {
- processRootMimeBody();
- m_iBytesLeft = m_strReceived.length();
- }
-
- // Subtract message length (so far) from expcted content length.
- m_iContentLength -= m_iBytesLeft;
-
- // If all of the message has been received, then reset the process state.
- if( m_iContentLength <= 0)
- {
- // The content length is <= 0, BUT if m_bReopenConnection is true
- // (because a 'Connection: close' has been found) the socket has been
- // closed by the server, then wait for the next HTTP message, otherwise
- // keep reading!
- if( m_bReopenConnection && m_pActiveChannel->getSocket())
- m_iContentLength = 0;
- else
- m_GetBytesState = eWaitingForHTTPHeader;
- }
+ m_strReceived.erase(0, iEndOfChunkSize + 2);
+ m_iBytesLeft = m_strReceived.length();
}
- else
- {
- // Reset the process state.
+
+ m_iChunkedDataLeftToConsume = m_iNextChunkedDataSize;
+ m_iNextChunkedDataSize = 0;
+ }
+ else
+ m_iChunkedDataLeftToConsume = getChunkSize();
+
+ // We should never be in a situation where caller invokes getBytes
+ // and there is no data to read, but just in case...
+ if (m_iChunkedDataLeftToConsume > 0)
+ {
+ // If the chunk size is larger than the available data, then read in more
+ // data until all of the chunk has been read. We read in the CRLF that
+ // ends a chunk and at least one more byte so that later we can read the
+ // next chunk size.
+ while ((m_iChunkedDataLeftToConsume + 2) >= m_iBytesLeft)
+ getNextDataPacket( "No data available for next chunk.");
+
+ // Determine next chunk size, mainly to determine if zero-length,
+ // meaning end-of-chunk processing and thus a state reset.
+ // "+ 2" used in if-check for CRLF since at end of each chunk there should be CRLF.
+ if (0 == (m_iNextChunkedDataSize = getChunkSize(m_iChunkedDataLeftToConsume + 2)))
m_GetBytesState = eWaitingForHTTPHeader;
+
+ // The chunk may contain Mime data (this depends on information in the HTTP header).
+ if( m_bMimeTrue)
+ {
+ processRootMimeBody();
+ m_iBytesLeft = m_strReceived.length();
}
-
- break;
}
+ else
+ m_GetBytesState = eWaitingForHTTPHeader;
}
-
- // Copy as much of the message to the parser buffer as possible.
- if( copyDataToParserBuffer( pcBuffer, piSize, m_iBytesLeft))
+
+ // OK, now we need to determine how much of the chunk will be left
+ // over depending on the buffer length that is passed in.
+ int iDataToCpyLen;
+ if (*piSize >= m_iChunkedDataLeftToConsume)
{
- m_strReceived += nextChunk;
- m_iBytesLeft = m_strReceived.length();
+ iDataToCpyLen = m_iChunkedDataLeftToConsume;
+ m_iChunkedDataLeftToConsume = 0;
+ }
+ else
+ {
+ iDataToCpyLen = *piSize;
+ m_iChunkedDataLeftToConsume -= *piSize;
+ }
+
+ return iDataToCpyLen;
+}
+
+/**
+ * getChunkSize() is method used to obtain the chunk size.
+ * Once obtained, it may remove the chunksize line from
+ * the data since it is not data to be returned.
+ */
+int HTTPTransport::
+getChunkSize(string::size_type pos)
+{
+ string::size_type iEndOfChunkSize;
+ string::size_type iEndOfChunkLine;
+
+ // Here is what a chunk size line may look like:
+ // chunk-size [ chunk-extension ] CRLF
+ // where chunk-extension is defined as:
+ // *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
+
+ // Get complete line.
+ while( (iEndOfChunkLine = m_strReceived.find(ASCII_S_CRLF, pos)) == std::string::npos )
+ getNextDataPacket("Could not find delimiter for end of chunk size.");
- return TRANSPORT_IN_PROGRESS;
+ string chunkSizeLine = m_strReceived.substr( pos, iEndOfChunkLine-pos);
+
+ // Look to see if there are any extensions - these are put in brackets.
+ if ((iEndOfChunkSize = chunkSizeLine.find(ASCII_S_LEFTPAREN)) != std::string::npos)
+ chunkSizeLine.erase(iEndOfChunkSize);
+
+ // Convert the hex string into the length of the chunk.
+ int chunkSize = axtoi((char *)chunkSizeLine.c_str());
+
+ // A chunk size of -1 means either we received an invalid chunk size
+ // or the code is not parsing chunks correctly. Whatever the case,
+ // we are hosed and there is no use continuing.
+ if (-1 == chunkSize)
+ {
+ m_bReopenConnection = true;
+
+ // We will only dump out just 40 bytes...otherwise we may be
+ // dumping out huge chunks of data
+ if (chunkSizeLine.length() > 40)
+ chunkSizeLine = chunkSizeLine.substr(0, 40);
+
+ PLATFORM_ASCTOSTR(chunkSizeLine.c_str());
+ string errorMessage = string("Chunk size (") + chunkSizeLine + string(") not valid.");
+ throw HTTPTransportException(SERVER_TRANSPORT_HTTP_EXCEPTION, errorMessage.c_str());
}
- return TRANSPORT_FINISHED;
+ // If chunksize is zero, remove the line including ending CRLFCRLF. This line
+ // will never be consumed so it needs to be removed from the buffer. Otherwise,
+ // if chunksize is not zero, we only remove the chunksize line only if offset is
+ // zero, i.e. at the beginning of line. If offset is not zero, it means this
+ // request came down to peek at the next chunksize.
+ if (0 == chunkSize)
+ {
+ string::size_type iEndOfResponse;
+ while ((iEndOfResponse = m_strReceived.find(ASCII_S_CRLFCRLF, pos)) == std::string::npos )
+ getNextDataPacket("Could not find delimiter for end of chunked response.");
+
+ m_strReceived.erase(pos, iEndOfResponse + 4); // "+4" for CRLFCRLF
+ }
+ else if (pos == 0)
+ m_strReceived.erase(0, iEndOfChunkLine + 2); // "+2" for CRLF
+ m_iBytesLeft = m_strReceived.length();
+
+ // return chunksize
+ return chunkSize;
}
/* HTTPTransport::setTransportProperty( Type, Value) Is an overloaded public
@@ -877,7 +1010,8 @@
* @return const char* Value is a NULL terminated character string containing
* the value associated with the service name.
*/
-const char * HTTPTransport::getServiceName()
+const char * HTTPTransport::
+getServiceName()
{
//Assume SOAPAction header to contain service name
int iIndex = FindTransportPropertyIndex( "SOAPAction");
@@ -975,15 +1109,13 @@
int iM = 0; // position in digit[] to shift
int iCount; // loop index
int intValue = 0; // integer value of hex string
- int iDigit[32]; // hold values to convert
+ int iDigit[32]; // hold values to convert
- while( iN < 32)
- {
- if( pcHexString[iN] == '\0')
- break;
+ bool badChunkSize = false;
- if( pcHexString[iN] >= ASCII_C_ZERO &&
- pcHexString[iN] <= ASCII_C_NINE)
+ while( iN < 32 && pcHexString[iN] != '\0')
+ {
+ if( pcHexString[iN] >= ASCII_C_ZERO && pcHexString[iN] <= ASCII_C_NINE)
{
iDigit[iN] = pcHexString[iN] & 0x0f; //convert to int
}
@@ -995,10 +1127,16 @@
iDigit[iN] = (pcHexString[iN] & 0x0f) + 9; //convert to int
}
else
+ {
+ badChunkSize = true;
break;
+ }
iN++;
}
+
+ if (badChunkSize || pcHexString[0] == '\0')
+ return -1;
iCount = iN;
iM = iN - 1;
@@ -1006,8 +1144,8 @@
while( iN < iCount)
{
- // digit[n] is value of hex digit at position n (m << 2) is the number of positions to shift OR the bits into
- // return value
+ // digit[n] is value of hex digit at position n (m << 2) is the
+ // number of positions to shift OR the bits into return value
intValue = intValue | (iDigit[iN] << (iM << 2));
iM--; // adjust the position to set
iN++; // next digit to process
@@ -1016,85 +1154,107 @@
return intValue;
}
-/* HTTPTransport::processResponseHTTPHeaders() Is a public method used to
+/**
+ * HTTPTransport::processHTTPHeader() Is a public method used to
* parse the HTTP header of the response message.
*/
void HTTPTransport::
-processResponseHTTPHeaders() throw (HTTPTransportException)
+processHTTPHeader()
{
- unsigned long iPosition = std::string::npos;
- unsigned long iStartPosition = iPosition;
-
- if( (iPosition = m_strResponseHTTPHeaders.find( ASCII_S_HTTP )) == std::string::npos)
+ // Prior to calling this method, m_strResponseHTTPHeaders should have been
+ // set to the HTTP header in the response, which is in ascii. For EBCDIC
+ // systems, we need to convert the data from ASCII to EBCDIC.
+ // WARNING: Response header processing within here should not be moved
+ // unless you search for the right string - ascii or ebcdic.
+ // Since we convert everything to EBCDIC, we can use literal
+ // strings such as "\r\n" instead of ascii equivalent "\x0d\x0a".
+ PLATFORM_ASCTOSTR(m_strResponseHTTPHeaders.c_str());
+
+ // The first line of a Response message is the Status-Line:
+ //
+ // Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
+ //
+ // Parse it to get status code and reason-phrase.
+
+ string::size_type iPosition = std::string::npos;
+ string::size_type iStartPosition = iPosition;
+
+ if( (iPosition = m_strResponseHTTPHeaders.find( "HTTP" )) == std::string::npos)
{
throw HTTPTransportException( SERVER_TRANSPORT_UNKNOWN_HTTP_RESPONSE,
"Protocol is not HTTP.");
}
+
+ m_strResponseHTTPProtocol = m_strResponseHTTPHeaders.substr( iPosition, strlen("HTTP/1.x"));
+ iPosition += strlen("HTTP/1.x");
- m_strResponseHTTPProtocol = m_strResponseHTTPHeaders.substr( iPosition, strlen( "HTTP/1.x"));
- iPosition += strlen( "HTTP/1.x");
-
- while( m_strResponseHTTPHeaders.substr()[iPosition] == ASCII_C_SPACE)
- {
+ while( m_strResponseHTTPHeaders[iPosition] == ' ')
iPosition++;
- }
iStartPosition = iPosition;
- while( m_strResponseHTTPHeaders.substr()[iPosition] != ASCII_C_SPACE )
- {
+ while( m_strResponseHTTPHeaders[iPosition] != ' ' )
iPosition++;
- }
std::string strResponseHTTPStatusCode = m_strResponseHTTPHeaders.substr( iStartPosition,iPosition - iStartPosition);
- m_iResponseHTTPStatusCode = atoi( PLATFORM_ASCTOSTR(strResponseHTTPStatusCode.c_str()));
+ m_iResponseHTTPStatusCode = atoi(strResponseHTTPStatusCode.c_str());
iStartPosition = ++iPosition;
- iPosition = m_strResponseHTTPHeaders.find( ASCII_S_LF );
+ iPosition = m_strResponseHTTPHeaders.find( "\n" );
m_strResponseHTTPStatusMessage = m_strResponseHTTPHeaders.substr( iStartPosition,iPosition - iStartPosition - 1);
- PLATFORM_ASCTOSTR(m_strResponseHTTPStatusMessage.c_str());
// reached the end of the first line
- iStartPosition = m_strResponseHTTPHeaders.find( ASCII_S_LF );
-
+ iStartPosition = m_strResponseHTTPHeaders.find( "\n" );
iStartPosition++;
- // read header fields and add to vector
+ // Now read the header fields and add to vector.
do
{
+ // Remove consumed line from header string.
m_strResponseHTTPHeaders = m_strResponseHTTPHeaders.substr( iStartPosition);
- iPosition = m_strResponseHTTPHeaders.find( ASCII_S_LF );
-
+
+ // now find end of line...if we do not find one, break out.
+ iPosition = m_strResponseHTTPHeaders.find( "\n" );
if( iPosition == std::string::npos)
break;
-
- std::string strHeaderLine = m_strResponseHTTPHeaders.substr( 0, iPosition);
- unsigned long iSeperator = strHeaderLine.find( ASCII_S_COLON );
-
- if( iSeperator == std::string::npos)
- break;
-
iStartPosition = iPosition + 1;
+
+ // store line in work buffer and find seperator ":", if no seperator,
+ // continue on with next line.
+ std::string strHeaderLine = m_strResponseHTTPHeaders.substr(0, iPosition);
+
+ string::size_type iSeperator = strHeaderLine.find( ":" );
+ if( iSeperator == std::string::npos)
+ continue;
- string key = strHeaderLine.substr( 0, iSeperator);
- string value = strHeaderLine.substr( iSeperator + 1,
- strHeaderLine.length () - iSeperator - 1 - 1);
- PLATFORM_ASCTOSTR(key.c_str());
- PLATFORM_ASCTOSTR(value.c_str());
-
+ // Store as key-value pairs
+ string key = strHeaderLine.substr( 0, iSeperator);
+ string value = strHeaderLine.substr( iSeperator + 1, strHeaderLine.length() - iSeperator - 2);
m_vResponseHTTPHeaders.push_back( std::make_pair( key, value));
- // if HTTP/1.0 we have to always close the connection by default
+ // Content length set? Chunked overrides Content-length. It should be noted
+ // that on successful one-way requests Content-Length would be set to zero.
+ if (key == "Content-Length")
+ if (m_GetBytesState != eSOAPMessageIsChunked)
+ {
+ m_iContentLength = atoi(value.c_str());
+ m_GetBytesState = eSOAPMessageHasContentLength;
+ }
+
+ // Is chunked?
+ if (key == "Transfer-Encoding" && value == " chunked")
+ m_GetBytesState = eSOAPMessageIsChunked;
+
+ // Now handle whether we are going to close connection after processing
+ // request. If HTTP/1.0 we have to always close the connection by default; otherwise,
+ // we assume persistant connection by default.
if( m_eProtocolType == APTHTTP1_0)
m_bReopenConnection = true;
- // if HTTP/1.1 we have to assume persistant connection by default
-
// We need to close the connection and open a new one if we have 'Connection: close'
if( key == "Connection" && (value == " close" || value == " Close"))
{
m_bReopenConnection = true;
-
m_pActiveChannel->closeQuietly( true);
}
@@ -1116,7 +1276,7 @@
{
m_strContentType = value;
- unsigned long ulMimePos = m_strContentType.find( ";");
+ string::size_type ulMimePos = m_strContentType.find( ";");
std::string strTypePart;
if( ulMimePos != std::string::npos)
@@ -1131,7 +1291,6 @@
m_strMimeBoundary = m_strContentType.substr( ulMimePos);
ulMimePos = m_strMimeBoundary.find( ";");
m_strMimeBoundary = m_strMimeBoundary.substr( 9, ulMimePos - 9);
- PLATFORM_STRTOASC(m_strMimeBoundary.c_str());
ulMimePos = m_strContentType.find( "type=");
m_strMimeType = m_strContentType.substr( ulMimePos);
@@ -1146,6 +1305,12 @@
}
}
while( iPosition != std::string::npos);
+
+ // HTTP protocol allows body with no Content-Length and no transfer-encoding! This
+ // means that we read from the stream until we are unable to read anymore. So ensure
+ // state is set correctly. In this case we set it to not-chunked.
+ if (m_GetBytesState == eWaitingForHTTPHeader)
+ m_GetBytesState = eSOAPMessageIsNotChunked;
}
/* HTTPTransport::processRootMimeBody() Is a public method used to
@@ -1176,7 +1341,7 @@
// the payload which contain the soap message
m_strReceived = m_strReceived.substr( m_strReceived.find( ASCII_S_CRLFCRLF ) + 4);
- unsigned long intMimeTemp = m_strReceived.find( m_strMimeBoundary);
+ string::size_type intMimeTemp = m_strReceived.find( m_strMimeBoundary);
if (intMimeTemp != std::string::npos)
{
@@ -1190,7 +1355,7 @@
}
else
{
- unsigned long intMimeTemp = m_strReceived.find( m_strMimeBoundary);
+ string::size_type intMimeTemp = m_strReceived.find( m_strMimeBoundary);
if( intMimeTemp != std::string::npos)
{
@@ -1211,8 +1376,8 @@
*/
void HTTPTransport::processMimeHeader()
{
- unsigned long pos = 0;
- unsigned long temppos = 0;
+ string::size_type pos = 0;
+ string::size_type temppos = 0;
// Look for content lenght
if( (pos = m_strMimeReceived.find( "Content-Type: ")) != std::string::npos)
@@ -1469,210 +1634,107 @@
void HTTPTransport::
readHTTPHeader()
-{
+{
+ m_pActiveChannel->closeQuietly( false);
+
// The parser is expecting a SOAP message. Thus, the HTTP header must have
// been read and processed before control is returned to the parser. It can
// not be assumed that the HTTP header will be read in one block, thus there
// must be processing that first identifies the beginning of the HTTP header
// block (i.e. looks for 'HTTP') and then additional processing that identifies
// the end of the HTTP header block (i.e. looks for CR LF CR LF).
- int numberOfBytesRead = 0;
-
- m_strReceived = "";
- m_iBytesLeft = 0;
- m_pActiveChannel->closeQuietly( false);
-
+ // Note that for HTTP 100 responses, we consume it and restart the process.
+ int numberOfBytesRead;
+ string::size_type iHTTPStart;
+ string::size_type iHTTPEnd;
+
do
{
- numberOfBytesRead = m_pActiveChannel->readBytes(m_pszRxBuffer, BUF_SIZE);
-
- if (numberOfBytesRead > 0)
- m_strReceived += m_pszRxBuffer;
- else
+ resetInputStateMachine();
+
+ while (m_strReceived.find( ASCII_S_HTTP) == std::string::npos
+ || m_strReceived.find( ASCII_S_CRLFCRLF) == std::string::npos)
{
- throw HTTPTransportException( SERVER_TRANSPORT_INPUT_STREAMING_ERROR,
- "Socket connection has been closed.");
+ numberOfBytesRead = m_pActiveChannel->readBytes(m_pszRxBuffer, BUF_SIZE);
+
+ if (numberOfBytesRead > 0)
+ {
+ m_strReceived += m_pszRxBuffer;
+ m_iBytesLeft = m_strReceived.length();
+ }
+ else
+ {
+ m_bReopenConnection = true;
+ throw HTTPTransportException( SERVER_TRANSPORT_INPUT_STREAMING_ERROR,
+ "Socket connection has been closed.");
+ }
}
-
- // Check for beginning and end of HTTP header.
- if( m_strReceived.find( ASCII_S_HTTP) != std::string::npos
- && m_strReceived.find( ASCII_S_CRLFCRLF) != std::string::npos)
- break;
- }
- while(numberOfBytesRead > 0);
-}
-
-void HTTPTransport::
-processHTTPHeader()
-{
- // At this point the HTTP header has been found. It now needs to be processed.
- int iPosContentLength = m_strReceived.find( ASCII_S_CONTENT_LENGTH);
-
- if( iPosContentLength != std::string::npos)
- {
- int iEOL = m_strReceived.find( ASCII_S_LF, iPosContentLength);
- iPosContentLength += strlen( ASCII_S_CONTENT_LENGTH);
- m_iContentLength = atoi(PLATFORM_ASCTOSTR (m_strReceived.substr( iPosContentLength, iEOL).c_str()));
- m_GetBytesState = eSOAPMessageIsNotChunked;
- }
-
- // Check if the message is chunked
- int iPosChunked = m_strReceived.find( ASCII_S_TRANSFERENCODING_CHUNKED);
- int iHTTPStart = m_strReceived.find( ASCII_S_HTTP);
- int iHTTPEnd = m_strReceived.find( ASCII_S_CRLFCRLF);
-
- if( iPosChunked != std::string::npos)
- {
- //Chunked data looks like ->
- // Chunked-Body = *chunk
- // "0" CRLF
- // footer
- // CRLF
- //
- // chunk = chunk-size [ chunk-ext ] CRLF
- // chunk-data CRLF
- //
- // hex-no-zero = <HEX excluding "0">
- //
- // chunk-size = hex-no-zero *HEX
- // chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-value ] )
- // chunk-ext-name = token
- // chunk-ext-val = token | quoted-string
- // chunk-data = chunk-size(OCTET)
- //
- // footer = *entity-header
-
- m_GetBytesState = eSOAPMessageIsChunked;
- }
- else if( (m_eProtocolType == APTHTTP1_0) || (m_eProtocolType == APTHTTP1_1) )
- {
- m_GetBytesState = eSOAPMessageIsNotChunked;
- m_iBytesLeft = m_strReceived.substr( iHTTPEnd + 2).length();
-
- // Check if all the message has already been received. If not, then subtract
- // that bit that has been from the total length. If so, then make the content length
- // equal to zero.
- if( m_iContentLength >= m_iBytesLeft)
- m_iContentLength -= m_iBytesLeft;
- else
- m_iContentLength = 0;
- }
- else
- {
- m_GetBytesState = eWaitingForHTTPHeader;
- throw HTTPTransportException( SERVER_TRANSPORT_INPUT_STREAMING_ERROR,
- "HTTP header message must be chunked or have a content length.");
+
+ // At this point the HTTP header has been found. Seperate the response headers
+ // from the payload (i.e. SOAP message).
+ iHTTPStart = m_strReceived.find( ASCII_S_HTTP);
+ iHTTPEnd = m_strReceived.find( ASCII_S_CRLFCRLF, iHTTPStart);
+
+ m_strResponseHTTPHeaders = m_strReceived.substr( iHTTPStart, iHTTPEnd + 4 - iHTTPStart);
+
+ // Process the HTTP header
+ processHTTPHeader();
}
-
- // Extract HTTP header and process it
- m_strResponseHTTPHeaders = m_strReceived.substr( iHTTPStart, iHTTPEnd + 2 - iHTTPStart);
-
- processResponseHTTPHeaders();
-
- // If the HTTP message is a 'continue' message then remove the HTTP header and
- // then repeat HTTP header processing.
- if( m_iResponseHTTPStatusCode == 100)
- m_strReceived = m_strReceived.substr( iHTTPEnd + 2);
-}
-
-void HTTPTransport::
-checkHTTPStatusCode()
-{
- // Now have a valid HTTP header that is not 100.
- if ( m_iResponseHTTPStatusCode != 500 &&
- (m_iResponseHTTPStatusCode < 200 ||
- m_iResponseHTTPStatusCode >= 300))
+ while( m_iResponseHTTPStatusCode == 100);
+
+ // Now have a valid HTTP header that is not 100. Throw an exception if some unexpected error.
+ // Note that error 500 are for for SOAP faults.
+ if ( m_iResponseHTTPStatusCode != 500
+ && (m_iResponseHTTPStatusCode < 200 || m_iResponseHTTPStatusCode >= 300))
{
- m_GetBytesState = eWaitingForHTTPHeader;
-
m_strResponseHTTPStatusMessage = std::string( "Server sent HTTP error: '") +
m_strResponseHTTPStatusMessage + std::string("'\n");
+ m_GetBytesState = eWaitingForHTTPHeader;
throw HTTPTransportException( SERVER_TRANSPORT_HTTP_EXCEPTION, m_strResponseHTTPStatusMessage.c_str());
- }
+ }
+
+ // We are home-free, now is the time to set the HTTP body - i.e. the SOAP message. Note that
+ // we could have done this in the loop, but why allocate resources if we do not need to.
+ m_strReceived = m_strReceived.substr( iHTTPEnd + 4);
+ m_iBytesLeft = m_strReceived.length();
}
-bool HTTPTransport::
-getNextDataPacket( const char * pcszExceptionMessage)
+int HTTPTransport::
+getNextDataPacket( const char * pcszExceptionMessage, char *bufferToUse, int *bufferLen)
{
- bool bDataRead = false;
- int numberOfBytesRead = 0;
+ int numberOfBytesRead;
// Read whatever part of the response message that has arrived at the active channel socket.
- numberOfBytesRead = m_pActiveChannel->readBytes(m_pszRxBuffer, BUF_SIZE);
+ // The buffer used is dependent on whether one is passed in. There is an internal buffer
+ // associated with the class, m_pszRxBuffer, that will be used if one is not passed in.
+ // Currently we do not pass buffers into this routine, but in the future we will as an
+ // optimization step...since if we are reading non-protocol data, we should just
+ // directly plop the data into parser buffer.
+ if (bufferToUse && bufferLen)
+ numberOfBytesRead = m_pActiveChannel->readBytes(bufferToUse, *bufferLen);
+ else
+ numberOfBytesRead = m_pActiveChannel->readBytes(m_pszRxBuffer, BUF_SIZE);
if( numberOfBytesRead > 0)
{
- m_strReceived += m_pszRxBuffer;
- m_iBytesLeft = m_strReceived.length();
+ if (bufferToUse && bufferLen)
+ *bufferLen = numberOfBytesRead;
+ else
+ {
+ m_strReceived += m_pszRxBuffer;
+ m_iBytesLeft = m_strReceived.length();
+ }
}
else if( m_strReceived.length() == 0)
{
- m_GetBytesState = eWaitingForHTTPHeader;
+ m_bReopenConnection = true;
if( pcszExceptionMessage != NULL && strlen( pcszExceptionMessage) > 0)
- {
throw HTTPTransportException( SERVER_TRANSPORT_HTTP_EXCEPTION, pcszExceptionMessage);
- }
}
- return (numberOfBytesRead > 0);
-}
-
-int HTTPTransport::
-getChunkSize()
-{
- int iChunkSize;
-
- while( m_strReceived.find( ASCII_S_CRLF) == std::string::npos)
- {
- getNextDataPacket( "Could not find delimiter for end of chunk size.");
- }
-
- int iEndOfChunkData = m_strReceived.find( ASCII_S_CRLF) + strlen( ASCII_S_CRLF);
- int iEndOfChunkSize = m_strReceived.find( ASCII_S_CRLF);
-
- // Now get the size of the chunk from the data. Look to see if there are any
- // extensions - these are put in brackets so look for those.
- if( m_strReceived.substr( 0, iEndOfChunkSize).find( ASCII_S_LEFTPAREN) != string::npos)
- iEndOfChunkSize = m_strReceived.find( ASCII_S_LEFTPAREN);
-
- // Convert the hex string into the length of the chunk.
- iChunkSize = axtoi( (char *) m_strReceived.substr( 0, iEndOfChunkSize).c_str());
-
- m_strReceived = m_strReceived.substr( iEndOfChunkData);
-
- m_iBytesLeft = m_strReceived.length();
-
- return iChunkSize;
-}
-
-bool HTTPTransport::
-copyDataToParserBuffer( char * pcBuffer, int * piSize, int iBytesToCopy)
-{
- bool bTransportInProgress = false;
-
- if( iBytesToCopy > 0)
- {
- int iToCopy = (*piSize < iBytesToCopy) ? *piSize : iBytesToCopy;
-
- strncpy( pcBuffer, m_strReceived.c_str(), iToCopy);
-
- m_iBytesLeft -= iToCopy;
- *piSize = iToCopy;
-
- if( m_iBytesLeft > 0)
- m_strReceived = m_strReceived.substr( iToCopy);
- else
- {
- m_strReceived = "";
- m_iBytesLeft = 0;
- }
-
- bTransportInProgress = true;
- }
-
- return bTransportInProgress;
+ return numberOfBytesRead;
}
int HTTPTransport::
@@ -1709,14 +1771,14 @@
// And discards stuff after first ';'
// This is the same assumption used in Axis Java
- unsigned long ulKeyEndsAt = nameValuePair.find( ";");
+ string::size_type ulKeyEndsAt = nameValuePair.find( ";");
string nameValue;
if( ulKeyEndsAt != std::string::npos)
nameValue = nameValuePair.substr( 0, ulKeyEndsAt);
// Now split the nameValue up
- unsigned long nameEndsAt = nameValue.find("=");
+ string::size_type nameEndsAt = nameValue.find("=");
return addCookie(nameValue.substr(0, nameEndsAt), nameValue.substr(nameEndsAt+1));
}
@@ -1746,28 +1808,6 @@
// we also need to remove it from the header properties that we send.
// This is done from the deleteTransportMethod before this one is called.
return AXIS_SUCCESS;
-}
-
-int HTTPTransport::
-peekChunkLength( std::string& strNextChunk)
-{
- if( strNextChunk.length() == 0)
- return -1;
-
- int iEndOfChunkSize = strNextChunk.find( ASCII_S_CRLF);
-
- if( iEndOfChunkSize == std::string::npos)
- return -1;
-
- // Now get the size of the chunk from the data. Look to see if there are any extensions - these are put in brackets
- // so look for those.
- if( strNextChunk.substr( iEndOfChunkSize).find( ASCII_S_LEFTPAREN) != std::string::npos)
- iEndOfChunkSize = strNextChunk.find( ASCII_S_LEFTPAREN);
-
- // Convert the hex string into the length of the chunk.
- char * pszValue = (char *) strNextChunk.c_str();
-
- return axtoi( (char *) strNextChunk.substr( 0, iEndOfChunkSize).c_str());
}
void HTTPTransport::
Modified: webservices/axis/trunk/c/src/transport/axis3/HTTPTransport.hpp
URL: http://svn.apache.org/viewvc/webservices/axis/trunk/c/src/transport/axis3/HTTPTransport.hpp?view=diff&rev=508976&r1=508975&r2=508976
==============================================================================
--- webservices/axis/trunk/c/src/transport/axis3/HTTPTransport.hpp (original)
+++ webservices/axis/trunk/c/src/transport/axis3/HTTPTransport.hpp Sun Feb 18 12:19:25 2007
@@ -42,7 +42,8 @@
{
eWaitingForHTTPHeader,
eSOAPMessageIsChunked,
- eSOAPMessageIsNotChunked
+ eSOAPMessageIsNotChunked,
+ eSOAPMessageHasContentLength
} EGETBYTESSTATE;
class HTTPTransport:public SOAPTransport
@@ -70,6 +71,7 @@
void setSessionId( const char * pcSessionId);
const char * getSessionId();
const char * getServiceName ();
+ bool isThereResponseData();
/* HTTPTransport::getProtocol() Is a public method to return the HTTP protocol
* type.
*
@@ -90,7 +92,7 @@
const char * getHTTPProtocol();
const char * getHTTPMethod();
void setHTTPMethod( const char *);
- const char * getHTTPHeaders();
+ const char * generateHTTPHeaders();
void setSocket( unsigned int);
const char * getFirstTransportPropertyKey(bool response);
const char * getNextTransportPropertyKey(bool response);
@@ -107,7 +109,6 @@
const char * getLastChannelError();
protected:
- void processResponseHTTPHeaders() throw (HTTPTransportException);
void processRootMimeBody();
void processMimeHeader();
void processMimeBody();
@@ -115,11 +116,18 @@
int FindTransportPropertyIndex( std::string);
void readHTTPHeader();
void processHTTPHeader();
- void checkHTTPStatusCode();
- bool getNextDataPacket( const char * pcszExceptionMessage);
- int getChunkSize();
- bool copyDataToParserBuffer( char * pcBuffer, int * piSize, int iBytesToCopy);
- int peekChunkLength( std::string& strNextChunk);
+ int getNextDataPacket( const char * pcszExceptionMessage, char *bufferToUse=NULL, int *bufferLen=NULL);
+ int getBytes_MessageIsChunked(char * pcBuffer, int * piSize);
+ int getBytes_MessageIsNotChunked(char * pcBuffer, int * piSize);
+ int getBytes_MessageHasContentLength(char * pcBuffer, int * piSize);
+ int getChunkSize(string::size_type pos=0);
+
+ void resetInputStateMachine();
+
+ unsigned int m_iChunkedDataLeftToConsume;
+ unsigned int m_iNextChunkedDataSize;
+
+
/**
* Adds a cookie to the http header.
*
---------------------------------------------------------------------
To unsubscribe, e-mail: axis-cvs-unsubscribe@ws.apache.org
For additional commands, e-mail: axis-cvs-help@ws.apache.org