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 sa...@apache.org on 2004/09/21 05:52:24 UTC
cvs commit: ws-axis/c/src/transport/axis2 Axis2Transport.cpp Axis2Transport.h AxisTransportException.cpp AxisTransportException.h Channel.cpp Channel.h Makefile.am Platform.h URL.cpp URL.h
samisa 2004/09/20 20:52:24
Added: c/src/transport/axis2 Axis2Transport.cpp Axis2Transport.h
AxisTransportException.cpp AxisTransportException.h
Channel.cpp Channel.h Makefile.am Platform.h
URL.cpp URL.h
Log:
New trasport with cyclic referances to classes removed and
lesser number of classes to help maintanace.
There has been some logic changes to improve performance.
Revision Changes Path
1.1 ws-axis/c/src/transport/axis2/Axis2Transport.cpp
Index: Axis2Transport.cpp
===================================================================
/*
* 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 "Axis2Transport.h"
#include <stdio.h>
#include <iostream>
Axis2Transport::Axis2Transport()
: m_bURIChanged( false ),
m_strHTTPProtocol("HTTP/1.1"), m_strHTTPMethod("POST"),
m_bChunked(false), m_bReadPastHTTPHeaders(false) ,m_strProxyHost( "" ), m_uiProxyPort( 0 ), m_bUseProxy( false )
{
m_pcEndpointUri = NULL;
m_pReleaseBufferCallback = 0;
m_strBytesToSend = "";
m_iBytesLeft = 0;
m_iContentLength = 0;
m_pcReceived = 0;
}
Axis2Transport::~Axis2Transport()
{
if ( m_pcEndpointUri )
free( m_pcEndpointUri );
}
void Axis2Transport::setEndpointUri( const char* pcEndpointUri )
{
if ( m_Channel.getURL() )
if ( strcmp( m_Channel.getURL(), pcEndpointUri ) == 0 )
return ; // no change to the current URI; hence do nothing
// we have a new URI
m_Channel.setURL( pcEndpointUri );
m_bURIChanged = true;
}
int Axis2Transport::openConnection()
{
//Samisa: I wonder whether this should be a SOAPTransport API call.
//It should not be the job of the upper layers to tell the trasport
//to open and close connections. Rather the transport should determine
//when to do that, when sendBytes is called.
return AXIS_SUCCESS;
}
void Axis2Transport::closeConnection()
{
m_bReadPastHTTPHeaders = false; // get ready for a new message
m_strReceived = ""; //clear the message buffer in preperation of the next read
m_iContentLength = 0;
}
AXIS_TRANSPORT_STATUS Axis2Transport::flushOutput()
{
if ( m_bURIChanged )
m_Channel.open();
char buff[ 8 ];
sprintf( buff, "%d", m_strBytesToSend.length() );
this->setTransportProperty( "Content-Length" , buff );
try
{
m_Channel << this->getHTTPHeaders();
m_Channel << this->m_strBytesToSend.c_str();
}
catch(AxisTransportException& e)
{
throw;
}
catch(AxisException& e)
{
throw;
}
catch(...)
{
throw;
}
m_strBytesToSend = "";
return TRANSPORT_FINISHED;
}
const char* Axis2Transport::getHTTPHeaders()
{
URL& url = m_Channel.getURLObject();
std::string strHTTPHeaders = m_strHTTPMethod + " ";
//strHTTPHeaders += std::string(url.getURL()) + " ";
strHTTPHeaders += std::string(url.getResource()) + " ";
strHTTPHeaders += m_strHTTPProtocol + "\r\n";
strHTTPHeaders += std::string("Host: ") + url.getHostName();
unsigned short port = url.getPort ();
char buff[8];
sprintf (buff, "%u", port);
strHTTPHeaders += ":";
strHTTPHeaders += buff;
strHTTPHeaders += "\r\n";
strHTTPHeaders += "Content-Type: text/xml; charset=UTF-8\r\n";
// Set other HTTP headers
for (unsigned int i = 0; i < m_vHTTPHeaders.size (); i++)
{
strHTTPHeaders += m_vHTTPHeaders[i].first;
strHTTPHeaders += ": ";
strHTTPHeaders += m_vHTTPHeaders[i].second;
strHTTPHeaders += "\r\n";
}
strHTTPHeaders += "\r\n";
return strHTTPHeaders.c_str();
}
const char* Axis2Transport::getHTTPMethod()
{
return m_strHTTPMethod.c_str();
}
void Axis2Transport::setHTTPMethod(const char* cpMethod)
{
m_strHTTPMethod = std::string(cpMethod);
}
AXIS_TRANSPORT_STATUS Axis2Transport::sendBytes( const char* pcSendBuffer,
const void* pBufferId )
{
m_strBytesToSend += std::string( pcSendBuffer );
return TRANSPORT_IN_PROGRESS;
}
AXIS_TRANSPORT_STATUS Axis2Transport::getBytes( char* pcBuffer, int* pSize )
{
if ( 0 <= m_iBytesLeft )
{
try
{
m_Channel >> m_strReceived;
if (!m_bReadPastHTTPHeaders)
{
do
{
if (m_strReceived.find ("\r\n\r\n") == std::string::npos)
m_Channel >> m_strReceived; // Assume non blocking here
}
while (m_strReceived.find ("\r\n\r\n") == std::string::npos);
//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;
}
// Skip headers and get payload
m_strReceived = m_strReceived.substr(m_strReceived.find ("\r\n\r\n") + 4 );
}
// Read past headers. Deal with payload
// make sure we have a message with some content
if (m_strReceived.length() == 0)
m_Channel >> m_strReceived;
if (m_bChunked && m_iContentLength < 1 )
{
/*
*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_Channel >> m_strReceived;
endOfChunkData = m_strReceived.find ("\r\n");
}while (endOfChunkData == std::string::npos);
}
int endOfChunkSize = endOfChunkData;
// now get just 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)
{
// there are extensions so just get the chunk dataSize
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
m_strReceived = m_strReceived.substr (endOfChunkData + 2);//, chunkSize);
// OK, now we have the chunk, we need to read in more chunks from the channel.
// we must have more chunks because we haven't reached the ")" which signifies the end of the
// now move the unparsed chunk along avoiding the 2 bytes of CRLF.
//unParsedChunks = unParsedChunks.substr (endOfChunkData + 2 + chunkSize + 2);
}
else
{
m_strReceived = "";
}
}
else // Not chunked
{
//nothing to do here
}
//printf( "cont len = %ld, read = %ld", m_iContentLength, m_strReceived.length());
m_pcReceived = m_strReceived.c_str();
if ( m_pcReceived )
m_iBytesLeft = strlen( m_pcReceived );
else
throw AxisTransportException( SERVER_TRANSPORT_BUFFER_EMPTY, "Reveved null" );
m_iContentLength -= m_iBytesLeft;
}
catch ( AxisTransportException & e )
{
throw;
}
catch ( AxisException & e )
{
throw;
}
catch ( ... )
{
throw;
}
}
if ( 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;
}
}
void Axis2Transport::setTransportProperty
( AXIS_TRANSPORT_INFORMATION_TYPE type, const char* value )
{
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;
default:
;
}
if ( !key )
return ;
setTransportProperty( key, value );
}
void Axis2Transport::setTransportProperty( const char* pcKey, const char* pcValue )
{
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 ) );
}
}
const char* Axis2Transport::getTransportProperty( AXIS_TRANSPORT_INFORMATION_TYPE eType )
{
//TODO
return 0;
}
const char* Axis2Transport::getServiceName()
{
//Assume SOAPAction header to contain service name
for ( unsigned int i = 0; i < m_vHTTPHeaders.size(); i++ )
{
if ( m_vHTTPHeaders[ i ].first == "SOAPAction" )
{
return ((string) m_vHTTPHeaders[ i ].second ).c_str();
}
}
return NULL;
}
AXIS_PROTOCOL_TYPE Axis2Transport::getProtocol()
{
return APTHTTP;
}
/**
* This method is supposed to return whether it is http GET or POST
*/
int Axis2Transport::getSubProtocol()
{
//TODO
return 0;
}
void
Axis2Transport::setProxy( const char* pcProxyHost, unsigned int uiProxyPort )
{
m_strProxyHost = pcProxyHost;
m_uiProxyPort = uiProxyPort;
m_bUseProxy = true;
}
void Axis2Transport::setTimeout( const long lSeconds )
{
m_Channel.setTimeout( lSeconds );
}
const char* Axis2Transport::getHTTPProtocol()
{
return m_strHTTPProtocol.c_str();
}
void Axis2Transport::setHTTPProtocol( int iVersion )
{
switch(iVersion)
{
case 0:
m_strHTTPProtocol = "HTTP/1.0";
break;
case 1:
default:
m_strHTTPProtocol = "HTTP/1.1";
}
}
extern "C"
{
STORAGE_CLASS_INFO
int CreateInstance( SOAPTransport **inst )
{
*inst = new Axis2Transport();
if ( *inst )
{
return AXIS_SUCCESS;
}
return AXIS_FAIL;
}
STORAGE_CLASS_INFO
int DestroyInstance( SOAPTransport * inst )
{
if ( inst )
{
delete inst;
return AXIS_SUCCESS;
}
return AXIS_FAIL;
}
}
extern "C"
{
STORAGE_CLASS_INFO
void initializeLibrary( void )
{
// Do init actions
}
}
extern "C"
{
STORAGE_CLASS_INFO
void uninitializeLibrary( void )
{
// Do uninit actions
}
}
/*
* This converts an ascii hex string to int converter.
*/
int
axtoi (char *hexStg)
{
int
n = 0; // position in string
int
m = 0; // position in digit[] to shift
int
count; // loop index
int
intValue = 0; // integer value of hex string
int
digit[32]; // hold values to convert
while (n < 32)
{
if (hexStg[n] == '\0')
break;
if (hexStg[n] > 0x29 && hexStg[n] < 0x40) //if 0 to 9
digit[n] = hexStg[n] & 0x0f; //convert to int
else if (hexStg[n] >= 'a' && hexStg[n] <= 'f') //if a to f
digit[n] = (hexStg[n] & 0x0f) + 9; //convert to int
else if (hexStg[n] >= 'A' && hexStg[n] <= 'F') //if A to F
digit[n] = (hexStg[n] & 0x0f) + 9; //convert to int
else
break;
n++;
}
count = n;
m = n - 1;
n = 0;
while (n < count)
{
// 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 | (digit[n] << (m << 2));
m--; // adjust the position to set
n++; // next digit to process
}
return (intValue);
}
1.1 ws-axis/c/src/transport/axis2/Axis2Transport.h
Index: Axis2Transport.h
===================================================================
/*
* 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)
*/
#if !defined(_AXIS_AXIS_TRANSPORT_HPP)
#define _AXIS_AXIS_TRANSPORT_HPP
#include "../SOAPTransport.h"
#include "Channel.h"
#include <string>
#include <vector>
AXIS_CPP_NAMESPACE_USE
using namespace std;
int axtoi (char *hexStg);
class Axis2Transport : public SOAPTransport
{
public:
Axis2Transport();
virtual ~Axis2Transport();
/**
* Sets the endpoint URI.
* Keeps track of the changes made to the URI. (Because if the URI changes,
* we cannot reuse the opned socket)
* @param pcEndPointURI End point URI of the service to connect to.
* e.g. http://localhost:8080/axis/services/echo
*/
void setEndpointUri(const char* pcEndpointUri);
int openConnection();
void closeConnection();
AXIS_TRANSPORT_STATUS sendBytes(const char* pcSendBuffer, const void* pBufferId);
void registerReleaseBufferCallback(AXIS_ENGINE_CALLBACK_RELEASE_SEND_BUFFER pFunct)
{ m_pReleaseBufferCallback = pFunct; };
AXIS_TRANSPORT_STATUS getBytes(char* pcBuffer, int* piSize);
void setTransportProperty(AXIS_TRANSPORT_INFORMATION_TYPE eType, const char* pcValue);
const char* getTransportProperty(AXIS_TRANSPORT_INFORMATION_TYPE eType);
void setTransportProperty(const char* pcKey, const char* pcValue);
const char* getTransportProperty(const char* pcKey){return "value";};
void setAttachment(const char* pcAttachmentId, const char* pcAttachment){};
const char* getAttachment(const char* pcAttachmentId){return "value";};
void setSessionId(const char* pcSessionId){};
const char* getSessionId(){return "some session id";};
const char* getServiceName();
AXIS_PROTOCOL_TYPE getProtocol();
int getSubProtocol();
AXIS_TRANSPORT_STATUS flushOutput();
/**
* Set proxy server and port for transport.
*
* @param pcProxyHost Host name of proxy server
* @param uiProxyPort Port of proxy server
*/
void setProxy(const char* pcProxyHost, unsigned int uiProxyPort);
/**
* Set transport timeout.
*
* @param lSeconds Timeout in seconds
*/
void setTimeout(const long lSeconds);
/**
* @return HTTP protocol in use - HTTP/1.1 or HTTP/1.0
*/
const char* getHTTPProtocol();
/**
* Sets the HTTP protocol to be 1.1 or 1.0
* @param iVersion Version to be used
* If 0 HTTP/1.0 would be used, if 1 HTTP/1.1 would be used.
* Default is HTTP1.1
*/
void setHTTPProtocol( int iVersion );
/**
* @return HTTP Method in use - POST, GET etc.
*/
const char* getHTTPMethod();
/**
* Set HTTP Method to use
* @param cpMethod - Possible values POST, GET, etc.
* Only POST is handled correctly at the moment
*/
void setHTTPMethod(const char* cpMethod);
const char* getHTTPHeaders();
private:
/**
* Keeps track of URI changes.
* Set true by setEndpointUri.
* Set false when a socket connection is established with the enpoint.
*/
bool m_bURIChanged;
/**
* Channel used for comminication
*/
Channel m_Channel;
/**
* Message string to be sent.
*/
std::string m_strBytesToSend;
/**
* Vector to hold HTTP header key/value pairs
*/
std::vector< std::pair<std::string, std::string> > m_vHTTPHeaders;
/**
* HTTP protocol (1.1 or 1.0). Default is HTTP/1.1
*/
std::string m_strHTTPProtocol;
/**
* HTTP method (POST, GET etc.) - Only support POST at the moment
*/
std::string m_strHTTPMethod;
/**
* Bytes left in the payload buffer to be read
*/
int m_iBytesLeft;
/**
* Payload lenght
*/
int m_iContentLength;
/**
* Is the message chunked
*/
int m_bChunked;
/**
* String holding what we received over the channel
*/
std::string m_strReceived;
/**
* Have we read past HTTP headers?
*/
bool m_bReadPastHTTPHeaders;
/**
* Payload buffer
*/
const char* m_pcReceived;
/**
* Proxy server name.
*/
std::string m_strProxyHost;
/**
* Proxy server port.
*/
unsigned int m_uiProxyPort;
/**
* Use Proxy or not?
*/
bool m_bUseProxy;
};
#endif
1.1 ws-axis/c/src/transport/axis2/AxisTransportException.cpp
Index: AxisTransportException.cpp
===================================================================
/* -*- C++ -*- */
/*
* 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 Damitha Kumarage (damitha@opensource.lk, damitha@jkcsworld.com)
*
*/
#include "AxisTransportException.h"
/**
* Default when no parameter passed. When thrown with no parameter
* more general SERVER_TRANSPORT_EXCEPTION is assumed.
*/
AxisTransportException::AxisTransportException()
{
processException(SERVER_TRANSPORT_EXCEPTION);
}
AxisTransportException::AxisTransportException (const int iExceptionCode)
{
m_iExceptionCode = iExceptionCode;
processException (iExceptionCode);
}
AxisTransportException::AxisTransportException(const int iExceptionCode, char* pcMessage)
{
m_iExceptionCode = iExceptionCode;
processException(iExceptionCode, pcMessage);
}
AxisTransportException::AxisTransportException (const exception* e)
{
processException (e);
}
AxisTransportException::AxisTransportException (const exception* e, const int iExceptionCode)
{
processException (e, iExceptionCode);
}
AxisTransportException::~AxisTransportException() throw ()
{
}
void AxisTransportException::processException (const exception* e, const int iExceptionCode)
{
m_sMessage = getMessage (iExceptionCode) + ":" + getMessage(e);
}
void AxisTransportException::processException (const exception* e, char* pcMessage)
{
m_sMessage += "AxisTransportException:" + string(pcMessage) + ":" + getMessage (e);
}
void AxisTransportException::processException (const exception* e)
{
m_sMessage += "AxisTransportException:" + getMessage (e);
}
void AxisTransportException::processException(const int iExceptionCode)
{
m_sMessage = getMessage (iExceptionCode);
}
void AxisTransportException::processException(const int iExceptionCode, char* pcMessage)
{
AxisString sMessage = pcMessage;
m_sMessage = getMessage(iExceptionCode) + " " + sMessage;
if(pcMessage)
delete pcMessage;
}
const string& AxisTransportException::getMessage (const exception* objException)
{
static string objExDetail = objException->what();
return objExDetail;
}
const string& AxisTransportException::getMessage (const int iExceptionCode)
{
switch(iExceptionCode)
{
case SERVER_TRANSPORT_RECEPTION_EXCEPTION:
m_sMessage = "AxisTransportException:Problem occured when" \
" receiving the stream";
break;
case SERVER_TRANSPORT_SENDING_EXCEPTION:
m_sMessage = "AxisTransportException:Problem occured when sending" \
" the stream";
break;
case SERVER_TRANSPORT_HTTP_EXCEPTION:
m_sMessage = "AxisTransportException:HTTP transport error";
break;
case SERVER_TRANSPORT_PROCESS_EXCEPTION:
m_sMessage = "AxisTransportException:HTTP Error, cannot process" \
" response message";
break;
case SERVER_TRANSPORT_UNKNOWN_HTTP_RESPONSE:
m_sMessage = "AxisTransportException:Unknow HTTP response," \
" cannot process response message";
break;
case SERVER_TRANSPORT_UNEXPECTED_STRING:
m_sMessage = "AxisTransportException:Unexpected string " \
"received. Most probably server " \
"returned an empty stream";
break;
case SERVER_TRANSPORT_CHANNEL_INIT_ERROR:
m_sMessage = "AxisTransportException:Cannot initialize a " \
"channel to the remote end";
break;
case SERVER_TRANSPORT_SOCKET_CREATE_ERROR:
m_sMessage = "AxisTransportException:Sockets error Couldn't" \
" create socket";
break;
case SERVER_TRANSPORT_SOCKET_CONNECT_ERROR:
m_sMessage = "AxisTransportException:Cannot open a channel to the" \
" remote end, shutting down the channel";
break;
case SERVER_TRANSPORT_INVALID_SOCKET:
m_sMessage = "AxisTransportException:Invalid socket. Socket may" \
" not be open";
break;
case SERVER_TRANSPORT_OUTPUT_STREAMING_ERROR:
m_sMessage = "AxisTransportException:Output streaming error on" \
" Channel while writing data";
break;
case SERVER_TRANSPORT_INPUT_STREAMING_ERROR:
m_sMessage = "AxisTransportException:Input streaming error while" \
" getting data";
break;
case SERVER_TRANSPORT_TIMEOUT_EXCEPTION:
m_sMessage = "AxisTransportException:Channel error while waiting" \
" for timeout";
break;
case SERVER_TRANSPORT_TIMEOUT_EXPIRED:
m_sMessage = "AxisTransportException:Channel error connection " \
"timeout before receving";
break;
case SERVER_TRANSPORT_BUFFER_EMPTY:
m_sMessage = "AxisTransportException:Transport buffer is empty";
break;
default:
m_sMessage = "AxisTransportException:Unknown Transport Exception";
}
return m_sMessage;
}
const char* AxisTransportException::what() throw ()
{
return m_sMessage.c_str ();
}
const int AxisTransportException::getExceptionCode()
{
return m_iExceptionCode;
}
1.1 ws-axis/c/src/transport/axis2/AxisTransportException.h
Index: AxisTransportException.h
===================================================================
/*
* 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 Damitha Kumarage (damitha@opensource.lk, damitha@jkcsworld.com)
*
*/
#ifndef __AXISTRANSPORTEXCEPTION_H_OF_AXIS_INCLUDED_
#define __AXISTRANSPORTEXCEPTION_H_OF_AXIS_INCLUDED_
#include <string>
#include <axis/server/AxisException.h>
using namespace std;
AXIS_CPP_NAMESPACE_USE
class STORAGE_CLASS_INFO AxisTransportException :public AxisException
{
public:
AxisTransportException();
AxisTransportException(const int iExceptionCode);
AxisTransportException(const int iExceptionCode, char* pcMessage);
AxisTransportException(const exception* e);
AxisTransportException(const exception* e, const int iExceptionCode);
virtual ~AxisTransportException() throw();
const char* what() throw();
const int getExceptionCode();
private:
const string& getMessage(const exception* e);
const string& getMessage(const int iExceptionCode);
void processException(const exception* e);
void processException(const exception* e, const int iExceptionCode);
void processException (const exception* e, char* pcMessage);
void processException(const int iExceptionCode);
void processException(const int iExceptionCode, char* pcMessage);
string m_sMessage;
int m_iExceptionCode;
};
#endif
1.1 ws-axis/c/src/transport/axis2/Channel.cpp
Index: Channel.cpp
===================================================================
/*
* 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 Lilantha Darshana (lilantha@virtusa.com)
* @author Damitha Kumarage (damitha@jkcsworld.com, damitha@opensource.lk)
* @author Samisa Abeysinghe (sabeysinghe@virtusa.com)
*/
#include "Platform.h"
#include "Channel.h"
#include <iostream>
#include <stdio.h>
using namespace std;
/**
* Create a Channel & initialize
*
*/
Channel::Channel ():m_Sock (INVALID_SOCKET)
{
}
Channel::~Channel ()
{
closeChannel ();
}
void Channel::setURL(const char* cpURL)
{
m_URL.setURL(cpURL);
}
const char* Channel::getURL()
{
return m_URL.getURL();
}
/**
* This channel open INET channel for the time being using primitive sockets
* Do we need any other type of channel; like shared memory, pipes etc. ????
*
* @param p_RemoteNode End point address as hostname/IP
* @param p_RemoteEnd Port #
*
* @return true if successfuly open a soket to the endpoint. o/w exception is
* thrown
*/
bool
Channel::open () //std::string & p_RemoteNode, unsigned short p_RemoteEnd)
throw (AxisTransportException)
{
if (!Init ())
throw AxisTransportException(SERVER_TRANSPORT_CHANNEL_INIT_ERROR);
sockaddr_in clAddr, svAddr;
if ((m_Sock = socket (PF_INET, SOCK_STREAM, 0)) != INVALID_SOCKET)
{
clAddr.sin_family = AF_INET; /* AF_INET (address family Internet). */
clAddr.sin_port = 0; /* No Specify Port required */
clAddr.sin_addr.s_addr = INADDR_ANY;
if (bind (m_Sock, (struct sockaddr *) &clAddr, sizeof (clAddr)) ==
SOCKET_ERROR)
{
/* Error - Binding. Cannot open a channel to the remote end,
shutting down the channel
*/
closeChannel ();
throw AxisTransportException(SERVER_TRANSPORT_SOCKET_CONNECT_ERROR);
}
/* Although the above fragment makes use of the bind() API, it would be
* just as effective to skip over this call as there are no specific
* local port ID requirements for this client. The only advantage that
* bind() offers is the accessibility of the port which the system
* chose via the .sin_port member of the cli_addr structure which will
* be set upon success of the bind() call.
*/
svAddr.sin_family = AF_INET;
svAddr.sin_port = htons (m_URL.getPort());
struct hostent *pHostEntry = NULL;
/* probably this is the host-name of the server we are connecting to */
if ((pHostEntry = gethostbyname (m_URL.getHostName())))
{
svAddr.sin_addr.s_addr =
((struct in_addr *) pHostEntry->h_addr)->s_addr;
}
else
{
/* no this is the IP address */
svAddr.sin_addr.s_addr = inet_addr (m_URL.getHostName());
}
/* connect to the remote server. */
if (connect (m_Sock, (struct sockaddr *) &svAddr,
sizeof (svAddr)) == SOCKET_ERROR)
{
closeChannel ();
/*Cannot open a channel to the remote end, shutting down the channel*/
throw AxisTransportException(SERVER_TRANSPORT_SOCKET_CONNECT_ERROR);
}
}
else
{
closeChannel ();
/* Sockets error Couldn't create socket*/
throw AxisTransportException(SERVER_TRANSPORT_SOCKET_CREATE_ERROR);
}
return true;
}
/*
* OS specific initialization should do here
*
* @return true if successfuly initilaize OS specific stuffs. false o/w
*/
bool
Channel::Init ()
{
#ifdef WIN32
WSADATA wsaData; /* contains vendor-specific information, such as the
* maximum number of sockets available and the maximum
* datagram size.
*/
if (WSAStartup (WS_VERSION_REQD, &wsaData))
/* Filled by Windows Sockets DLLs */
{
m_LastErr = "WinSock DLL not responding.";
//Error ((char *) m_LastErr.c_str ());
return false;
}
else
{
/* Query to see whether the available version matches what we need */
if ((LOBYTE (wsaData.wVersion) < WS_VERSION_MAJOR ()) ||
(LOBYTE (wsaData.wVersion) == WS_VERSION_MAJOR () &&
HIBYTE (wsaData.wVersion) < WS_VERSION_MINOR ()))
{
char buf[100];
sprintf (buf,
"Windows Sockets version %d.%d not supported by winsock2.dll",
LOBYTE (wsaData.wVersion), HIBYTE (wsaData.wVersion));
Error (buf);
closeChannel ();
return false;
}
}
#else
/* cout << "no need for linux" << endl; */
/* other OS specific Intitialization goes here */
#endif
return true;
}
/*
* Write/send a message to the remote server; sending blocks the app.
* we may need to do this asynchronizely; preferably either non-blocking
* send or pthread.
*
* @param Message to be written to the open channel
*/
const Channel &
Channel::operator << (const char *msg)
{
if (INVALID_SOCKET == m_Sock)
{
/*Writing cannot be done without having a open socket to remote end*/
throw AxisTransportException(SERVER_TRANSPORT_INVALID_SOCKET);
}
int size = strlen (msg), nByteSent;
if ((nByteSent = send (m_Sock, msg, size, MSG_DONTROUTE)) == SOCKET_ERROR)
{
/*Output streaming error while writing data*/
closeChannel ();
throw AxisTransportException(SERVER_TRANSPORT_OUTPUT_STREAMING_ERROR);
}
return *this;
}
/*
* Read/receive a message from the remote server; reading may be done in
* chunks.
* @param string to hold the read Message
*/
const Channel &
Channel::operator >> (std::string & msg)
{
msg = "";
if (INVALID_SOCKET == m_Sock)
{
/* Reading cannot be done without having a open socket
Input streaming error on undefined channel; please open the channel first
*/
throw AxisTransportException (SERVER_TRANSPORT_INVALID_SOCKET);
}
int nByteRecv = 0;
const int BUF_SIZE = 1024;
char buf[BUF_SIZE];
//assume timeout not set; set default tatus to OK
int iTimeoutStatus = 1;
//check if timeout set
if(m_lTimeoutSeconds)
iTimeoutStatus = applyTimeout();
//handle timeout outcome
if(iTimeoutStatus < 0)//error
{
//select SOCKET_ERROR. Channel error while waiting for timeout
throw AxisTransportException(SERVER_TRANSPORT_TIMEOUT_EXCEPTION,
"Channel error while waiting for timeout");
}
if(iTimeoutStatus == 0)//timeout expired
{
/*"select timeout expired.
*Channel error connection timeout before receving
*/
throw AxisTransportException(SERVER_TRANSPORT_TIMEOUT_EXPIRED,
"Channel error: connection timed out before receving");
}
//either timeout was not set or data available before timeout; so read
if ((nByteRecv = recv (m_Sock, (char *) &buf, BUF_SIZE - 1, 0))
== SOCKET_ERROR)
{
/*recv SOCKET_ERROR, Channel error while getting data*/
/* closeChannel(); */
throw AxisTransportException(SERVER_TRANSPORT_INPUT_STREAMING_ERROR,
"Channel error while getting data");
/* throw AxisTransportException(SERVER_TRANSPORT_INPUT_STREAMING_ERROR);
*/
}
if (nByteRecv)
{
/* printf("nByteRecv:%d\n", nByteRecv); */
buf[nByteRecv] = '\0';
/* got a part of the message, so add " \ "to form */
msg = buf;
/* printf("buf:%s\n", buf); */
}
else
;//printf ("execution break\n");
return *this;
}
const Channel &
Channel::readNonBlocking( std::string & msg, bool bBlockingRequired)
{
msg = "";
if (INVALID_SOCKET == m_Sock)
{
/*Reading cannot be done without having a open socket*/
throw AxisTransportException(SERVER_TRANSPORT_INVALID_SOCKET);
}
int nByteRecv = 0;
const int BUF_SIZE = 1024;
char buf[BUF_SIZE];
//Samisa: I want to set the socket to non blocking mode here
//for Winsock there is no simple way to do this but for Linux I used MSG_DONTWAIT
//there is no MSG_DONTWAIT defined in Winsock
int flags = 0;
#if defined WIN32
// Set the socket I/O mode; iMode = 0 for blocking; iMode != 0 for non-blocking
int iMode = 1;
if( bBlockingRequired)
{
iMode = 0;
}
ioctlsocket( m_Sock, FIONBIO, (u_long FAR*) &iMode);
flags = 0;
#elif defined AIX
flags=MSG_WAITALL;
if (!bBlockingRequired)
{
flags=MSG_NONBLOCK;
}
#elif defined( __OS400__ )
fcntl(m_Sock, F_SETFL, (int)O_NONBLOCK);
flags = 0;
#else
//for linux
if( !bBlockingRequired)
{
flags = MSG_DONTWAIT;
}
//TODO: define flags (or other means) to enable non blocking for other operating systems
#endif
if ((nByteRecv = recv (m_Sock, (char *) &buf, BUF_SIZE - 1, flags))
== SOCKET_ERROR)
{
/*Channel error while getting data*/
return *this;
}
if (nByteRecv)
{
buf[nByteRecv] = '\0';
msg = buf;
}
else
Error( "Channel::readNonBlocking: execution break");
return *this;
}
//samisa
/*
* Close, and clean-up any OS specific stuff
*
*/
void
Channel::closeChannel ()
{
#ifdef WIN32
if (INVALID_SOCKET != m_Sock)
closesocket (m_Sock);
/* Check for any possible error conditions from WSACleanup() and report
* them before exiting, as this information might indicate a network
* layer problem in the system.
*/
WSACleanup ();
#else
if (INVALID_SOCKET != m_Sock)
::close (m_Sock);
#endif
}
/*
* Log any errors that cause on channel usage/initilaization
*
*/
void
Channel::Error (const char *err)
{
#ifdef _DEBUG
std::cerr << err << std::endl;
#endif
}
void Channel::setTimeout(const long lSeconds)
{
m_lTimeoutSeconds = lSeconds;
}
int Channel::applyTimeout()
{
fd_set set;
struct timeval timeout;
/* Initialize the file descriptor set. */
FD_ZERO(&set);
FD_SET(m_Sock, &set);
/* Initialize the timeout data structure. */
timeout.tv_sec = m_lTimeoutSeconds;
timeout.tv_usec = 0;
/* select returns 0 if timeout, 1 if input available, -1 if error. */
return select(FD_SETSIZE, &set, NULL, NULL, &timeout);
}
1.1 ws-axis/c/src/transport/axis2/Channel.h
Index: Channel.h
===================================================================
/*
* 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 Lilantha Darshana (lilantha@virtusa.com)
* @author Damitha Kumarage (damitha@jkcsworld.com, damitha@opensource.lk)
* @author Samisa Abeysinghe (sabeysinghe@virtusa.com)
*/
#if !defined(_AXIS_CHANNEL_HPP)
#define _AXIS_CHANNEL_HPP
#include <string>
#include "AxisTransportException.h"
#include "URL.h"
/* platform specific stuff */
#ifdef WIN32
#include <winsock2.h>
/* what version of WinSock is required */
const int WS_VERSION_REQD = 0x0101;
/* macros to get version major & minor */
inline WS_VERSION_MAJOR() {return HIBYTE(WS_VERSION_REQD);}
inline WS_VERSION_MINOR() {return LOBYTE(WS_VERSION_REQD);}
#else
#include <unistd.h>
#include <sys/types.h> /* basic system data types */
#include <sys/socket.h> /* basic socket definitions */
#include <fcntl.h> /* for nonblocking if need */
#include <sys/time.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h> /* inet(3) functions */
const unsigned int INVALID_SOCKET = 0;
const int SOCKET_ERROR = -1;
/* ther OS specific stuff goes here */
#endif
/*
*
* Implements primitive socket connection for all platforms, for
* sending/receiving SOAP Envelops with given transport; This implementation
* abstract the low-level communications.
*
* @brief The primitive socket implementation for SOAP Envelops passing.
*
*/
class Channel
{
public:
Channel();
virtual ~Channel();
void setURL(const char* cpURL);
const char* getURL();
URL& getURLObject() { return m_URL; };
/* Open a socket to a given remote node/server address with remote port */
virtual bool open() throw (AxisTransportException);
/* Close all open sockets and clean up */
virtual void close(){closeChannel();}
/* Read from a open socket and store read message in msg */
virtual const Channel& operator >> (std::string& msg);
/* Read from socket in non bloking more in msg */
virtual const Channel& readNonBlocking(std::string& msg, bool bBlockingRequired);
/* Write a given message (msg) to the end-point using the open socket */
virtual const Channel& operator << (const char* msg);
/* Return last error (if any). */
virtual const std::string& GetLastError(){return m_LastErr;}
/**
* Set transport timeout.
*
* @param lSeconds Timeout in seconds
*/
void setTimeout(const long lSeconds);
protected:
/* OS specific initilization */
virtual bool Init();
/* Report error on read/write */
virtual void Error(const char * err);
/* Close & clean-up the open socket/system resources */
virtual void closeChannel();
/**
* @return 0 if timeout, 1 if input available, -1 if error.
*/
int applyTimeout();
unsigned int m_Sock; /* Socket descriptor */
URL m_URL;
std::string m_LastErr; /* Last error as a string */
/**
* Timeout in seconds
*/
long m_lTimeoutSeconds;
};
#endif
1.1 ws-axis/c/src/transport/axis2/Makefile.am
Index: Makefile.am
===================================================================
lib_LTLIBRARIES = libaxis2_transport.la
AM_CPPFLAGS = $(CPPFLAGS)
libaxis2_transport_la_SOURCES = Channel.cpp \
URL.cpp \
Axis2Transport.cpp \
AxisTransportException.cpp
libaxis2_transport_la_LIBADD = -lstdc++
INCLUDES = -I../../../include
1.1 ws-axis/c/src/transport/axis2/Platform.h
Index: Platform.h
===================================================================
/*
* 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 Lilantha Darshana (lilantha@erunway.com)
*
*/
#if !defined(_AXIS_STDAFX_H)
#define _AXIS_STDAFX_H
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
/* Exclude rarely-used stuff from Windows headers */
#pragma warning ( disable : 4786 )
/* #include <afx.h> */
/* #include <afxwin.h> */
#ifdef AXIS_EXPORTS
#define AXIS_API __declspec(dllexport)
#else
#define AXIS_API __declspec(dllimport)
#endif
#else /* WIN32 */
#define AXIS_API
#include <unistd.h>
/* other OS specific stuff goes here */
#endif
#if defined(_DEBUG)
# include <iostream>
# define DebugMsg(x) std::cout << x <<std::endl;
#else
# define DebugMsg(x)
#endif
#endif
1.1 ws-axis/c/src/transport/axis2/URL.cpp
Index: URL.cpp
===================================================================
/*
* 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 Lilantha Darshana (lilantha@virtusa.com)
*
*/
#include "Platform.h"
#include "URL.h"
#include <ctype.h>
#include <iostream>
using namespace std;
URL::URL()
: m_Protocol(unknown), m_Port(0), m_URL("")
{
/* cout << "inside URL constructor" << endl; */
}
URL::URL(std::string url)
{
m_URL = url;
if(isascii((int)url.at(0)))
{
/* check this a valid URL */
if((url.at(1) == (int)':') &&
((url.at(2) == (int)'/') || (url.at(2) == (int)'\\')))
return;
else /* assume valid URL hence, proceed with finding entries */
ParseURL(url);
}
}
URL::~URL()
{
}
void URL::setProtocol(std::string prot)
{
m_Port = 0;
if(prot == "http")
{
m_Protocol = http;
m_Port = HTTP_PORT;
}
else if( prot == "file")
{
m_Protocol = file;
}
else if( prot == "ftp")
{
m_Protocol = ftp;
m_Port = FTP_PORT;
}
else if( prot == "https")
{
m_Protocol = https;
m_Port = HTTPS_PORT;
}
else
m_Protocol = unknown;
}
void URL::setURL(const char* cpURL)
{
m_URL = std::string(cpURL);
if(isascii((int)m_URL.at(0)))
{
/* check this a valid URL */
if((m_URL.at(1) == (int)':') &&
((m_URL.at(2) == (int)'/') || (m_URL.at(2) == (int)'\\')))
return;
else /* assume valid URL hence, proceed with finding entries */
ParseURL(m_URL);
}
}
const char* URL::getURL()
{
if (m_URL.length() > 0 )
return m_URL.c_str();
else
return NULL;
}
void URL::ParseURL(std::string url)
{
std::string::size_type begpos, pos;
/* try to find out the protocol */
if((pos = url.find("://")) != std::string::npos)
{
setProtocol(url.substr(0, pos));
/* find m_Host name */
if(m_Protocol != unknown)
{
url = url.substr(pos + 3); /* rest of the URL string */
begpos = pos = 0;
std::string key(":/?");
while((pos = url.find_first_of(key, begpos)))
{
if(pos == std::string::npos) /* only host name found */
{
if(m_Host.empty())
m_Host = url;
if (key == "?") /* found path */
m_Path = url.substr(begpos - 1);
break;
}
else
if(pos == 0) break;
switch(url.at(pos))
{
case ':':
if(m_Host.empty())
m_Host = url.substr(begpos, pos - begpos);
pos++;
begpos = pos;
key = "/?";
/* scan for the rest to get the path & query */
continue;
case '/':
if (key == "/?") /* found port number */
{
m_Port = atoi(url.substr(begpos,
pos - begpos + 1).c_str());
if(m_Host.empty())
m_Host = url.substr(0, begpos - 1);
}
else
m_Host = url.substr(0, pos);
pos++;
begpos = pos;
/*
key = "?";
continue;
case '?':
//not correctly supported
m_Query = url.substr(pos);
*/
/* no need to find other ? */
m_Path = url.substr(begpos - 1);
break;
}
break;
}
}
}
}
1.1 ws-axis/c/src/transport/axis2/URL.h
Index: URL.h
===================================================================
/*
* 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 Lilantha Darshana (lilantha@virtusa.com)
*
*/
#if !defined(_AXIS_URL_HPP)
#define _AXIS_URL_HPP
#include <string>
/* Welknown ports */
const unsigned short HTTP_PORT = 80;
const unsigned short HTTPS_PORT = 443;
const unsigned short FTP_PORT = 21;
/*
* Implementation of URL to manupulate URLs.
*
* This implementation only supports subset of a URL
* note that # references, userinfo query string
* processing are not supported for this version.
*
* URLs are of the form:
*
* URL = protocol "://" server "/" [path]["?" query]
* server = [userinfo "@"] hostname-port
* hostname-port = hostname [ ":" port ]
* userinfo = user[:password]
*
*
* @brief Manupulate URLs
*/
class URL
{
public:
enum Protocol { http, https, ftp, file, unknown};
/* for our purpose currently we need http, https only. This is provided
* To make extensible to support other transports for RPC but file????,
* yes we may require pipes; with web-service????
*/
public:
URL();
URL(std::string url);
~URL();
void setProtocol(std::string prot);
void setProtocol(Protocol prot){m_Protocol = prot;}
void setHostName(std::string host){m_Host= host;}
void setResource(std::string path){m_Path = path;}
void setPort(unsigned short port){m_Port = port;}
Protocol getProtocol(){return m_Protocol;}
const char* getHostName(){return m_Host.c_str();}
std::string getResource(){return m_Path;}
void setURL(const char* cpURL);
const char* getURL();
unsigned short getPort(){return m_Port;}
// other functions are not supported yet
private:
void ParseURL(std::string url);
Protocol m_Protocol;
std::string m_Host;
unsigned short m_Port;
std::string m_Path;
std::string m_Query;
std::string m_Password;
std::string m_User;
std::string m_URL;
};
#endif