You are viewing a plain text version of this content. The canonical link for it is here.
Posted to c-dev@axis.apache.org by "Samisa Abeysinghe (JIRA)" <ax...@ws.apache.org> on 2005/03/11 08:41:52 UTC
[jira] Closed: (AXISCPP-518) Call to method getBytes of the class HTTPTransport never returns a value different from TRANSPORT_IN_PROGRESS
[ http://issues.apache.org/jira/browse/AXISCPP-518?page=history ]
Samisa Abeysinghe closed AXISCPP-518:
-------------------------------------
Resolution: Fixed
Fix Version: 1.5 Final
Applied rest of the changes. Now all requasted changes are in CVS
> Call to method getBytes of the class HTTPTransport never returns a value different from TRANSPORT_IN_PROGRESS
> -------------------------------------------------------------------------------------------------------------
>
> Key: AXISCPP-518
> URL: http://issues.apache.org/jira/browse/AXISCPP-518
> Project: Axis-C++
> Type: Bug
> Components: Transport (axis3)
> Versions: unspecified
> Environment: The bug affects all platforms
> Reporter: Arcangelo Di Balsamo
> Assignee: Samisa Abeysinghe
> Fix For: 1.5 Final
> Attachments: HTTPTransport.cpp, HTTPTransportcpp diff.txt, HTTPTrasportTestClient.zip
>
> I got a bug in the http trasport library ( HTTPTransport). I wrote a simple test client to reproduce the problem (I can send the test program, if you want ).
> The problem is that the method getBytes of the class HTTPTransport never returns a value different from TRANSPORT_IN_PROGRESS. That makes the caller to loop forever.
> I tried to workaround the problem by checking the size of the ruturned buffer in the client, but that led to data truncation.
> The regression suite should be modified too. In fact you should try to use a buffer smaller than the size of the expected response from the server.
> I've already made a fix: the affected module is HTTPTransport.cpp.
> The modified code is :
> /*
> * Copyright 2003-2004 The Apache Software Foundation.
> *
> * Licensed under the Apache License, Version 2.0 (the "License");
> * you may not use this file except in compliance with the License.
> * You may obtain a copy of the License at
> *
> * http://www.apache.org/licenses/LICENSE-2.0
> *
> * Unless required by applicable law or agreed to in writing, software
> * distributed under the License is distributed on an "AS IS" BASIS,
> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> * See the License for the specific language governing permissions and
> * limitations under the License.
> */
> /*
> * @author Samisa Abeysinghe (sabeysinghe@virtusa.com)
> *
> */
> #ifdef WIN32
> #pragma warning (disable : 4786)
> #pragma warning (disable : 4101)
> #endif
> #include "HTTPTransport.hpp"
> #include <stdio.h>
> #include <iostream>
> /*
> * HTTPTransport constuctor
> */
> HTTPTransport::HTTPTransport ():m_bReopenConnection (false),
> m_strHTTPProtocol ("HTTP/1.1"),
> m_strHTTPMethod ("POST"),
> m_bChunked (false),
> m_bReadPastHTTPHeaders (false),
> m_strProxyHost (""), m_uiProxyPort (0), m_bUseProxy (false),
> m_bMaintainSession (false)
> {
> m_pcEndpointUri = NULL;
> m_pReleaseBufferCallback = 0;
> m_eProtocolType = APTHTTP1_1;
> m_strBytesToSend = "";
> m_strHeaderBytesToSend = "";
> m_iBytesLeft = 0;
> m_iContentLength = 0;
> m_pcReceived = 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_pszRxBuffer = new char [BUF_SIZE];
> #ifdef WIN32
> m_lChannelTimeout = 10;
> #else
> m_lChannelTimeout = 0;
> #endif
> }
> /*
> * HTTPTransport destuctor
> */
> HTTPTransport::~HTTPTransport()
> {
> if( m_pcEndpointUri)
> {
> delete[] m_pcEndpointUri;
> }
> if( m_pChannelFactory)
> {
> delete m_pChannelFactory;
> m_pChannelFactory = 0;
> }
> delete [] m_pszRxBuffer;
> }
> /*
> * HTTPTransport::setEndpointUri( EndpointURI) sets the URI for the message.
> * Everytime the endpoint changes then currently connected channel is closed
> * and a new channel connection is opened.
> *
> * @param EndpointURI - char * to a null terminated string that holds the
> * new URI.
> */
> void HTTPTransport::setEndpointUri( const char * pcEndpointUri) throw (HTTPTransportException)
> {
> bool bUpdateURL = false;
> // Get the current channel URI
> if( m_pActiveChannel != NULL && m_pActiveChannel->getURL())
> {
> // Does the new URI equal the existing channel URI?
> if( strcmp (m_pActiveChannel->getURL (), pcEndpointUri) != 0)
> {
> // There is a new URI.
> bUpdateURL = true;
> }
> }
> else
> {
> bUpdateURL = true;
> }
> // If there is a new URI, then this flag will be set. Depending on whether
> // there is an SSL implementation available, if the new URI is a secure
> // connection, a secure channel will be opened. If an SSL implementation
> // is not available and the URL requires a secure connection then an
> // exception will be thrown.
> if( bUpdateURL)
> {
> if( m_pActiveChannel == NULL)
> {
> m_pActiveChannel = m_pNormalChannel;
> }
> m_pActiveChannel->setURL( pcEndpointUri);
> m_bReopenConnection = true;
> // Check if the new URI requires SSL (denoted by the https prefix).
> if( (m_pActiveChannel->getURLObject()).getProtocol() == URL::https)
> {
> if( m_pSecureChannel != NULL)
> {
> m_pNormalChannel->close();
> m_pActiveChannel = m_pSecureChannel;
> m_pActiveChannel->setURL( pcEndpointUri);
> m_bChannelSecure = true;
> }
> if( !m_bChannelSecure)
> {
> throw HTTPTransportException( CLIENT_TRANSPORT_HAS_NO_SECURE_TRANSPORT_LAYER);
> }
> }
> else
> {
> // URI does not require a secure channel. Delete the existing
> // channel if it is secure and create a new unsecure
> // channel.
> if (m_bChannelSecure)
> {
> if( m_pNormalChannel != NULL)
> {
> m_pSecureChannel->close();
> m_pActiveChannel = m_pNormalChannel;
> m_pActiveChannel->setURL( pcEndpointUri);
> m_bChannelSecure = false;
> }
> if( m_bChannelSecure)
> {
> throw HTTPTransportException( CLIENT_TRANSPORT_HAS_NO_UNSECURE_TRANSPORT_LAYER);
> }
> }
> }
> }
> // Need this code to set the channel timeout. If the timeout was changed
> // before the channel was created, then it may not have the correct timeout.
> // By setting it here, the channel is sure to have the correct timeout value
> // next time the channel is read.
> if( m_pActiveChannel != NULL)
> {
> m_pActiveChannel->setTimeout( m_lChannelTimeout);
> }
> }
> /*
> * HTTPTransport::openConnection().
> */
> int HTTPTransport::openConnection()
> {
> return m_pActiveChannel->open();
> }
> /*
> * HTTPTransport::closeConnection().
> */
> void HTTPTransport::closeConnection()
> {
> // get ready for a new message.
> m_bReadPastHTTPHeaders = false;
> //clear the message buffer in preperation of the next read.
> m_strReceived = "";
> m_iContentLength = 0;
> if( m_pActiveChannel != NULL)
> {
> m_pActiveChannel->close();
> }
> }
> /*
> * HTTPTransport::flushOutput() Is called when the message construction is
> * complete. The message is ready to be 'flushed out' onto the network.
> * Check if the URI has changed. If it has, then need to open a new Channel
> * instance before transmitting the message.
> *
> * @return AXIS_TRANSPORT_STATUS If the method completes successfully, then
> * this will be set to TRANSPORT_FINISHED. Otherwise, an exception will have
> * been thrown.
> */
> AXIS_TRANSPORT_STATUS HTTPTransport::flushOutput() throw (HTTPTransportException)
> {
> if( m_bReopenConnection)
> {
> m_bReopenConnection = false;
> if( m_pActiveChannel->open() != AXIS_SUCCESS)
> {
> int iStringLength = m_pActiveChannel->GetLastErrorMsg().length() + 1;
> const char * pszLastError = new char[iStringLength];
> memcpy( (void *) pszLastError,
> m_pActiveChannel->GetLastErrorMsg().c_str(),
> iStringLength);
> throw HTTPTransportException( CLIENT_TRANSPORT_OPEN_CONNECTION_FAILED,
> (char *) pszLastError);
> }
> }
> // In preperation for sending the message, calculate the size of the message
> // by using the string length method.
> // NB: This calculation may not necessarily be correct when dealing with SSL
> // messages as the length of the encoded message is not necessarily the
> // same as the length of the uncoded message.
> char buff[8];
> sprintf( buff, "%d", m_strBytesToSend.length ());
> this->setTransportProperty ("Content-Length", buff);
> // The header is now complete. The message header and message can now be
> // transmitted.
> try
> {
> *m_pActiveChannel << this->getHTTPHeaders ();
> *m_pActiveChannel << this->m_strBytesToSend.c_str ();
> }
> catch( HTTPTransportException & e)
> {
> throw;
> }
> catch( AxisException & e)
> {
> throw;
> }
> catch(...)
> {
> throw;
> }
> // Empty the bytes to send string.
> m_strBytesToSend = "";
> m_strHeaderBytesToSend = "";
> return TRANSPORT_FINISHED;
> }
> /* HTTPTransport::getHTTPHeaders() Called to retreive the current HTTP header
> * information block that will preceed the SOAP message.
> *
> * @return const char* Pointer to a NULL terminated character string containing
> * the HTTP header block of information.
> */
> const char * HTTPTransport::getHTTPHeaders()
> {
> URL & url = m_pActiveChannel->getURLObject();
> unsigned short uiPort = url.getPort();
> char buff[8];
> m_strHeaderBytesToSend = m_strHTTPMethod + " ";
> m_strHeaderBytesToSend += std::string (url.getResource ()) + " ";
> m_strHeaderBytesToSend += m_strHTTPProtocol + "\r\n";
> m_strHeaderBytesToSend += std::string ("Host: ") + url.getHostName ();
> sprintf (buff, "%u", uiPort);
> m_strHeaderBytesToSend += ":";
> m_strHeaderBytesToSend += buff;
> m_strHeaderBytesToSend += "\r\n";
> m_strHeaderBytesToSend += "Content-Type: text/xml; charset=UTF-8\r\n";
> // Set other HTTP headers
> for (unsigned int i = 0; i < m_vHTTPHeaders.size (); i++)
> {
> m_strHeaderBytesToSend += m_vHTTPHeaders[i].first;
> m_strHeaderBytesToSend += ": ";
> m_strHeaderBytesToSend += m_vHTTPHeaders[i].second;
> m_strHeaderBytesToSend += "\r\n";
> }
> // Set session cookie
> if (m_bMaintainSession && (m_strSessionKey.size () > 0))
> {
> m_strHeaderBytesToSend += "Cookie";
> m_strHeaderBytesToSend += ": ";
> m_strHeaderBytesToSend += m_strSessionKey;
> m_strHeaderBytesToSend += "\r\n";
> }
> m_strHeaderBytesToSend += "\r\n";
> return m_strHeaderBytesToSend.c_str ();
> }
> /* HTTPTransport::getHTTPMethod() Is a public method that gets the HTTP method
> * (i.e. GET or POST) that will be part of the HTTP header block.
> *
> * @return const char* Pointer to a NULL terminated character string containing
> * the HTTP method.
> */
> const char * HTTPTransport::getHTTPMethod()
> {
> return m_strHTTPMethod.c_str ();
> }
> /* HTTPTransport::setHTTPMethod( Method) Is a public method that sets the HTTP
> * method (i.e. POST or GET) that will be part of the HTTP header block.
> *
> * @param const char* Pointer to a NULL terminated character string containing
> * the new HTTP method.
> */
> void HTTPTransport::setHTTPMethod( const char *cpMethod)
> {
> m_strHTTPMethod = std::string( cpMethod);
> }
> /* HTTPTransport::sendBytes( SendBuffer, BufferId) Is a public method that
> * concatinates the new send buffer to the bytes to send string. This message
> * will only be sent when a flush buffer is received.
> *
> * @param const char* SendBufer - Pointer to a NULL terminated character string
> * containing all or some of the transmission message.
> * @param const void* BufferId - Pointer. This parameter is ignored.
> *
> * @return AXIS_TRANSPORT_STATUS Value to a status value (currently it will
> * always be TRANSPORT_IN_PROGRESS).
> */
> AXIS_TRANSPORT_STATUS HTTPTransport::sendBytes( const char *pcSendBuffer, const void *pBufferId)
> {
> m_strBytesToSend += std::string (pcSendBuffer);
> return TRANSPORT_IN_PROGRESS;
> }
> /* HTTPTransport::getBytes( ReceiveBuffer, Size) Is a public method that will
> * receive the synchronous reply to the sent message.
> *
> * @param const char* ReceiveBuffer - Pointer to a character string that on
> * return will containing all or part of the received message.
> * @param int* Size - Pointer to an integer value that on return will contain
> * the length of the received message.
> *
> * @return AXIS_TRANSPORT_STATUS Value to the status o message reception
> * (TRANSPORT_FINISHED or TRANSPORT_IN_PROGRESS).
> */
> AXIS_TRANSPORT_STATUS HTTPTransport::getBytes( char *pcBuffer, int *pSize) throw (AxisException, HTTPTransportException)
> {
> if (0 >= m_iBytesLeft)
> {
> try
> {
> m_pszRxBuffer [0] = '\0';
> *m_pActiveChannel >> m_pszRxBuffer;
> m_strReceived = m_pszRxBuffer;
> if( !m_bReadPastHTTPHeaders)
> {
> unsigned int start = std::string::npos;
> do
> {
> do
> {
> if (m_strReceived.find( "\r\n\r\n") == std::string::npos)
> {
> m_pszRxBuffer [0] = '\0';
> *m_pActiveChannel >> m_pszRxBuffer;
> m_strReceived += m_pszRxBuffer;
> }
> } while( m_strReceived.find( "\r\n\r\n") == std::string::npos);
> if( m_strReceived.find ("HTTP") == std::string::npos)
> {
> // Most probably what we read was left overs from earlier reads
> // Skip this \r\n\r\n
> m_strReceived = m_strReceived.substr( m_strReceived.find( "\r\n\r\n") + 4);
> do
> {
> if( m_strReceived.find( "\r\n\r\n") == std::string::npos)
> {
> m_pszRxBuffer [0] = '\0';
> *m_pActiveChannel >> m_pszRxBuffer;
> m_strReceived += m_pszRxBuffer;
> }
> } while( m_strReceived.find( "\r\n\r\n") == std::string::npos);
> // now this must contain HTTP. Else there is a conent error.
> }
> //now we have found the end of headers
> m_bReadPastHTTPHeaders = true;
> unsigned int pos = 0;
> // Look for content lenght
> if( (pos = m_strReceived.find( "Content-Length: ")) != std::string::npos)
> {
> m_iContentLength = atoi( m_strReceived.substr( pos + strlen( "Content-Length: "),
> m_strReceived.find( "\n", pos)).c_str());
> }
> // Check if the message is chunked
> if( (pos = m_strReceived.find( "Transfer-Encoding: chunked")) != std::string::npos)
> {
> m_bChunked = true;
> }
> else
> {
> m_bChunked = false;
> }
> // check if there is HTTP header. If not, there must be an error and
> // will be detected by processResponseHTTPHeaders()
> // However, must make sure that the left overs from eatlier reads
> // do not appear before HTTP/1.x
> start = m_strReceived.find( "HTTP");
> if( start == std::string::npos)
> {
> start = 0;
> }
> // Extract HTTP headers and process them
> m_strResponseHTTPHeaders = m_strReceived.substr( start,
> m_strReceived.find( "\r\n\r\n") + 2 - start);
> processResponseHTTPHeaders();
> if( m_iResponseHTTPStatusCode == 100)
> {
> // Samisa: We found Continue. Keep on reading and processing headers
> // till we get a HTTP code other than 100
> // Here it is assumed that the whole of the request is already sent
> m_pszRxBuffer [0] = '\0';
> *m_pActiveChannel >> m_pszRxBuffer;
> m_strReceived = m_pszRxBuffer;
> }
> } while( m_iResponseHTTPStatusCode == 100);
> if ( m_iResponseHTTPStatusCode != 500 &&
> ( m_iResponseHTTPStatusCode < 200 || m_iResponseHTTPStatusCode >= 300 ))
> {
> throw HTTPTransportException( SERVER_TRANSPORT_HTTP_EXCEPTION,
> const_cast <char *> (m_strResponseHTTPStatusMessage.c_str()));
> }
> // Done with HTTP headers, get payload
> m_strReceived = m_strReceived.substr( m_strReceived.find( "\r\n\r\n", start) + 4);
> }
> // Read past headers. Deal with payload
> // make sure we have a message with some content
> if( m_strReceived.length () == 0)
> {
> m_pszRxBuffer [0] = '\0';
> *m_pActiveChannel >> m_pszRxBuffer;
> m_strReceived = m_pszRxBuffer;
> }
> if( m_strReceived.length () > 0)
> {
> if( m_bChunked && m_iContentLength < 1) // Read first chunk
> {
> /*
> *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
> */
> // firstly read in the chunk size line.
> //There might be chunk extensions in there too but we may not need them
> unsigned int endOfChunkData = m_strReceived.find( "\r\n");
> // make sure we have read at least some part of the message
> if( endOfChunkData == std::string::npos)
> {
> do
> {
> m_pszRxBuffer [0] = '\0';
> *m_pActiveChannel >> m_pszRxBuffer;
> m_strReceived = m_pszRxBuffer;
> endOfChunkData = m_strReceived.find( "\r\n");
> } while( endOfChunkData == std::string::npos);
> }
> int endOfChunkSize = endOfChunkData;
> // 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, endOfChunkData).find( "(") != string::npos)
> {
> endOfChunkSize = m_strReceived.find( "(");
> }
> // convert the hex String into the length of the chunk
> m_iContentLength = axtoi( (char *) m_strReceived.substr( 0, endOfChunkSize).c_str());
> // if the chunk size is zero then we have reached the footer
> // If we have reached the footer then we can throw it away because we don't need it
> if( m_iContentLength > 0)
> {
> // now get the chunk without the CRLF
> // check if we have read past chunk length
> if( m_strReceived.length() >= (endOfChunkData + 2 + m_iContentLength))
> {
> m_strReceived = m_strReceived.substr( endOfChunkData + 2, m_iContentLength);
> }
> else // we have read lesser than chunk length
> {
> m_strReceived = m_strReceived.substr( endOfChunkData + 2);
> }
> /* We have received part of chunk data. If received payload
> * is a mime struct, process it
> */
> if( m_bMimeTrue)
> {
> processRootMimeBody();
> }
> }
> else
> {
> m_strReceived = "";
> }
> }
> else if( m_bChunked) // read continued portions of a chunk
> {
> // Samisa - NOTE: It looks as if there is some logic duplication
> // in this block, where we read continued chunks and the block
> // above, where we read the first chunk. However, there are slight
> // logical differences here, and that is necessary to enable the
> // pull model used by the parser - this logic makes pulling more
> // efficient (30th Sept 2004)
> if( m_strReceived.length () >= m_iContentLength) // We have reached end of current chunk
> {
> // Get remainder of current chunk
> std::string strTemp = m_strReceived.substr( 0, m_iContentLength);
> // Start looking for the next chunk
> // The format we are expecting here is:
> // <previous chunk>\r\n<chunk size>\r\n<next chunk>
> unsigned int endOfChunkData = m_strReceived.find( "\r\n");
> // Make sure that we have the found the end of previous chunk
> while( endOfChunkData == std::string::npos)
> {
> m_pszRxBuffer [0] = '\0';
> *m_pActiveChannel >> m_pszRxBuffer;
> m_strReceived += m_pszRxBuffer;
> endOfChunkData = m_strReceived.find( "\r\n");
> }
> m_strReceived = m_strReceived.substr( endOfChunkData + 2); // Skip end of previous chunk
> endOfChunkData = m_strReceived.find( "\r\n"); // Locate the start of next chunk
> // Make sure that we have the starting line of next chunk
> while( endOfChunkData == std::string::npos)
> {
> m_pszRxBuffer [0] = '\0';
> *m_pActiveChannel >> m_pszRxBuffer;
> m_strReceived += m_pszRxBuffer;
> endOfChunkData = m_strReceived.find( "\r\n");
> }
> int endOfChunkSize = endOfChunkData;
> // look to see if there are any extensions - these are put in brackets so look for those
> if (m_strReceived.substr (0, endOfChunkData).find ("(") != string::npos)
> {
> endOfChunkSize = m_strReceived.find ("(");
> }
> // convert the hex String into the length of the chunk
> int iTempContentLength = axtoi( (char *) m_strReceived.substr( 0, endOfChunkSize).c_str());
> // if the chunk size is zero then we have reached the footer
> // If we have reached the footer then we can throw it away because we don't need it
> if( iTempContentLength > 0)
> {
> // Update the content lenght to be remainde of previous chunk and lenght of new chunk
> m_iContentLength += iTempContentLength;
> // now get the chunk without the CRLF
> // check if we have read past chunk length
> if( m_strReceived.length() >= (endOfChunkData + 2 + iTempContentLength))
> {
> m_strReceived = m_strReceived.substr( endOfChunkData + 2, iTempContentLength);
> }
> else
> {
> m_strReceived = m_strReceived.substr( endOfChunkData + 2);
> }
> /* We have received part of chunk data. If received payload
> * is a mime struct, process it
> */
> if( m_bMimeTrue)
> {
> processRootMimeBody();
> }
> }
> else
> {
> m_strReceived = "";
> }
> // Append the data of new chunk to data from previous chunk
> m_strReceived = strTemp + m_strReceived;
> } // End of if (m_strReceived.length() >= m_iContentLength)
> // If we have not reached end of current chunk, nothing to be done
> }
> else // Not chunked
> {
> //nothing to do here
> /* We have received part of chunk data. If received payload
> * is a mime struct, process it
> */
> if( m_bMimeTrue)
> {
> processRootMimeBody();
> }
> }
> }
> m_pcReceived = m_strReceived.c_str();
> if( m_pcReceived)
> {
> m_iBytesLeft = strlen( m_pcReceived);
> }
> else
> {
> throw HTTPTransportException( SERVER_TRANSPORT_BUFFER_EMPTY, "Recieved null");
> }
> m_iContentLength -= m_iBytesLeft;
> }
> catch( HTTPTransportException & e)
> {
> throw;
> }
> catch( AxisException & e)
> {
> throw;
> }
> catch(...)
> {
> throw;
> }
> }
> if (( m_pcReceived) && (*m_pcReceived))
> {
> int iToCopy = (*pSize < m_iBytesLeft) ? *pSize : m_iBytesLeft;
> strncpy( pcBuffer, m_pcReceived, iToCopy);
> m_iBytesLeft -= iToCopy;
> m_pcReceived += iToCopy;
> *pSize = iToCopy;
> return TRANSPORT_IN_PROGRESS;
> }
> else
> {
> m_bReadPastHTTPHeaders = false; // get ready for a new message
> m_strReceived = ""; //clear the message buffer in preperation of the next read
> return TRANSPORT_FINISHED;
> }
> }
> /* HTTPTransport::setTransportProperty( Type, Value) Is an overloaded public
> * method used to set a HTTP transport or SSL implementation property.
> *
> * @param AXIS_TRANSPORT_INFORMATION_TYPE Type is an enumerated type containing
> * the type of information to be stored in either the HTTP Header or SSL
> * implementation settings.
> * @param const char* Value is a NULL terminated character string containing
> * the value associated with the type.
> */
> void HTTPTransport::setTransportProperty( AXIS_TRANSPORT_INFORMATION_TYPE type, const char *value) throw (HTTPTransportException)
> {
> const char *key = NULL;
> switch (type)
> {
> case SOAPACTION_HEADER:
> {
> key = "SOAPAction";
> break;
> }
> case SERVICE_URI: // need to set ?
> {
> break;
> }
> case OPERATION_NAME: // need to set ?
> {
> break;
> }
> case SOAP_MESSAGE_LENGTH:
> {
> key = "Content-Length"; // this Axis transport handles only HTTP
> break;
> }
> case TRANSPORT_PROPERTIES:
> {
> m_pActiveChannel->setTransportProperty( type, value);
> break;
> }
> case SECURE_PROPERTIES:
> {
> m_pActiveChannel->setSecureProperties( value);
> break;
> }
> case CHANNEL_HTTP_DLL_NAME:
> {
> m_pNormalChannel = m_pChannelFactory->LoadChannelLibrary( UnsecureChannel, value);
> break;
> }
> case CHANNEL_HTTP_SSL_DLL_NAME:
> {
> m_pSecureChannel = m_pChannelFactory->LoadChannelLibrary( SecureChannel, value);
> break;
> }
> default:
> {
> break;
> }
> }
> if( key)
> {
> setTransportProperty( key, value);
> }
> }
> /* HTTPTransport::setTransportProperty( Key, Value) Is an overloaded public
> * method used to set a HTTP transport or SSL implementation property.
> *
> * @param const char* Key is a NULL terminated character string containing
> * the type of information to be stored in either the HTTP Header or SSL
> * implementation settings.
> * @param const char* Value is a NULL terminated character string containing
> * the value associated with the type.
> */
> void HTTPTransport::setTransportProperty( const char *pcKey, const char *pcValue) throw (HTTPTransportException)
> {
> if( !pcKey || !pcValue) // Samisa - fix for AXISCPP-295. We must check for valid values here.
> {
> return;
> }
> bool b_KeyFound = false;
> if( strcmp( pcKey, "SOAPAction") == 0 || strcmp( pcKey, "Content-Length") == 0)
> {
> std::string strKeyToFind = std::string( pcKey);
> for (unsigned int i = 0; i < m_vHTTPHeaders.size(); i++)
> {
> if (m_vHTTPHeaders[i].first == strKeyToFind)
> {
> m_vHTTPHeaders[i].second = (string) pcValue;
> b_KeyFound = true;
> break;
> }
> }
> }
> if( !b_KeyFound)
> {
> m_vHTTPHeaders.push_back( std::make_pair( (string) pcKey, (string) pcValue));
> }
> }
> /* HTTPTransport::getTransportProperty( Type) Is a public method that will
> * return the HTTP Header/SSL implementation value associated with type.
> *
> * @param AXIS_TRANSPORT_INFORMATION_TYPE Type is an enumerated type containing
> * the type of information to be retrieved in either the HTTP Header or SSL
> * implementation settings.
> *
> * @return const char* Value is a NULL terminated character string containing
> * the value associated with the type.
> */
> const char * HTTPTransport::getTransportProperty( AXIS_TRANSPORT_INFORMATION_TYPE eType) throw (HTTPTransportException)
> {
> const char *pszPropValue = NULL;
> switch( eType)
> {
> case SOAPACTION_HEADER:
> {
> int iIndex = FindTransportPropertyIndex( "SOAPAction");
> if (iIndex > -1)
> {
> pszPropValue = m_vHTTPHeaders[iIndex].second.c_str();
> }
> break;
> }
> case SERVICE_URI:
> {
> break;
> }
> case OPERATION_NAME:
> {
> break;
> }
> case SOAP_MESSAGE_LENGTH:
> {
> int iIndex = FindTransportPropertyIndex( "Content-Length");
> if (iIndex > -1)
> {
> pszPropValue = m_vHTTPHeaders[iIndex].second.c_str();
> }
> break;
> }
> case TRANSPORT_PROPERTIES:
> case SECURE_PROPERTIES:
> {
> pszPropValue = m_pActiveChannel->getTransportProperty( eType);
> break;
> }
> case CHANNEL_HTTP_SSL_DLL_NAME:
> case CHANNEL_HTTP_DLL_NAME:
> {
> break;
> }
> }
> return pszPropValue;
> }
> /* HTTPTransport::FindTransportPropertyIndex( Key) Is a private method that will
> * return the HTTP Header index associated with Key.
> *
> * @param AXIS_TRANSPORT_INFORMATION_TYPE Key is an enumerated type containing
> * the type of information to be retrieved in either the HTTP Header settings.
> *
> * @return int Index is an index to the key within the HTTP Header list. If
> * the return value is -1, then the key was not found.
> */
> int HTTPTransport::FindTransportPropertyIndex( string sKey)
> {
> bool bKeyFound = false;
> int iIndex = 0;
> do
> {
> if (!m_vHTTPHeaders[iIndex].first.compare( sKey))
> {
> bKeyFound = true;
> }
> else
> {
> iIndex++;
> }
> } while( (unsigned int) iIndex < m_vHTTPHeaders.size() && !bKeyFound);
> if( !bKeyFound)
> {
> iIndex = -1;
> }
> return iIndex;
> }
> /* HTTPTransport::getServiceName() Is a public method to return the HTTP
> * Header service name.
> *
> * @return const char* Value is a NULL terminated character string containing
> * the value associated with the service name.
> */
> const char * HTTPTransport::getServiceName()
> {
> //Assume SOAPAction header to contain service name
> int iIndex = FindTransportPropertyIndex( "SOAPAction");
> if (iIndex > -1)
> {
> return m_vHTTPHeaders[iIndex].second.c_str();
> }
> return NULL;
> }
> AXIS_PROTOCOL_TYPE HTTPTransport::getProtocol()
> {
> return m_eProtocolType;
> }
> int HTTPTransport::setProtocol( AXIS_PROTOCOL_TYPE eProtocol)
> {
> if (eProtocol == APTHTTP1_1 || eProtocol == APTHTTP1_0)
> {
> m_eProtocolType = eProtocol;
> m_strHTTPProtocol = (m_eProtocolType == APTHTTP1_1) ? "HTTP/1.1" : "HTTP/1.0";
> return AXIS_SUCCESS;
> }
> else
> {
> return AXIS_FAIL;
> }
> }
> /**
> * HTTPTransport::getSubProtocol() is a public method that is supposed to
> * return the sub protocol (currently this method always return 0).
> * This method is supposed to return whether it is http GET or POST
> */
> int HTTPTransport::getSubProtocol()
> {
> //TODO
> // for SimpleAxisServer assume POST
> return AXIS_HTTP_POST;
> //return 0;
> }
> /* HTTPTransport::setProxy( Host, Port) Is a public method for setting or
> * updating the proxy for the connection.
> *
> * @param const char* Host is a NULL terminated character string containing the new
> * proxy host.
> * @param unsigned int Port is the new proxy port number.
> */
> void HTTPTransport::setProxy( const char *pcProxyHost, unsigned int uiProxyPort)
> {
> m_strProxyHost = pcProxyHost;
> m_uiProxyPort = uiProxyPort;
> m_bUseProxy = true;
> }
> /* HTTPTransport::setTimeout( Timeout) Is a public method for setting the
> * current maximum timeout period between that can elapse between receiving
> * message parts.
> *
> * @param const long Timeout is a long value in seconds.
> */
> void HTTPTransport::setTimeout( const long lSeconds)
> {
> if( m_pActiveChannel != NULL)
> {
> m_pActiveChannel->setTimeout( lSeconds);
> }
> m_lChannelTimeout = lSeconds;
> }
> /* HTTPTransport::getHTTPProtocol() Is a public method for retrieving the
> * current HTTP protocol settings.
> *
> * @return const char* HTTPProtocol is a NULL terminated character string
> * containing the HTTP protocol.
> */
> const char * HTTPTransport::getHTTPProtocol()
> {
> return m_strHTTPProtocol.c_str ();
> }
> /* axtoi( Hex) Is a private method to convert an ascii hex string to an integer.
> */
> int axtoi( char *pcHexStg)
> {
> int iN = 0; // position in string
> 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
> while( iN < 32)
> {
> if( pcHexStg[iN] == '\0')
> {
> break;
> }
>
> if( pcHexStg[iN] > 0x29 && pcHexStg[iN] < 0x40) //if 0 to 9
> {
> iDigit[iN] = pcHexStg[iN] & 0x0f; //convert to int
> }
> else if (pcHexStg[iN] >= 'a' && pcHexStg[iN] <= 'f') //if a to f
> {
> iDigit[iN] = (pcHexStg[iN] & 0x0f) + 9; //convert to int
> }
> else if (pcHexStg[iN] >= 'A' && pcHexStg[iN] <= 'F') //if A to F
> {
> iDigit[iN] = (pcHexStg[iN] & 0x0f) + 9; //convert to int
> }
> else
> {
> break;
> }
> iN++;
> }
> iCount = iN;
> iM = iN - 1;
> iN = 0;
> 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
> intValue = intValue | (iDigit[iN] << (iM << 2));
> iM--; // adjust the position to set
> iN++; // next digit to process
> }
> return intValue;
> }
> /* HTTPTransport::processResponseHTTPHeaders() Is a public method used to
> * parse the HTTP header of the response message.
> */
> void HTTPTransport::processResponseHTTPHeaders() throw (HTTPTransportException)
> {
> unsigned int iPosition = std::string::npos;
> unsigned int iStartPosition = iPosition;
> if( (iPosition = m_strResponseHTTPHeaders.find( "HTTP")) != std::string::npos)
> {
> m_strResponseHTTPProtocol = m_strResponseHTTPHeaders.substr( iPosition, strlen( "HTTP/1.x"));
> iPosition += strlen( "HTTP/1.x");
> while( m_strResponseHTTPHeaders.substr()[iPosition] == ' ')
> {
> iPosition++;
> }
> iStartPosition = iPosition;
> while( m_strResponseHTTPHeaders.substr()[iPosition] != ' ')
> {
> iPosition++;
> }
> std::string strResponseHTTPStatusCode = m_strResponseHTTPHeaders.substr( iStartPosition,
> iPosition - iStartPosition);
> m_iResponseHTTPStatusCode = atoi( strResponseHTTPStatusCode.c_str());
> iStartPosition = ++iPosition;
> iPosition = m_strResponseHTTPHeaders.find( "\n");
> m_strResponseHTTPStatusMessage = m_strResponseHTTPHeaders.substr( iStartPosition,
> iPosition - iStartPosition - 1);
> // reached the end of the first line
> iStartPosition = m_strResponseHTTPHeaders.find( "\n");
> iStartPosition++;
> // read header fields and add to vector
> do
> {
> m_strResponseHTTPHeaders = m_strResponseHTTPHeaders.substr( iStartPosition);
> iPosition = m_strResponseHTTPHeaders.find( "\n");
> if( iPosition == std::string::npos)
> {
> break;
> }
> std::string strHeaderLine = m_strResponseHTTPHeaders.substr( 0, iPosition);
> unsigned int iSeperator = strHeaderLine.find(":");
> if( iSeperator == std::string::npos)
> {
> break;
> }
> iStartPosition = iPosition + 1;
> string key = strHeaderLine.substr( 0, iSeperator);
> string value = strHeaderLine.substr( iSeperator + 1,
> strHeaderLine.length () - iSeperator - 1 - 1);
> m_vResponseHTTPHeaders.push_back( std::make_pair( key, value));
> // if HTTP/1.0 we have to always close the 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")
> {
> m_bReopenConnection = true;
> }
> // For both HTTP/1.0 and HTTP/1.1,
> // We need to keep the connection if we have 'Connection: Keep-Alive'
> if( key == "Connection" && value == " Keep-Alive")
> {
> m_bReopenConnection = false;
> }
> // Look for cookies
> if( m_bMaintainSession && !(m_strSessionKey.size() > 0))
> {
> if( key == "Set-Cookie")
> {
> m_strSessionKey = value;
> // Spec syntax : Set-Cookie: NAME=VALUE; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure
> // This code assumes it to be : Set-Cookie: NAME=VALUE; Anything_else
> // And discards stuff after first ';'
> // This is the same assumption used in Axis Java
> unsigned long ulKeyEndsAt = m_strSessionKey.find( ";");
>
> if( ulKeyEndsAt != std::string::npos)
> {
> m_strSessionKey = m_strSessionKey.substr( 0, ulKeyEndsAt);
> }
> }
> }
> /* If Content-Type: Multipart/Related; boundary=<MIME_boundary>; type=text/xml;
> start="<content id>" */
> if( key == "Content-Type")
> {
> m_strContentType = value;
>
> unsigned long ulMimePos = m_strContentType.find( ";");
> std::string strTypePart;
> if( ulMimePos != std::string::npos)
> {
> strTypePart = m_strContentType.substr( 1, ulMimePos - 1);
> }
>
> if( "Multipart/Related" == strTypePart)
> {
> m_bMimeTrue = true;
> m_strContentType = m_strContentType.substr( ulMimePos + 1,
> m_strContentType.length());
> ulMimePos = m_strContentType.find( "boundary=");
> m_strMimeBoundary = m_strContentType.substr( ulMimePos);
> ulMimePos = m_strMimeBoundary.find( ";");
> m_strMimeBoundary = m_strMimeBoundary.substr( 9, ulMimePos - 9);
> ulMimePos = m_strContentType.find( "type=");
> m_strMimeType = m_strContentType.substr( ulMimePos);
> ulMimePos = m_strMimeType.find( ";");
> m_strMimeType = m_strMimeType.substr( 5, ulMimePos - 5);
> ulMimePos = m_strContentType.find( "start=");
> m_strMimeStart = m_strContentType.substr( ulMimePos);
> ulMimePos = m_strMimeStart.find( ";");
> m_strMimeStart = m_strMimeStart.substr( 6, ulMimePos - 6);
> }
> }
> } while( iPosition != std::string::npos);
> }
> else
> {
> throw HTTPTransportException( SERVER_TRANSPORT_UNKNOWN_HTTP_RESPONSE,
> "Protocol is not HTTP.");
> }
> }
> /* HTTPTransport::processRootMimeBody() Is a public method used to
> * parse the mime attachments.
> */
> void HTTPTransport::processRootMimeBody()
> {
> if( false == m_bReadPastRootMimeHeader)
> {
> do
> {
> if( m_strReceived.find( "\r\n\r\n") == std::string::npos)
> {
> m_pszRxBuffer [0] = '\0';
> *m_pActiveChannel >> m_pszRxBuffer;
> m_strReceived += m_pszRxBuffer;
> }
> } while( m_strReceived.find( "\r\n\r\n") == std::string::npos);
> //now we have found the end of root mime header
> m_bReadPastRootMimeHeader = true;
> //processMimeHeader(); For the time being we don't process this
> // Done with root mime body headers, get rest of the payload
> // which contain the soap message
> m_strReceived = m_strReceived.substr( m_strReceived.find( "\r\n\r\n") + 4);
>
> unsigned int intMimeTemp = m_strReceived.find( m_strMimeBoundary);
> if (intMimeTemp != std::string::npos)
> {
> m_strReceived = m_strReceived.substr( 0, intMimeTemp);
> m_strMimeReceived = m_strReceived.substr( intMimeTemp);
> /* Using m_strMimeReceived will be
> * continued when getAttachment is called.
> */
> m_bMimeTrue = false;
> }
> }
> else
> {
> unsigned int intMimeTemp = m_strReceived.find( m_strMimeBoundary);
>
> if( intMimeTemp != std::string::npos)
> {
> m_strReceived = m_strReceived.substr( 0, intMimeTemp);
> m_strMimeReceived = m_strReceived.substr( intMimeTemp);
> /* Using m_strMimeReceived will be
> * continued when getAttachment is called.
> */
> m_bMimeTrue = false;
> }
> return;
> }
> }
> /* HTTPTransport::processMimeHeaders() Is a public method used to
> * parse the Mime headers of the response message.
> */
> void HTTPTransport::processMimeHeader()
> {
> unsigned int pos = 0;
> unsigned int temppos = 0;
> // Look for content lenght
> if( (pos = m_strMimeReceived.find( "Content-Type: ")) != std::string::npos)
> {
> m_strMimeContentType = m_strMimeReceived.substr( pos + strlen( "Content-Type: "),
> m_strMimeReceived.find( "\n", pos));
> pos = m_strMimeContentType.find( ";");
> temppos = m_strMimeContentType.find( "\r\n");
> if( pos < temppos)
> {
> m_strMimeContentType = m_strMimeContentType.substr( 0, pos);
> }
> else
> {
> m_strMimeContentType = m_strMimeContentType.substr( 0, temppos);
> }
> }
> // Look for mime root body's content transfer encoding
> if( (pos = m_strMimeReceived.find( "Content-Transfer-Encoding: ")) != std::string::npos)
> {
> m_strMimeContentTransferEncoding = m_strMimeReceived.substr( pos + strlen( "Content-Transfer-Encoding: "),
> m_strMimeReceived.find( "\n", pos));
> temppos = m_strMimeContentTransferEncoding.find( "\r\n");
> m_strMimeContentTransferEncoding = m_strMimeContentTransferEncoding.substr( 0, temppos);
> }
> // Look for mime root body's content id
> if( (pos = m_strMimeReceived.find( "Content-ID: ")) != std::string::npos)
> {
> m_strMimeContentID = m_strMimeReceived.substr( pos + strlen( "Content-ID: "),
> m_strMimeReceived.find( "\n", pos));
> temppos = m_strMimeContentID.find( "\r\n");
> m_strMimeContentID = m_strMimeContentID.substr( 0, temppos);
> }
> // Look for mime root body's content location
> if( (pos = m_strMimeReceived.find( "Content-Location: ")) != std::string::npos)
> {
> m_strMimeContentLocation = atoi( m_strMimeReceived.substr( pos + strlen( "Content-Location: "),
> m_strMimeReceived.find( "\n", pos)).c_str());
> temppos = m_strMimeContentLocation.find( "\r\n");
> m_strMimeContentLocation = m_strMimeContentLocation.substr( 0, temppos);
> }
> }
> void HTTPTransport::processMimeBody ()
> {
> }
> void HTTPTransport::getAttachment( char * pStrAttachment, int * pIntSize, int intAttachmentId)
> {
> m_pszRxBuffer [0] = '\0';
> *m_pActiveChannel >> m_pszRxBuffer;
> m_strMimeReceived += m_pszRxBuffer;
> do
> {
> if( m_strMimeReceived.find( "\r\n\r\n") == std::string::npos)
> {
> m_pszRxBuffer [0] = '\0';
> *m_pActiveChannel >> m_pszRxBuffer;
> m_strMimeReceived += m_pszRxBuffer;
> }
> } while( m_strMimeReceived.find( "\r\n\r\n") == std::string::npos);
> //now we have found the end of next mime header
> processMimeHeader();
> m_strMimeReceived = m_strMimeReceived.substr( m_strMimeReceived.find( "\r\n\r\n"));
> processMimeBody();
> }
> void HTTPTransport::setSocket( unsigned int uiNewSocket)
> {
> m_pActiveChannel->setSocket( uiNewSocket);
> }
> const char * HTTPTransport::getTransportProperty( const char * pcKey) throw (HTTPTransportException)
> {
> std::string strKeyToFind = std::string( pcKey);
> for( unsigned int i = 0; i < m_vResponseHTTPHeaders.size(); i++)
> {
> if( m_vResponseHTTPHeaders[i].first == strKeyToFind)
> {
> return ((string) m_vResponseHTTPHeaders[i].second).c_str();
> }
> }
> return NULL;
> }
> const char * HTTPTransport::getFirstTransportPropertyKey()
> {
> m_viCurrentHeader = m_vHTTPHeaders.begin ();
> if( m_viCurrentHeader == m_vHTTPHeaders.end())
> {
> return NULL;
> }
> else
> {
> return (*m_viCurrentHeader).first.c_str();
> }
> }
> const char * HTTPTransport::getNextTransportPropertyKey()
> {
> //already at the end?
> if( m_viCurrentHeader == m_vHTTPHeaders.end())
> {
> return NULL;
> }
> m_viCurrentHeader++;
> if( m_viCurrentHeader == m_vHTTPHeaders.end())
> {
> return NULL;
> }
> else
> {
> return (*m_viCurrentHeader).first.c_str();
> }
> }
> const char * HTTPTransport::getCurrentTransportPropertyKey()
> {
> if( m_viCurrentHeader == m_vHTTPHeaders.end())
> {
> return NULL;
> }
> else
> {
> return (*m_viCurrentHeader).first.c_str();
> }
> }
> const char * HTTPTransport::getCurrentTransportPropertyValue()
> {
> if( m_viCurrentHeader == m_vHTTPHeaders.end())
> {
> return NULL;
> }
> else
> {
> return (*m_viCurrentHeader).second.c_str();
> }
> }
> void HTTPTransport::deleteCurrentTransportProperty()
> {
> if( m_viCurrentHeader != m_vHTTPHeaders.end())
> {
> m_vHTTPHeaders.erase( m_viCurrentHeader);
> }
> }
> void HTTPTransport::deleteTransportProperty (char *pcKey, unsigned int uiOccurance)
> {
> vector < std::pair < std::string,
> std::string > >::iterator currentHeader = m_vHTTPHeaders.begin();
> unsigned int uiCount = 1;
> while( currentHeader != m_vHTTPHeaders.end() && uiCount <= uiOccurance)
> {
> if( strcmp( pcKey, (*currentHeader).first.c_str()) == 0)
> {
> if( uiCount == uiOccurance)
> {
> m_vHTTPHeaders.erase( currentHeader);
> break;
> }
>
> uiCount++;
> }
>
> currentHeader++;
> }
> }
> void HTTPTransport::setMaintainSession( bool bSession)
> {
> m_bMaintainSession = bSession;
> }
> void HTTPTransport::setSessionId( const char * pcSessionId)
> {
> m_strSessionKey = std::string (pcSessionId);
> }
> const char * HTTPTransport::getSessionId()
> {
> return m_strSessionKey.c_str();
> }
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://issues.apache.org/jira/secure/Administrators.jspa
-
If you want more information on JIRA, or have a bug to report see:
http://www.atlassian.com/software/jira