Details
-
Bug
-
Status: Resolved
-
Major
-
Resolution: Fixed
-
0.95
-
None
-
Tried in both windows (xp pro) and linux (Suse)
Description
We are using axis2/c within a c++ class. We created static variables for axis2_http_client_t and axis2_env_t in the class and trying to reuse the instances for transmitting multiple messages. please note that respose also reusing the same instance. This code was developed by my colleague and I'm only modifying (denoted by pbkar in comments) it to use single client instance that uses the same socket stream for multiple messages.
The files are APSAPISoap.cpp / .h
1) APSAPISoap.cpp
---------------------------------------------
///
///
/// @author lkrankur
///
///
#ifdef WIN32
#include "stdafx.h"
#endif
#include "APSAPISoap.h"
#include "APSConfigData.h"
#include "ClientLog.h"
#include <vector>
extern
string trim(string* s);
axis2_env* APSAPISoap::m_env = NULL; // instances defined here pbkar
axis2_http_client_t *APSAPISoap::m_http_client = NULL;
int APSAPISoap::m_count = 0;
//#ifdef MYDBG
//extern std::ofstream outt;
//#endif
typedef struct axis2_http_simple_response_impl
{
axis2_http_simple_response_t simple_response;
axis2_http_status_line_t *status_line;
axis2_array_list_t *header_group;
axis2_stream_t *stream;
}
axis2_http_simple_response_impl_t;
#define AXIS2_INTF_TO_IMPL2(simple_response) \
((axis2_http_simple_response_impl_t *)(simple_response))
axis2_ssize_t AXIS2_CALL
axis2_http_simple_response_get_body_bytes1
(
axis2_http_simple_response_t* simple_response,
const axis2_env_t* env,
axis2_char_t **buffer,
long bsize
)
{
if ( 1 > bsize )
return 0;
axis2_http_simple_response_impl_t* response_impl = NULL;
long return_size = 0;
try
{
response_impl = AXIS2_INTF_TO_IMPL2(simple_response);
if ( NULL == response_impl->stream )
return return_size;
*buffer =
(char *)AXIS2_MALLOC
(
env->allocator,
sizeof(char) * (bsize + 1)
);
#ifdef MYDBG
int k = 1;
#endif
for ( int ret = 1 ; bsize != return_size && 0 < ret; )
{
return_size +=
ret =
AXIS2_STREAM_READ
(
response_impl->stream,
env,
*buffer + return_size,
bsize - return_size
);
if ( bsize == return_size || 0 == ret )
{ char* p = *buffer + bsize; p[0] = 0; break; }else
{ #ifdef MYDBG // cout << Log::getCurrentDateTime() << "\tprocessID = " << getpid() << "\ttry in receive = " << k << ", read bytes = " << return_size2 << endl; // outt << Log::getCurrentDateTime() << "\tprocessID = " << getpid() << "\ttry in receive = " << k << ", read bytes = " << return_size2 << endl; // ++k; #endif ; } }
}
catch ( ... )
{
return_size = 0;
if ( NULL != *buffer )
}
return return_size;
}
///
/// AXIS2_HTTP_CLIENT_SEND Axis2c 0.94. 095 has memory leak
/// method replaces axis2_http_client_send method (in http_client.c) modified to fix
///
axis2_status_t AXIS2_CALL
axis2_http_client_send1
(
axis2_http_client_t* client,
const axis2_env_t* env,
axis2_http_simple_request_t* request
)
{
static axis2_http_client_impl_t* client_impl = NULL;
char* wire_format = NULL;
axis2_array_list_t* headers = NULL;
char* str_body = NULL;
char* str_request_line = NULL;
int body_size = 0;
int written = 0;
axis2_status_t status = AXIS2_FAILURE;
axis2_bool_t chunking_enabled = AXIS2_FALSE;
AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
// this code is an attempt to reset the client_impl since it was hanging after 50 calls pbkar
++APSAPISoap::m_count;
if (APSAPISoap::m_count >= 49){
client_impl->request_sent = AXIS2_TRUE;
APSAPISoap::m_count=0;
if ( NULL != client_impl->data_stream )
{
try
catch ( ... )
{
}
client_impl->data_stream = NULL;
}
axis2_network_handler_close_socket(env, client_impl->sockfd);
AXIS2_HTTP_SIMPLE_RESPONSE_FREE(client_impl->response, env);
//AXIS2_HTTP_CLIENT_FREE( &(client_impl->http_client), env);
//client_impl->http_client.ops->free( &(client_impl->http_client), env);
//AXIS2_URL_FREE(client_impl->url, env);
client_impl = NULL;
}
// end reset client_impl
if(client_impl == NULL) { // code to bypass socket creation once client instance created created, pbkar
client_impl = AXIS2_INTF_TO_IMPL(client);
if ( NULL == client_impl->url )
{ if ( NULL != env->error ) AXIS2_ERROR_SET ( env->error, AXIS2_ERROR_NULL_URL, (axis2_status_codes_t)AXIS2_FAILURE ); return AXIS2_FAILURE; } if ( AXIS2_TRUE == client_impl->proxy_enabled )
{
if ( NULL == client_impl->proxy_host || 0 >= client_impl->proxy_port )
client_impl->sockfd =
axis2_network_handler_open_socket
(
env,
client_impl->proxy_host,
client_impl->proxy_port
);
}
else
if ( 0 > client_impl->sockfd )
{ if ( NULL != env->error ) AXIS2_ERROR_SET ( env->error, AXIS2_ERROR_SOCKET_ERROR, (axis2_status_codes_t)AXIS2_FAILURE ); return AXIS2_FAILURE; }/* ONLY FOR TESTING
- client_impl->data_stream = axis2_stream_create_file(env,
- stdout);
*/
if ( 0 < client_impl->timeout ) { axis2_network_handler_set_sock_option ( env, client_impl->sockfd, SO_RCVTIMEO, client_impl->timeout ); axis2_network_handler_set_sock_option ( env, client_impl->sockfd, SO_SNDTIMEO, client_impl->timeout ); }
if ( 0 == AXIS2_STRCASECMP
(
AXIS2_URL_GET_PROTOCOL(client_impl->url, env),
"HTTPS"
)
)
{
#ifdef AXIS2_SSL_ENABLED
if ( AXIS2_TRUE == client_impl->proxy_enabled )
{
if ( AXIS2_SUCCESS != axis2_http_client_connect_ssl_host(client, env,
AXIS2_URL_GET_SERVER(client_impl->url, env),
AXIS2_URL_GET_PORT(client_impl->url, env))
)
}
client_impl->data_stream =
axis2_stream_create_ssl
(
env,
client_impl->sockfd
);
#else
if ( NULL != env->error )
AXIS2_ERROR_SET
(
env->error,
AXIS2_ERROR_INVALID_TRANSPORT_PROTOCOL,
(axis2_status_codes_t)AXIS2_FAILURE
);
return AXIS2_FAILURE;
#endif
}
else
if ( NULL == client_impl->data_stream )
{ axis2_network_handler_close_socket(env, client_impl->sockfd); return AXIS2_FAILURE; }} // end code to bypass pbkar
headers = AXIS2_HTTP_SIMPLE_REQUEST_GET_HEADERS(request, env);
string s;
if ( headers )
{
int header_count = AXIS2_ARRAY_LIST_SIZE(headers, env);
char ee[2048] =
{0};for ( int i = 0; i < header_count; ++i )
{
axis2_char_t* header_ext_form = NULL;
axis2_http_header_t*
tmp_header =
(axis2_http_header_t *)AXIS2_ARRAY_LIST_GET(headers, env, i);
if ( NULL == tmp_header )
{ continue; }
/* check whether we have transfer encoding and then see whether the
* value is "chunked" */
if ( 0 == AXIS2_STRCMP(AXIS2_HTTP_HEADER_GET_NAME(tmp_header, env),
AXIS2_HTTP_HEADER_TRANSFER_ENCODING) && 0 ==
AXIS2_STRCMP(AXIS2_HTTP_HEADER_GET_VALUE(tmp_header, env),
AXIS2_HTTP_HEADER_TRANSFER_ENCODING_CHUNKED)
)
{ chunking_enabled = AXIS2_TRUE; }
sprintf
(
ee,
"%s: %s%s",
tmp_header->ops->get_name(tmp_header, env),
tmp_header->ops->get_value(tmp_header, env),
AXIS2_HTTP_CRLF
);
s += ee;
}
}
if ( AXIS2_FALSE == client_impl->proxy_enabled )
{ str_request_line = AXIS2_HTTP_REQUEST_LINE_TO_STRING ( AXIS2_HTTP_SIMPLE_REQUEST_GET_REQUEST_LINE(request, env), env ); }
else
{
/* we need the request line in the format
* POST http://host:port/path HTTP/1.x if we have enabled proxies
*/
axis2_char_t* host_port_str = NULL;
axis2_char_t* server = AXIS2_URL_GET_SERVER(client_impl->url, env);
axis2_http_request_line_t* request_line =
AXIS2_HTTP_SIMPLE_REQUEST_GET_REQUEST_LINE(request, env);
axis2_char_t* path = AXIS2_HTTP_REQUEST_LINE_GET_URI(request_line, env);
/* length = len(server) + len(:port) + len("http://") + len(path) + 1*/
host_port_str =
(axis2_char_t*)AXIS2_MALLOC
(
env->allocator, AXIS2_STRLEN(server) +
AXIS2_STRLEN(path) +
20 * sizeof(axis2_char_t)
);
if ( NULL == host_port_str )
{ if ( NULL != env->error ) AXIS2_ERROR_SET ( env->error, AXIS2_ERROR_NO_MEMORY, (axis2_status_codes_t)AXIS2_FAILURE ); return AXIS2_FAILURE; }
sprintf
(
host_port_str,
"http://%s:%d%s",
server,
AXIS2_URL_GET_PORT(client_impl->url, env),
path
);
str_request_line =
(char*)AXIS2_MALLOC
(
env->allocator,
AXIS2_STRLEN(host_port_str) + 20 * sizeof(axis2_char_t)
);
sprintf
(
str_request_line, "%s %s %s\r\n",
AXIS2_HTTP_REQUEST_LINE_GET_METHOD(request_line, env),
host_port_str,
AXIS2_HTTP_REQUEST_LINE_GET_HTTP_VERSION(request_line, env)
);
AXIS2_FREE(env->allocator, host_port_str);
host_port_str = NULL;
}
s = string(str_request_line) + s;
AXIS2_FREE(env->allocator, str_request_line);
str_request_line = NULL;
written = AXIS2_STREAM_WRITE(client_impl->data_stream, env, s.c_str(), s.size());
cout << "after write" << endl;
AXIS2_FREE(env->allocator, wire_format);
wire_format = NULL;
written = AXIS2_STREAM_WRITE(client_impl->data_stream, env, AXIS2_HTTP_CRLF, 2);
cout << "after write crlf" << endl;
body_size = AXIS2_HTTP_SIMPLE_REQUEST_GET_BODY_BYTES(request, env, &str_body);
if ( 0 < body_size && str_body )
{
if (AXIS2_FALSE == chunking_enabled)
{
status = AXIS2_SUCCESS;
while ( written < body_size )
{
written =
AXIS2_STREAM_WRITE
(
client_impl->data_stream,
env,
str_body,
body_size
);
if ( -1 == written )
{ status = AXIS2_FAILURE; break; }
}
}
else
{
axis2_http_chunked_stream_t* chunked_stream = NULL;
chunked_stream =
axis2_http_chunked_stream_create(env, client_impl->data_stream);
status = AXIS2_SUCCESS;
if ( NULL == chunked_stream )
{ if ( NULL != env->log ) AXIS2_LOG_ERROR ( env->log, AXIS2_LOG_SI, "Creation of chunked stream failed" ); return AXIS2_FAILURE; }
while ( written < body_size )
{
written =
AXIS2_HTTP_CHUNKED_STREAM_WRITE
(
chunked_stream,
env,
str_body,
body_size
);
if ( -1 == written )
{ status = AXIS2_FAILURE; break; }
}
if ( AXIS2_SUCCESS == status )
{ AXIS2_HTTP_CHUNKED_STREAM_WRITE_LAST_CHUNK(chunked_stream, env); }
AXIS2_HTTP_CHUNKED_STREAM_FREE(chunked_stream, env);
}
}
client_impl->request_sent = AXIS2_TRUE;
if ( NULL != str_body )
{ AXIS2_FREE(env->allocator, str_body); str_body = NULL; }
cout << "after send1" << endl;
return status;
}
/// <summary>
/// constructor
/// <param name="logSoap">, [in], type = char*, path to the axis2 log file</param>
/// </summary>
APSAPISoap::APSAPISoap()
:m_buffer(NULL), m_buffer2(NULL), m_body(NULL) { m_allocator = axis2_allocator_init (NULL); //m_env = axis2_env_create(m_allocator); axis2_allocator_t* allocator = axis2_allocator_init (NULL); axis2_error_t* error = axis2_error_create(allocator); m_env = axis2_env_create_with_error(allocator, error); }
/// <summary>
/// method creates unsigned envelope
/// <param name="localName">, [in], type = axis2_char_t*, local name for the request element</param>
/// <param name="localNamespace">, [in], type = axis2_char_t*, namespace for the request element, could be NULL</param>
/// <param name="pRequest">, [in], type = RequestTO*, XACML request, could be NULL</param>
/// <param name="applicationName">, [in], type = axis2_char_t*, application name, could be NULL</param>
/// </summary>
bool APSAPISoap::getSoapEnvelope
(
axis2_char_t* localName,
axis2_char_t* localNamespace,
RequestTO* pRequest,
axis2_char_t* applicationName
)
{
bool fOk = false;
m_buffer = m_buffer2 = NULL;
axiom_soap_body* body = NULL;
axiom_soap_envelope* envelope = NULL;
axiom_node_t* request_om_node = NULL;
axiom_node_t* envelope_om_node = NULL;
try
{
axiom_namespace_t* ns[] = { axiom_namespace_create (m_env, APS::XML_NAMESPACE::SOAP_ENCODING, "soapenc"), axiom_namespace_create (m_env, APS::XML_NAMESPACE::SCHEMA, "xsd"), axiom_namespace_create (m_env, APS::XML_NAMESPACE::SCHEMA_INSTANCE, "xsi"), };
envelope = axiom_soap_envelope_create_with_soap_version_prefix(m_env, 1, "");
envelope_om_node = AXIOM_SOAP_ENVELOPE_GET_BASE_NODE(envelope, m_env);
axiom_element_t* envelope_om_ele = (axiom_element_t*)AXIOM_NODE_GET_DATA_ELEMENT(envelope_om_node, m_env);
for ( int i = 0; i < 3; ++i )
AXIOM_ELEMENT_DECLARE_NAMESPACE(envelope_om_ele, m_env, envelope_om_node, ns[i]);
body = axiom_soap_body_create_with_parent(m_env, envelope);
request_om_node =
(
( applicationName ) ?
createRequest2(localName, applicationName)
:
createRequest(localName, localNamespace, pRequest)
);
m_buffer2 = AXIOM_NODE_TO_STRING(request_om_node, m_env);
axis2_status_t status =
AXIOM_SOAP_BODY_ADD_CHILD
(
body,
m_env,
request_om_node
);
m_buffer = AXIOM_NODE_TO_STRING(envelope_om_node, m_env);
fOk = true;
AXIOM_SOAP_ENVELOPE_FREE(envelope, m_env);
envelope = NULL;
}
catch ( ... )
{
// to do logging?
try
{ if ( !fOk ) freeBuffers(); //if ( NULL != body ) // AXIOM_SOAP_BODY_FREE(body, m_env); //if ( NULL != request_om_node ) // AXIOM_SOAP_BODY_FREE(request_om_node, m_env); //if ( NULL != envelope_om_node ) // AXIOM_NODE_FREE_TREE(envelope_om_node, m_env); if ( NULL != envelope ) AXIOM_SOAP_ENVELOPE_FREE(envelope, m_env); }
catch ( ... )
{ // to do logging? }
}
return fOk;
}
/// <summary>
/// method creates XACML Request element (evaluation policy) as OM node
/// <param name="localName">, [in], type = axis2_char_t*, localName of Request element</param>
/// <param name="localNamespace">, [in], type = axis2_char_t*, namespace of localName of Request element</param>
/// <param name="pRequest">, [in], type = RequestTO*, pointer to RequestTO object </param>
/// </summary>
axiom_node_t* APSAPISoap::createRequest
(
axis2_char_t* localName,
axis2_char_t* localNamespace,
RequestTO* pRequest
)
{
axiom_node_t* request_om_node = NULL;
axiom_node_t* resource_om_node = NULL;
axiom_element_t* resource_om_ele = NULL;
axiom_node_t* action_om_node = NULL;
axiom_element_t* action_om_ele = NULL;
axiom_element_t* request_om_ele =
axiom_element_create
(
m_env,
NULL,
localName,
// to comfort signature validation have to create request without namespace
/* axiom_namespace_create
(
m_env,
localNamespace,
""
)*/
NULL
,
&request_om_node
);
SubjectTO tmpSTO = pRequest->getSubject();
createSubject
(
request_om_node,
&tmpSTO
);
createResource
(
request_om_node,
(axis2_char_t*)pRequest->getResource().c_str(),
(axis2_char_t*)pRequest->getScope().c_str()
);
createAction
(
request_om_node,
(axis2_char_t*)pRequest->getAction().c_str()
);
return request_om_node;
}
/// <summary>
/// method creates XACML Request element (RoleRequest, ResourceRequest, DCRequest) as OM node
/// <param name="localName">, [in], type = aps_arribute_t*, localName of Request element</param>
/// <param name="appname">, [in], type = axis2_char_t*, name of application</param>
/// </summary>
axiom_node_t* APSAPISoap::createRequest2
(
axis2_char_t* localName,
axis2_char_t* appname
)
{
axiom_node_t* request_om_node = NULL;
axiom_node_t* add0_om_node = NULL;
axiom_element_t* request_om_ele =
axiom_element_create
(
m_env,
NULL,
localName,
NULL,
&request_om_node
);
axiom_element_t* add0_om_ele =
axiom_element_create
(
m_env,
request_om_node,
"Application",
NULL,
&add0_om_node
);
axiom_attribute_t* attr0 = axiom_attribute_create(m_env, "Name", appname, NULL);
AXIOM_ELEMENT_SET_NAMESPACE(add0_om_ele, m_env, NULL, add0_om_node);
AXIOM_ELEMENT_ADD_ATTRIBUTE(add0_om_ele, m_env, attr0, add0_om_node);
return request_om_node;
}
/// <summary>
/// method creates OM node for Subject element and adds to Request node
/// <param name="request">, [in], type = axiom_node_t*, request node</param>
/// <param name="pSubject">, [in], type = SubjectTO*, pointer to SubjectTO object</param>
/// </summary>
void APSAPISoap::createSubject(axiom_node_t* parent, SubjectTO* pSubject)
{
axiom_node_t* om_node = NULL;
axiom_element_t* om_ele =
axiom_element_create
(
m_env,
parent,
"Subject",
NULL,
&om_node
);
AXIOM_ELEMENT_ADD_ATTRIBUTE
(
om_ele,
m_env,
axiom_attribute_create
(
m_env,
"SubjectCategory",
APS::XACML::SUBJECT_CATEGORY,
NULL
),
om_node
);
vector<aps_arribute_t*> attributes;
vector<AttributeTO> subjectAtts = pSubject->getAttributes();
vector<AttributeTO>::iterator attributeTO;
for
(
attributeTO = subjectAtts.begin();
attributeTO != subjectAtts.end();
attributeTO++
)
{ aps_arribute_t* t = new aps_arribute_t ( (axis2_char_t*)attributeTO->getID().c_str(), (axis2_char_t*)attributeTO->getType().c_str(), (axis2_char_t*)attributeTO->getValue().c_str(), m_env ); attributes.push_back(t); }
addAttributes(attributes, om_node);
clearAttributes(attributes);
}
/// <summary>
/// method creates OM node for Resource element and adds to Request node
/// <param name="request">, [in], type = axiom_node_t*, request node</param>
/// <param name="resource">, [in], type = axis2_char_t*, resource name</param>
/// <param name="scope">, [in], type = axis2_char_t*, scope of resource</param>
/// </summary>
void APSAPISoap::createResource
(
axiom_node_t* parent,
axis2_char_t* resource,
axis2_char_t* scope)
{
axiom_node_t* om_node = NULL;
axiom_element_t* resource_om_ele =
axiom_element_create
(
m_env,
parent,
"Resource",
NULL,
&om_node
);
vector<aps_arribute_t*> attributes;
aps_arribute_t* t = new aps_arribute_t((axis2_char_t*)APS::XACML::RESOURCE_ID, (axis2_char_t*)APS::XACML::RESOURCE_DEFAULT_TYPE, resource, m_env);
attributes.push_back(t);
t = new aps_arribute_t((axis2_char_t*)APS::XACML::RESOURCE_SCOPE_ID, scope, m_env);
attributes.push_back(t);
addAttributes(attributes, om_node);
clearAttributes(attributes);
}
/// <summary>
/// method creates OM node for Action element and adds to Request node
/// <param name="request">, [in], type = axiom_node_t*, request node</param>
/// <param name="action">, [in], type = axis2_char_t*, action name</param>
/// </summary>
void APSAPISoap::createAction(axiom_node_t* parent, axis2_char_t* action)
{
axiom_node_t* om_node = NULL;
axiom_element_t* om_ele =
axiom_element_create
(
m_env,
parent,
"Action",
NULL,
&om_node
);
vector<aps_arribute_t*> attributes;
aps_arribute_t* t = new aps_arribute_t((axis2_char_t*)APS::XACML::ACTION_ID, action, m_env);
attributes.push_back(t);
addAttributes(attributes, om_node);
clearAttributes(attributes);
}
/// <summary>
/// method adds XACML attribute as OM element to a parent OM node
/// <param name="attribute">, [in], type = aps_arribute_t*, attribute info </param>
/// <param name="parent">, [in], type = axiom_node_t*, parent OM node </param>
/// </summary>
void APSAPISoap::addAttribute
(
aps_arribute_t* attribute,
axiom_node_t* parent
)
{
axiom_node_t* add0_om_node = NULL;
axiom_node_t* add1_om_node = NULL;
axiom_element_t* add0_om_ele =
axiom_element_create(m_env, parent, "Attribute", NULL, &add0_om_node);
axiom_element_t*
add1_om_ele = axiom_element_create(m_env, add0_om_node, "AttributeValue", NULL, &add1_om_node);
axiom_attribute_t* attr0 = axiom_attribute_create(m_env, "AttributeId", attribute->attributeId, NULL);
axiom_attribute_t* attr1 = axiom_attribute_create(m_env, "DataType", attribute->dataType, NULL);
AXIOM_ELEMENT_SET_NAMESPACE(add0_om_ele, m_env, NULL, add0_om_node);
AXIOM_ELEMENT_ADD_ATTRIBUTE(add0_om_ele, m_env, attr0, add0_om_node);
AXIOM_ELEMENT_ADD_ATTRIBUTE(add0_om_ele, m_env, attr1, add0_om_node);
AXIOM_ELEMENT_SET_TEXT(add1_om_ele, m_env, attribute->dataValue, add1_om_node);
}
/// <summary>
/// method adds XACML attributes as OM elements to parent node
/// <param name="attributes">, [in], type = vector<aps_arribute_t*>, collection of attribute info </param>
/// <param name="parent">, [in], type = axiom_node_t*, parent OM node </param>
/// </summary>
void APSAPISoap::addAttributes
(
vector<aps_arribute_t*> attributes,
axiom_node_t* parent
)
{
vector<aps_arribute_t*>::iterator iter;
for ( iter = attributes.begin(); iter != attributes.end(); iter++ )
{ addAttribute(*iter, parent); }
}
/// <summary>
/// method clears collections of aps_arribute_t*
/// <param name="attributes">, [in], type = vector<aps_arribute_t*>& </param>
/// </summary>
void APSAPISoap::clearAttributes(vector<aps_arribute_t*>& attributes)
{
try
{
while ( 0 < attributes.size() )
{ aps_arribute_t* t = attributes[attributes.size()-1]; attributes.pop_back(); m_allocator->free_fn(m_allocator, t->attributeId); m_allocator->free_fn(m_allocator, t->dataType); m_allocator->free_fn(m_allocator, t->dataValue); delete t; }
}
catch ( ... )
{ // to do logging? }
attributes.clear();
}
/// <summary>
/// method logs send/receive SOAP over HTTP
/// <param name="attempt">, [in], type = integer, attempt tried</param>
/// <param name=buffer>, [in], type = integer, number of attempts configured</param>
/// <param name="method">, [in], type = char*, message that sent</param>
/// <param name="pResponseMsg">, [in], type = SOAPResponseMessage*, pointer to SOAPResponseMessage object</param>
/// <param name="status">, [in], type = integer, HTTP code returned (if any)</param>
/// </summary>
void APSAPISoap::logSoap
(
int attempt,
int retry,
char* buffer,
SOAPResponseMessage* pResponseMsg,
int status
)
{
int level = APSConfigData::getInstance().getLogLevel();
bool fOk = (200 == status || 500 == status);
if ( APS::LOG_ERROR <= level )
{
char msg[512] = {0}
;
char* f[] =
;
string warning;
sprintf
(
msg,
"%d%s attempt (from %d) to retry sending SOAP message %s. ",
attempt+1, f[( attempt < 3 ) ? attempt : 3],
retry,
fOk ? "succeed" : "failed"
);
warning += msg;
if ( ( 200 != status ) &&
(pResponseMsg->getStatusTransportDescription().size() || pResponseMsg->getStatusHTTPDescription().size() )
)
else
warning += "\n";
if ( APS::LOG_INFO <= level && NULL != buffer && 500 == status )
{ warning += "SOAP fault:\r"; warning += buffer; warning += "\n"; }if ( warning.size() )
{ int msgtype = fOk ? ( 200 == status ? APS::LOG_INFO : APS::LOG_WARNING ) : APS::LOG_ERROR; if ( msgtype <= level ) ClientLog::getInstance().saveMsg(warning, msgtype); } }
}
/// <summary>
/// sends Request SOAP message over HTTP
/// <param name="envlopebuffer">, [in], type = char*, buffer - keeps signed SOAP envelope</param>
/// <param name="url">, [in], type = axis2_char_t*, path to the service fotmat (pdp location)/(service)</param>
/// <param name="method">, [in], type = axis2_char_t*, service method - soap action</param>
/// <param name="pResponseMsg">, [in], type = SOAPResponseMessage*, pointer to SOAPResponseMessage object</param>
/// <param name="int">, [in], type = int, number of attempts when failure</param>
/// <param name="int">, [in], type = int, interval in min? between attempts when failure</param>
/// </summary>
bool APSAPISoap::sendSoapEnvelope
(
char* envlopebuffer,
axis2_char_t* url_str,
axis2_char_t* method,
SOAPResponseMessage* pResponseMsg,
int retry, // default = 1
int timeout // default = 10
)
{
int tt = strlen(url_str) + strlen(method);
if ( 0 > retry && 3 < retry )
retry = 1;
if ( 0 > timeout && 10 < timeout )
timeout = 10;
bool fOk = false;
axis2_url_t* url = NULL;
//axis2_http_client_t* http_client = NULL;
axis2_http_simple_request_t* simple_request = NULL;
m_body = NULL;
int status = AXIS2_FAILURE; // AXIS2_SUCCESS;
if ( NULL != envlopebuffer && strlen(envlopebuffer) )
{
#ifdef MYDBG
// FILE *fp = fopen("C:\\Myfiles\\temp
mysigned.xml","w");
// fprintf(fp,"%s", envlopebuffer);
// fclose(fp);
// cout << "SOAP envelope with signed request sent to C:\\Myfiles\\temp
mysigned.xml" << endl;
//getchar();
#endif
char content_lenght[17] =
{0};sprintf((char*)&content_lenght, "%d", strlen(envlopebuffer));
axis2_http_header_t* header_host = NULL;
axis2_http_header_t* header_soap_action = NULL;
axis2_http_header_t* header_content_type = NULL;
axis2_http_header_t* header_content_lenght = NULL;
axis2_http_request_line_t* request_line = NULL;
for ( int i = 0; i < retry; ++i )
{
url = axis2_url_parse_string(m_env, url_str);
request_line =
axis2_http_request_line_create
(
m_env,
AXIS2_HTTP_HEADER_POST,
AXIS2_URL_GET_PATH(url, m_env),
AXIS2_HTTP_HEADER_PROTOCOL_11
);
simple_request =
axis2_http_simple_request_create
(
m_env,
request_line,
NULL,
0,
NULL
);
// create HTTP headers
header_host =
axis2_http_header_create
(
m_env,
AXIS2_HTTP_HEADER_HOST,
AXIS2_URL_GET_SERVER(url, m_env)
);
header_soap_action =
axis2_http_header_create
(
m_env,
AXIS2_HTTP_HEADER_SOAP_ACTION,
method
);
header_content_type =
axis2_http_header_create
(
m_env,
AXIS2_HTTP_HEADER_CONTENT_TYPE,
AXIS2_HTTP_HEADER_ACCEPT_TEXT_XML
);
header_content_lenght =
axis2_http_header_create
(
m_env,
AXIS2_HTTP_HEADER_CONTENT_LENGTH,
(const axis2_char_t *)&content_lenght
);
// add HTTP headers
AXIS2_HTTP_SIMPLE_REQUEST_ADD_HEADER
(
simple_request,
m_env,
header_host
);
AXIS2_HTTP_SIMPLE_REQUEST_ADD_HEADER
(
simple_request,
m_env,
header_soap_action
);
AXIS2_HTTP_SIMPLE_REQUEST_ADD_HEADER
(
simple_request,
m_env,
header_content_type
);
AXIS2_HTTP_SIMPLE_REQUEST_ADD_HEADER
(
simple_request,
m_env,
header_content_lenght
);
AXIS2_HTTP_SIMPLE_REQUEST_SET_BODY_STRING
(
simple_request,
m_env,
envlopebuffer
);
if(m_http_client == NULL) { m_http_client = axis2_http_client_create(m_env, url); }
AXIS2_HTTP_CLIENT_SET_TIMEOUT(m_http_client, m_env, TIMEOUT);
// send request to server
try
{ status = //AXIS2_HTTP_CLIENT_SEND temporarely commented, Axis2c 0.94. 095 has memory leak //( // http_client, // m_env, // simple_request //) axis2_http_client_send1(m_http_client, m_env, simple_request); ; }
catch ( ... )
{
}
int statCode = getHTTPResponse(status, m_http_client, pResponseMsg);
logSoap(i, retry, m_body, pResponseMsg, statCode);
if ( 1 < retry && mustRetry(statCode) )
{ #ifdef WIN32 Sleep(timeout*1000); #else // sleep(timeout); #endif #ifdef MYDBG //cout << Log::getCurrentDateTime() << "\tsend try = " << i+1 << ", statcode = " << statCode << endl; //outt << Log::getCurrentDateTime() << "\tsend try = " << i+1 << ", statcode = " << statCode << endl; #endif }
else
break;
freeBuffer(&m_body);
freeSimpleRequest(&simple_request);
//freeClient(&http_client);
}
if ( NULL != m_body )
fOk = isResponseValid(pResponseMsg);
}
else
{ pResponseMsg->setStatusTransport(status); pResponseMsg->setStatusTransportDescription(string("SEND failure .......... nothing to send!")); }
freeBuffer(&m_body);
freeSimpleRequest(&simple_request);
//freeClient(&m_http_client);
return (fOk);
}
/// <summary>
/// method gets HTTP response (axis2_simple_response)
/// <param name="status">, [in], type = integer, status</param>
/// <param name="http_client">, [in], type = axis2_http_client_t*, axis2 http_client</param>
/// <param name="pResponseMsg">, [in], type = SOAPResponseMessage*, pointer to SOAPResponseMessage object</param>
/// <returns> type = int, status</returns>
/// </summary>
int APSAPISoap::getHTTPResponse
(
int status0,
axis2_http_client_t* http_client,
SOAPResponseMessage* pResponseMsg
)
{
int status = status0;
char cStatus[256] = {0}
;
freeBuffer(&m_body);
pResponseMsg->setStatusTransport(status);
if ( status < 0 )
{ sprintf((char*)cStatus, "SEND Failed .........Can't send the request. Status :%d", status); pResponseMsg->setStatusTransportDescription(string(cStatus)); #ifdef MYDBG // debug printf("%s\n", cStatus); // degug #endif return (status); } cout << "before recv header" << endl;
//cout << AXIS2_ERROR_GET_MESSAGE(m_env->error) << endl;
status = AXIS2_HTTP_CLIENT_RECIEVE_HEADER(http_client, m_env);
cout << "after recv header" << endl;
if ( status < 0 )
{ cout << AXIS2_ERROR_GET_MESSAGE(m_env->error) << endl; sprintf((char*)cStatus, "SEND Failed ......... Can't recieve. Status :%d", status); pResponseMsg->setStatusTransportDescription(string(cStatus)); #ifdef MYDBG // debug printf("%s\n", cStatus); //debug #endif return (status); } cout << "before get response" << endl;
axis2_http_simple_response_t*
simple_response = AXIS2_HTTP_CLIENT_GET_RESPONSE(http_client, m_env);
cout << "after get response" << endl;
if ( NULL == simple_response )
sprintf((char*)&cStatus, "%d", AXIS2_HTTP_SIMPLE_RESPONSE_GET_STATUS_CODE(simple_response, m_env));
pResponseMsg->setStatusHTTP(string(cStatus));
pResponseMsg->setStatusHTTPDescription
(
string(AXIS2_HTTP_SIMPLE_RESPONSE_GET_STATUS_LINE(simple_response, m_env))
);
#ifdef MYDBG
// debug
printf("Content Type :%s\n", AXIS2_HTTP_SIMPLE_RESPONSE_GET_CONTENT_TYPE(
simple_response, m_env));
printf("Content Length :%d\n", AXIS2_HTTP_SIMPLE_RESPONSE_GET_CONTENT_LENGTH(
simple_response, m_env));
printf("Status code :%d\n", status);
// debug
#endif
if ( 200 == status || 500 == status )
{
bool fOk = false;
try
{
char msg[512] =
;
int len2 = 0;
for ( int i = 0; 3 > i; ++i )
if ( 0 < (len2 = AXIS2_HTTP_SIMPLE_RESPONSE_GET_CONTENT_LENGTH(simple_response, m_env) ) )
break;
if ( fOk = ( 0 < len2 ) )
{
fOk = false;
try
{
// int len = AXIS2_HTTP_SIMPLE_RESPONSE_GET_BODY_BYTES(simple_response, m_env, &m_body);
int len = axis2_http_simple_response_get_body_bytes1(simple_response, m_env, &m_body, len2);
cout << "after get body bytes1" << endl;
if ( len != len2 )
{ #ifdef MYDBG // cout << Log::getCurrentDateTime() << "\tprocessID = " << getpid() << "\tlen get body = " << len << ", len2 get content = " << len2 << endl; // outt << Log::getCurrentDateTime() << "\tprocessID = " << getpid() << "\tlen get body = " << len << ", len2 get content = " << len2 << endl; #endif pResponseMsg->setStatusHTTP("-1"); sprintf(msg, "Response body length = %d is less than stated in content length header = (%d)", len2, len); pResponseMsg->setStatusHTTPDescription(msg); freeBuffer(&m_body); return (-1); }pResponseMsg->setEnvelope(string(m_body));
fOk = true;
}
catch ( ... )
{
}
}
else
}
catch ( ... )
{
}
#ifdef MYDBG
// debug
// printf("body :%s\n", ( fOk && (NULL != m_body ) ) ? m_body : " response content is empty");
//debug
#endif
if ( !fOk )
}
return (status);
}
/// <summary>
/// method validates response
/// <param name="pResponseMsg">, [in], type = SOAPResponseMessage*, pointer to SOAPResponseMessage object</param>
/// <returns> type = bool, validaty of response, no faults - response HTTP code = 200 (OK)</returns>
/// </summary>
bool APSAPISoap::isResponseValid
(
SOAPResponseMessage* pResponseMsg
)
{
bool fOk = false;
axiom_soap_envelope_t* soap_envelope = NULL;
axiom_soap_builder_t* soap_builder = NULL;
axiom_stax_builder_t* om_builder = NULL;
axiom_xml_reader_t* xml_reader = NULL;
axiom_soap_body* body = NULL;
axiom_soap_fault_t* fault = NULL;
try
{
xml_reader =
axiom_xml_reader_create_for_memory
(
m_env,
(void*)m_body,
strlen(m_body),
AXIS2_UTF_8,
AXIS2_XML_PARSER_TYPE_BUFFER
);
om_builder =
axiom_stax_builder_create(m_env, xml_reader);
soap_builder =
axiom_soap_builder_create
(
m_env,
om_builder,
AXIOM_SOAP11_SOAP_ENVELOPE_NAMESPACE_URI
);
soap_envelope =
AXIOM_SOAP_BUILDER_GET_SOAP_ENVELOPE(soap_builder, m_env);
body =
AXIOM_SOAP_ENVELOPE_GET_BODY(soap_envelope, m_env);
if ( AXIOM_SOAP_BODY_HAS_FAULT(body, m_env) )
{ // SOAP fault, HTTP code = 500, and NULL != m_body pResponseMsg->setBodyHasFault(true); parseFault ( fault = AXIOM_SOAP_BODY_GET_FAULT(body, m_env), pResponseMsg ); #ifdef MYDBG // debug printf("BODY HAS A FAULT"); // debug #endif }else
{ // OK, HTTP code = 200 fOk = true; axis2_char_t* t = AXIOM_NODE_TO_STRING ( AXIOM_NODE_GET_FIRST_CHILD ( AXIOM_SOAP_BODY_GET_BASE_NODE(body, m_env), m_env ), m_env ); string response = t; AXIS2_FREE(m_env->allocator, t); // to comfort signature validation int pos = string::npos; while ( string::npos != (pos = response.find(" xmlns=\"\"") ) ) response.erase(pos, 9); pResponseMsg->setResponse(response); } // cleanup
try
catch ( ... )
{
}
}
catch ( ... )
#ifdef MYDBG
//debug
printf("\nFinished http_client send ..........\n\n");
// debug
#endif
return (fOk);
}
/// <summary>
/// method parses SOAP fault element
/// <param name="fault">, [in], type = axiom_soap_fault_t*, soap fault</param>
/// <param name="pResponseMsg">, [in], type = SOAPResponseMessage*, pointer to SOAPResponseMessage object</param>
/// </summary>
void APSAPISoap::parseFault
(
axiom_soap_fault_t* fault,
SOAPResponseMessage* pResponseMsg
)
{
axiom_soap_fault_code*
code = AXIOM_SOAP_FAULT_GET_CODE(fault, m_env);
if ( NULL != code )
{ axiom_soap_fault_value_t* value = AXIOM_SOAP_FAULT_CODE_GET_VALUE(code, m_env); if ( NULL != value ) pResponseMsg->setFaultCode((char*)AXIOM_SOAP_FAULT_VALUE_GET_TEXT(value, m_env)); } axiom_soap_fault_reason*
reason = AXIOM_SOAP_FAULT_GET_REASON(fault, m_env);
if ( NULL != reason )
{
try
catch ( ... )
{
}
}
}
/// <summary>
/// destructor
/// cleanup
/// </summary>
APSAPISoap::~APSAPISoap(void)
{
//freeClient(&m_http_client); //commented this as the instance is no longer recreated for every request pbkar
freeBuffers();
axis2_env_free(m_env);
}
------------------------------------------------------------
2) APSAPISoap.h
///
///
/// @author lkrankur
///
///
//#pragma once
#ifndef APSAPISOAP_H
#define APSAPISOAP_H
#include "Extern.h"
#include "APSAPISoapUtil.h"
#include "RequestTO.h"
#include "SOAPResponseMessage.h"
#include "APSConfigData.h"
#include <vector>
using namespace std;
const int TIMEOUT = 60000;
/// <summary>
///Info of XACML attribute
/// </summary>
struct aps_arribute_t
{
///
axis2_char_t* attributeId;
///
axis2_char_t* dataType;
///
axis2_char_t* dataValue;
/// constructor
aps_arribute_t(axis2_env_t* env)
;
/// <summary>
/// constructor
/// <param name="id">, [in], type = axis2_char_t*, AttributeID of attribute element </param>
/// <param name="value">, [in], type = axis2_char_t*, DataValue of attribute element </param>
/// </summary>
aps_arribute_t(axis2_char_t* id, axis2_char_t* value, axis2_env_t* env)
;
/// <summary>
/// constructor
/// <param name="id">, [in], type = axis2_char_t*, AttributeID of attribute element </param>
/// <param name="id">, [in], type = axis2_char_t*, DataType of attribute element </param>
/// <param name="value">, [in], type = axis2_char_t*, DataValue of attribute element </param>
/// </summary>
aps_arribute_t(axis2_char_t* id, axis2_char_t* type, axis2_char_t* value, axis2_env_t* env)
;
};
///
/// struct to use in fixing Axis2c 0.94. 095 memory leak
/// axis2_http_client implementation
///
typedef struct axis2_http_client_impl
{
axis2_http_client_t http_client;
int sockfd;
axis2_stream_t *data_stream;
axis2_url_t *url;
axis2_http_simple_response_t *response;
axis2_bool_t request_sent;
int timeout;
axis2_bool_t proxy_enabled;
axis2_char_t *proxy_host;
int proxy_port;
axis2_char_t *proxy_host_port;
}
axis2_http_client_impl_t;
#define AXIS2_INTF_TO_IMPL(http_client) ((axis2_http_client_impl_t *)(http_client))
/// <summary>
/// ASP SOAP processing
/// </summary>
class APSAPISoap
{
/// axis2 environment
public:
static axis2_env_t* m_env; // made static for single instance pbkar
static axis2_http_client_t* m_http_client;
static int m_count;
/// axis2 memory allocation
axis2_allocator_t* m_allocator;
///
axis2_char_t* m_buffer;
axis2_char_t* m_buffer2;
axis2_char_t* m_body; // http body
void freeOMElement(axiom_element_t* om_element);
void freeOMNode(axiom_node_t* om_node);
/// <summary>
/// method adds XACML attributes as OM elements to parent node
/// <param name="attributes">, [in], type = vector<aps_arribute_t*>, collection of attribute info </param>
/// <param name="parent">, [in], type = axiom_node_t*, parent OM node </param>
/// </summary>
void addAttributes
(
vector<aps_arribute_t*> attributes,
axiom_node_t* parent
);
/// <summary>
/// method adds XACML attribute as OM element to a parent OM node
/// <param name="attribute">, [in], type = aps_arribute_t*, attribute info </param>
/// <param name="parent">, [in], type = axiom_node_t*, parent OM node </param>
/// </summary>
void addAttribute
(
aps_arribute_t* attribute,
axiom_node_t* parent
);
/// <summary>
/// method clears collections of aps_arribute_t*
/// <param name="attributes">, [in], type = vector<aps_arribute_t*>& </param>
/// </summary>
void clearAttributes(vector<aps_arribute_t*>& attributes);
/// <summary>
/// method creates XACML Request element (evaluation policy) as OM node
/// <param name="localName">, [in], type = axis2_char_t*, localName of Request element</param>
/// <param name="localNamespace">, [in], type = axis2_char_t*, namespace of localName of Request element</param>
/// <param name="pRequest">, [in], type = RequestTO*, pointer to RequestTO object </param>
/// </summary>
axiom_node_t* createRequest
(
axis2_char_t* localName,
axis2_char_t* localNamespace,
RequestTO* pRequest
);
/// <summary>
/// method creates XACML Request element (RoleRequest, ResourceRequest, DCRequest) as OM node
/// <param name="localName">, [in], type = axis2_char_t*, localName of Request element</param>
/// <param name="appname">, [in], type = axis2_char_t*, name of application</param>
/// </summary>
axiom_node_t* createRequest2
(
axis2_char_t* localName,
axis2_char_t* appname
);
/// <summary>
/// method creates OM node for Subject element and adds to Request node
/// <param name="request">, [in], type = axiom_node_t*, request node</param>
/// <param name="pSubject">, [in], type = SubjectTO*, pointer to SubjectTO object</param>
/// </summary>
void createSubject
(
axiom_node_t* request,
SubjectTO* subject
);
/// <summary>
/// method creates OM node for Resource element and adds to Request node
/// <param name="request">, [in], type = axiom_node_t*, request node</param>
/// <param name="resource">, [in], type = axis2_char_t*, resource name</param>
/// <param name="scope">, [in], type = axis2_char_t*, scope of resource</param>
/// </summary>
void createResource
(
axiom_node_t* request,
axis2_char_t* resource,
axis2_char_t* scope
);
/// <summary>
/// method creates OM node for Action element and adds to Request node
/// <param name="request">, [in], type = axiom_node_t*, request node</param>
/// <param name="action">, [in], type = axis2_char_t*, action name</param>
/// </summary>
void createAction
(
axiom_node_t* request,
axis2_char_t* action
);
/// <summary>
/// method logs send/receive SOAP over HTTP
/// <param name="attempt">, [in], type = integer, attempt tried</param>
/// <param name=buffer>, [in], type = integer, number of attempts configured</param>
/// <param name="method">, [in], type = char*, message that sent</param>
/// <param name="pResponseMsg">, [in], type = SOAPResponseMessage*, pointer to SOAPResponseMessage object</param>
/// <param name="status">, [in], type = integer, HTTP code returned (if any)</param>
/// </summary>
void logSoap
(
int attempt,
int retry,
char* buffer,
SOAPResponseMessage* pResponseMsg,
int status
);
void freeClient(axis2_http_client_t** http_client)
{
if ( NULL != *http_client )
{
axis2_http_client_impl_t* client_impl = AXIS2_INTF_TO_IMPL(*http_client);
if ( NULL != client_impl->data_stream )
{
try
catch ( ... )
{
}
client_impl->data_stream = NULL;
}
try
{ AXIS2_HTTP_CLIENT_FREE(*http_client, m_env); } catch ( ... )
{
}
}
*http_client = NULL;
}
void freeSimpleRequest(axis2_http_simple_request_t** simple_request)
{
if ( NULL != *simple_request)
{
try
catch ( ... )
{
}
*simple_request = NULL;
}
}
public:
/// <summary>
/// constructor
/// </summary>
APSAPISoap();
/// <summary>
/// method creates unsigned envelope
/// <param name="localName">, [in], type = axis2_char_t*, local name for the request element</param>
/// <param name="localNamespace">, [in], type = axis2_char_t*, namespace for the request element, could be NULL</param>
/// <param name="pRequest">, [in], type = RequestTO*, XACML request, could be NULL</param>
/// <param name="applicationName">, [in], type = axis2_char_t*, application name, could be NULL</param>
/// </summary>
bool getSoapEnvelope
(
axis2_char_t* localName,
axis2_char_t* localNamespace,
RequestTO* pRequest,
axis2_char_t* applicationName
);
/// <summary>
/// method sends Request SOAP message over HTTP
/// <param name="envlopebuffer">, [in], type = char*, buffer - keeps signed SOAP envelope</param>
/// <param name="url">, [in], type = axis2_char_t*, path to the service fotmat (pdp location)/(service)</param>
/// <param name="method">, [in], type = axis2_char_t*, service method - soap action</param>
/// <param name="pResponseMsg">, [in], type = SOAPResponseMessage*, pointer to SOAPResponseMessage object</param>
/// <param name="int">, [in], type = int, number of attempts when failure</param>
/// <param name="int">, [in], type = int, interval in sec between attempts when connection failure</param>
/// <returns> type = bool, success in sending HTTP</returns>
/// </summary>
bool sendSoapEnvelope
(
char* envelope,
axis2_char_t* url,
axis2_char_t* method,
SOAPResponseMessage* pResponseMsg,
int retry = 1,
int timeout = 10
);
/// <summary>
/// method gets HTTP response (axis2_simple_response)
/// <param name="status">, [in], type = integer, status</param>
/// <param name="http_client">, [in], type = axis2_http_client_t*, axis2 http_client</param>
/// <param name="pResponseMsg">, [in], type = SOAPResponseMessage*, pointer to SOAPResponseMessage object</param>
/// <returns> type = int, status</returns>
/// </summary>
int getHTTPResponse
(
int status,
axis2_http_client_t* http_client,
SOAPResponseMessage* pResponseMsg
);
/// <summary>
/// method validates response
/// <param name="status">, [in], type = integer, status</param>
/// <returns> type = bool, sending request needs retry</returns>
/// </summary>
bool mustRetry(int status)
;
/// <summary>
/// method validates response
/// <param name="pResponseMsg">, [in], type = SOAPResponseMessage*, pointer to SOAPResponseMessage object</param>
/// <returns> type = bool, validaty of response, no faults - response HTTP code = 200 (OK)</returns>
/// </summary>
bool isResponseValid
(
SOAPResponseMessage* pResponseMsg
);
/// <summary>
/// method parses SOAP fault element
/// <param name="fault">, [in], type = axiom_soap_fault_t*, soap fault</param>
/// <param name="pResponseMsg">, [in], type = SOAPResponseMessage*, pointer to SOAPResponseMessage object</param>
/// </summary>
void parseFault
(
axiom_soap_fault_t* fault,
SOAPResponseMessage* pResponseMsg
);
/// <summary>
/// accessor get buffer, keeps SOAP envelope
/// <returns> type = axis2_char_t*, buffer, keeps SOAP envelope
/// </summary>
axis2_char_t* getBuffer()
/// <summary>
/// accessor get buffer, keeps first child of SOAP body
/// <returns> type = axis2_char_t*, buffer, keeps first child of SOAP bod
/// </summary>
axis2_char_t* getBuffer2()
void freeBuffer(axis2_char_t** buffer)
{
if ( NULL != *buffer )
{
try
catch ( ... )
{
}
*buffer = NULL;
}
}
/// <summary>
/// method frees m_buffer, m_buffer2
/// </summary>
void freeBuffers()
/// destructor
virtual ~APSAPISoap(void);
};
#endif /* APSAPISOAP_H */