Feeds:
Posts
Comments

Archive for the ‘Axis2/C’ Category

NTLM auth support for Axis2/C

I have added NTLM authentication support for Axis2/C recently.

I have added this support by writing a dynamically loadable library called axis2_ntlm which wrap an existing NTLM library. Currently it wrap a NTLM library called Heimdal [1].

However one can write his own wrapper for the external NTLM library of his choice.

When using Heimdal, if I send same messages to a server requiring NTLM authentication using different connections, I noticed that some authentication requests fail with server responding that the provided credentials are not valid, even when the provided credentials are perfectly valid. If I repeat the same request again it is authorized. This intermittent failure come from Heimdal, because when linked with a wrapper for a different external library like libntlm[2] it works fine. It seems that Heimdal no longer actively support it’s NTLM library, so I encourage ppl to use libntlm instead. I have attached the code for libntlm wrapper for Axis2/C NTLM below[3] as a text file. Also you can download this libntlm wrapper for Axis2/C at [4]. One use this code to compile a wrapper for Axis2/C by studing how it is done for Heimdal. Note the additions to configure.ac, samples/configure.ac when it is done for Heimdal.

[1] http://www.h5l.org/

[2] http://josefsson.org/libntlm/

[3] https://damithakumarage.files.wordpress.com/2011/06/libntlm_wrapper-c.doc

[4] https://github.com/damitha23/libntlm-axis2c.git

Read Full Post »

I have a proxy service deployed in my esb server. This service will verify the signature of the incoming messages and decrypt them before sending it to the target service. I send the messges to ESB using WSO2 wsclient which is bundled with WSO2 WSF/C. To sign the messages I use Alice’s private key. To encrypt the messages I use the public key received from ESB ( You can find Alice’s samples keys bundled with WSF/C samples. More on ESB keys during this article).

To deploy that service I followed the following procedure. I first created a simple pass through service using the Add/Proxy Service menu. I gave the target server as my WSAS instance running on a separate server. After that I selected the created proxy service and added security using the Sign and Encrypt option. I also gave the private and trusted key store as wso2carbon.jks. I also added Alice’s public key to the wso2carbon.jks key store using WSO2 ESB admin console facilities.

Now my services are ready, I wanted to use WSO2 wsclient (A command line web services client tool) to access the service through ESB. To learn more about how to use wsclient and how to secure your messages using it please refer to [1] and [2]. To encrypt and sign messages wsclient use server certificate in PEM format. We give the server certificate using –recipient-certificate option.  Usually I use my wsclient command line tool to access web services deployed in Apache2 server. So I knew how to generate my server certificates in PEM format from  PKCS key stores. But did not know how to generate PEM certificates from JKS key stores. Howerver I could not find a direct way to do this. Following is how I did this using java keytool and openssh x509 commands.

keytool -export -file wso2carbon.cer -keystore /wso2carbon.jks -alias wso2carbon

In this step we create a wso2carbon.cer file using wso2carbon.jks server keystore. Here you will be asked the password for the keystore entry alias.

After that I executed the following command to create the recipient certificate in PEM format.

openssl x509 -out wso2carbon.pem -outform pem -in wso2carbon.cer -inform der

Now I could use the created pem certificate to execute the following command to access the service

./wsclient –log-level error –no-wsa –soap –no-mtom –sign-body –key /alice_key.pem –certificate /alice_cert.cert –recipient-certificate /wso2carbon.pem –encrypt-payload –policy-file ./policy.xml  http://localhost:8280/services/SignEncProxy < ./data/POService.xml

 

[1] https://damithakumarage.wordpress.com/2008/10/04/access-secure-enabled-web-services-from-command-line/

[2] https://damithakumarage.wordpress.com/2010/05/25/using-wso2-wsclient-generate-your-custom-soap-messages-for-you/

 

Read Full Post »

WSO2 wsclient can consume web services from your platforms command line shell. I have already introduced it in my previous entry titled Access security enabled web services from command line and in an article titled Calling web services from the shell

Today I discuss about generating your custom soap messages using wsclient. You may need pre-built custom soap messages for various purposes. For example your performance test tool may need pre-built soap messages in order to generate load for the target server, or you may need to customize each of your message sent to the target server and observe how server react.

Here is a sample usage of wsclient to send a message to target server at http://localhost:8280/services/EchoProxy

./wsclient –action echo –log-level debug –soap –no-mtom http://localhost:8280/services/EchoProxy < ./data/msg.xml

So your input file msg.xml contain

<m:buyStocks xmlns:m=”http://services.samples/xsd”&gt;
<m:order>
<m:symbol>IBM</m:symbol>
<m:buyerID>asankha</m:buyerID>
<m:price>140.34</m:price>
<m:volume>200000</m:volume>
</m:order>
<m:order>
<m:symbol>MSFT</m:symbol>
<m:buyerID>ruwan</m:buyerID>
<m:price>23.56</m:price>
<m:volume>803000</m:volume>
</m:order>
<m:order>
<m:symbol>SUN</m:symbol>
<m:buyerID>indika</m:buyerID>
<m:price>14.56</m:price>
<m:volume>500000000</m:volume>
</m:order>
</m:buyStocks>

Now we want instead of sending that message to the server, dump it to a file.

./wsclient –action echo –log-level debug –soap –no-mtom –soap-dump http://localhost:8281/services/EchoProxy < ./data/msg.xml > output.xml

The trick is –soap-dump option passed to the wsclient.

Here is the message dumped into a file by the wsclient

<soapenv:Envelope xmlns:soapenv=”http://www.w3.org/2003/05/soap-envelope”&gt;
<soapenv:Header xmlns:wsa=”http://www.w3.org/2005/08/addressing”&gt;
<wsa:To>http://localhost:8281/services/EchoProxy</wsa:To&gt;
<wsa:Action>echo</wsa:Action>
<wsa:MessageID>urn:uuid:da14cd20-6820-1df1-2c4f-000000000000</wsa:MessageID>
</soapenv:Header>
<soapenv:Body>
<m:buyStocks xmlns:m=”http://services.samples/xsd”&gt;
<m:order>
<m:symbol>IBM</m:symbol>
<m:buyerID>asankha</m:buyerID>
<m:price>140.34</m:price>
<m:volume>200000</m:volume>
</m:order>
<m:order>
<m:symbol>MSFT</m:symbol>
<m:buyerID>ruwan</m:buyerID>
<m:price>23.56</m:price>
<m:volume>803000</m:volume>
</m:order>
<m:order>
<m:symbol>SUN</m:symbol>
<m:buyerID>indika</m:buyerID>
<m:price>14.56</m:price>
<m:volume>500000000</m:volume>
</m:order>
</m:buyStocks>
</soapenv:Body>
</soapenv:Envelope>

You may argue that you can hand write these messages without going into hassle of downloading and using wsclient to do the task. But the real important usage comes when your target server expect ws secured soap messages. How do you encrypt and/or sign your messages?. wsclient come into rescue.
Say you need to encrypt and sign your message. Here is how you do it in wsclient.

./wsclient –log-level error –no-wsa –soap –no-mtom –sign-body –key $WSFC_HOME/samples/src/rampartc/data/keys/ahome/alice_key.pem –certificate $WSFC_HOME/samples/src/rampartc/data/keys/ahome/alice_cert.cert –recipient-certificate /home/damitha/projects/perftest-framework/wsclient/wso2carbon.pem –encrypt-payload –policy-file ./policy.xml –soap-dump http://localhost:8280/services/EchoProxy < ./data/message1k.xml > output.xml

I can take you one step further by showing how this could be useful when using httperf,  a populer opensource performance testing tool.

Say you need to load your server with signed and encryped timestamped messages with a nonce. Each of your messages should be different. That means your input file to httperf should not contain the same message.

My trick is to generate an input file with as much as different messages by using the following script, which uses wsclient

echo -n "/services/SignEncProxy method=POST contents=\"" > inputfile
./wsclient --log-level error --no-wsa --soap --no-mtom --sign-body --key $WSFC_HOME/samples/src/rampartc/data/keys/ahome/alice_key.pem --certificate $WSFC_HOME/samples/src/rampartc/data/keys/ahome/alice_cert.cert --recipient-certificate /home/damitha/projects/perftest-framework/wsclient/wso2carbon.pem --encrypt-payload --policy-file ./policy.xml --soap-dump http://localhost:8280/services/EchoProxy < ./data/message1k.xml > inputfile_temp
perl -e 'while (<>) { if (! /\|$/ ) { chomp; } print ;}' inputfile_temp >> inputfile

echo -n "\"" >> inputfile
echo "" >> inputfile
echo "" >> inputfile

for i in {1..10}
do
echo -n "/services/SignEncProxy method=POST contents=\"" >> inputfile
./wsclient --log-level error --no-wsa --soap --no-mtom --sign-body --key $WSFC_HOME/samples/src/rampartc/data/keys/ahome/alice_key.pem --certificate $WSFC_HOME/samples/src/rampartc/data/keys/ahome/alice_cert.cert --recipient-certificate /home/damitha/projects/perftest-framework/wsclient/wso2carbon.pem --encrypt-payload --policy-file ./policy.xml --soap-dump http://localhost:8280/services/EchoProxy < ./data/message1k.xml > inputfile_temp
perl -e 'while (<>) { if (! /\|$/ ) { chomp; } print ;}' inputfile_temp >> inputfile

echo -n "\"" >> inputfile
echo "" >> inputfile
echo "" >> inputfile

done
sed s/'"'/'\\\"'/g < inputfile > x
sed s/'Envelope>\\"'/'Envelope\>"'/g < x > y
sed s/'contents=\\"'/'contents="'/g < y > z
cat z > inputfile

rm x y z inputfile_temp

Above script would generate an httperf input file for http post with 11 different soap messages.
In the above example codes and scripts make sure that you replace paths with your own environment.

Read Full Post »

Axis2/C has strong support for message level web services security. It also provides wire level protection between web services and its clients. In this guide I do not detail basics of Axis2/C web services. You can refer for them else where. WSO2 Oxygen Tank is a good place for you to refer. Here are the steps.

1. Make sure your Apache2 web server is installed with mod_ssl module support.

2. Configure and install Axis2/C with ssl support

3. Configure your Apache2 server with ssl support

4. Configure your clients to access secured web service.

Following are the steps in detail

1. Install Apache2 with ssl support:

Make sure that your Apache2 server is installed with mod_ssl support. Here is how to check your installed modules.

httpd -l

If your Apache2 server does not already have mod_ssl  module support you may need to configure it again and install.

Here is an example configuration.

%./configure --prefix=/usr/local/apache2  --enable-ssl --enable-setenvif  --enable-mods-shared="mod_log_config mod_status mod-mime mod-dir"

2. Configure and install Axis2/C with SSL support:

First you need to install openssl dev package. In Ubuntu and Dabian related distros you can install it by

%sudo apt-get install libssl-dev

%sh configure --prefix=${AXIS2C_HOME} --enable-openssl=yes --with-apache2=/usr/local/apache2/include

%make
%make install

3. Configure Apache2 server for ssl support:
You need to create certificates for your server. Here I just show you the command how
to create a self signed certificate for testing purposes. A detailed explanation on
creating your certificates with certificate authorities please refer to

http://httpd.apache.org/docs/2.0/ssl/ssl_faq.html#selfcert

%openssl req -new -x509 -nodes -out server.crt -keyout server.key

In httpd.conf Add the virtual host entry for https server as following
Note that you need to replace ‘localhost’ with your running server name
and replace the paths with the paths to above generated key/certificates.

<VirtualHost localhost:443>
DocumentRoot “/usr/local/apache2/htdocs”
SSLEngine on
SSLCertificateFile /usr/local/apache2/damitha-cert/server.crt
SSLCertificateKeyFile /usr/local/apache2/damitha-cert/server.key
</VirtualHost>


You can test your ssl enabled server with the following command
%openssl s_client -connect localhost:443

4. Configure your Axis2/C client to support ssl

Create the client certificates to access your secured web service as following

%echo |\
openssl s_client -connect localhost:443 2>&1 |\
sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > client_cert.pem

Remember to replace the ‘localhost’ in the above command with your secured
server url

Now to send ssl secured messages using your Axis2/C client uncomment the
following https related entries in axis2.xml

<transportReceiver name=”https”>
<parameter name=”port” locked=”false”>6060</parameter>
<parameter name=”exposeHeaders” locked=”true”>false</parameter>
</transportReceiver>

<transportSender name=”https”>
<parameter name=”PROTOCOL” locked=”false”>HTTP/1.1</parameter>
</transportSender>

<parameter name="SERVER_CERT">/path/to/ca/certificate</parameter>
Remember to replace the server certicate path with the path to the client certificate created above.
Now you are good to go with your secured Axis2/C web services.

Read Full Post »

I’m very much pleased to acknowledge the WSF/C++ release from WSO2. This is a long felt need for the WSO2 web services stacks in C/C++. As I have pointed out in my article comparing WSF/C and gSOAP as well as article compaing WSF/C and RogueWave’s HydraExpress the main minus point for WSF/C stack was its lacking of C++ API level support. Even at the time I was compairing these stacks WSF/C++ 1.0.0 was available but without code generation support and server side support. WSF/C++ is a fully featured release with API’s for writing services as well as complete code generation support. So now I can speak of WSF/C++ as a complete web services stack for C/C++ web services development with the added advantage of providing C++ support over the already feature rich WSF/C stack.
While using the C++ API’s for writing web services, developers can always exploit the underline WSF/C core API’s to his advantage.

Read Full Post »

Dinesh Premalal in his blog post on Axis2/C with cbthread explain that using cbthreads he ran about 100,000 concurrent requests using Axis2/C client. The reason for this achievement is because of the non-preemptive and continuation-based threads implemented with cbthreads. However in his next blog Axis2/C with pthreads he goes on explaining how he used similer Axis2/C client with pthreads and could only run about 300 concurrent requests. This is predictable because each thread in pthreads consume considerable amount of memory in it’s stack-based nature implementation. In adition Dinesh’s program for pthreads does not use a thread pool which cause the the program to create threads until system resources exhausted.

In cbthreads home page it is mentioned

“A downside of having a non-preemptive thread system is that you cannot assign threads to blocking system calls as you can with pthreads, and have threads run while the system call blocks. If you do, the entire process blocks.”

This reason highly discourage using cbthreads for Axis2/C. Besides pthreads is provenly portable among numerous platforms. In my opinion what Axis2/C needs is a good thread pool implementation using pthreads.

In search of a good thread pool using pthreads I came across this one which seems to be a good candidate. I wrote a similer client as Dinesh wrote for testing cbthreads using this pthreads thread pool.

Axis2/C client With pthread threadpool for 10,000 request
real 1m9.974s
user 0m34.890s
sys 0m9.297s

Axis2/C client with cbthreads for 10,000 requests
real 3m29.835s
user 0m13.621s
sys 0m8.857s

This shows that using pthreads with a good thread pool is the right way to use pthreads for Axis2/C with it’s all proven features.

To try this with Axis2/C echo.cpp client program do the following steps.

1. Download the pthread pool from here and build the source by executing make in the root source folder.

2. Install Axis2/C. I assume you installed it into /axis2c/deploy.(You need Axis2/C 1.6 or build it from svn source)

3. Copy the following echo.cpp source file and build.sh build script into the same source folder.

4. Execute build.sh and run the exectuable program.

One thing to notice about the echo.cpp code is creating service client for each thread. Main overhead of creating service client is associated with creating the Axis2/C main cofiguration context. This is reduced by creating each service client passing the same configuratin context as following.

conf_ctx = axis2_svc_client_get_conf_ctx(svc_client, env);
svc = axis2_svc_client_get_svc(svc_client, env);
svc_client = axis2_svc_client_create_with_conf_ctx_and_svc(env, client_home, conf_ctx, svc);

echo.cpp

#include <TThreadPool.hh>
#include <stdio.h>
#include <stdio.h>
#include <axiom.h>
#include <axis2_util.h>
#include <axiom_soap.h>
#include <axis2_client.h>
#include <axis2_conf_ctx.h>
#include <axis2_svc.h>

#define NTHREADS 10000
#define POOLSIZE 100

axiom_node_t *
build_om_payload_for_echo_svc(const axutil_env_t * env);

typedef struct _svcinfo {
    const axutil_env_t *env;
    axis2_svc_client_t *svc_client;
    axis2_char_t *address;
}svc_info_t;

static void svc_client_send_request (void *v);

class echo : public TThreadPool::TJob
{
public:
   echo ( int id )
       : TThreadPool::TJob( id )
   {
   }

public:
  void run ( void * arg )
  {
      svc_client_send_request(arg);
  }
};

int
main(int argc, char **argv)
{
    const axutil_env_t *env = NULL;
    const axis2_char_t *address = NULL;
    axis2_endpoint_ref_t *endpoint_ref = NULL;
    axis2_options_t *options = NULL;
    const axis2_char_t *client_home = NULL;
    axis2_svc_client_t *svc_client = NULL;
    int i = 0;
    TThreadPool * pool = NULL;
    axis2_conf_ctx_t *conf_ctx = NULL;
    axis2_svc_t *svc = NULL;

    /* Set up the environment */
    env = axutil_env_create_all("echo.log", AXIS2_LOG_LEVEL_TRACE);

    /* Set end point reference of echo service */
    address = "http://localhost:9091/axis2/services/echo";
    if (argc > 1)
    {
        if (axutil_strcmp(argv[1], "-h") == 0)
        {
            printf("Usage : %s [endpoint_url]\n",
                   argv[0]);
            printf("use -h for help\n");
            return 0;
        }
        else
        {
            address = argv[1];
        }
    }
    printf("Using endpoint : %s\n", address);

    /* Set up deploy folder. It is from the deploy folder, the configuration is picked up
     * using the axis2.xml file.
     * In this sample client_home points to the Axis2/C default deploy folder. The client_home can
     * be different from this folder on your system. For example, you may have a different folder
     * (say, my_client_folder) with its own axis2.xml file. my_client_folder/modules will have the
     * modules that the client uses
     */
    client_home = AXIS2_GETENV("AXIS2C_HOME");
    if (!client_home || !strcmp(client_home, ""))
        client_home = "../..";

    /* Create service client */
    svc_client = axis2_svc_client_create(env, client_home);
    if (!svc_client)
    {
        printf
            ("Error creating service client, Please check AXIS2C_HOME again\n");
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
                        "Stub invoke FAILED: Error code:" " %d :: %s",
                        env->error->error_number,
                        AXIS2_ERROR_GET_MESSAGE(env->error));
        return -1;
    }

    /* Set service client options */
    axis2_svc_client_set_options(svc_client, env, options);

    /* Engage addressing module */
    axis2_svc_client_engage_module(svc_client, env, AXIS2_MODULE_ADDRESSING);

    conf_ctx = axis2_svc_client_get_conf_ctx(svc_client, env);
    svc = axis2_svc_client_get_svc(svc_client, env);
    pool = new TThreadPool( POOLSIZE );

    for (i = 0; i < NTHREADS; i++)
    {
        echo *job = new echo(i);
        axis2_svc_client_t *t_client = NULL;
        svc_info_t *svcinfo = NULL;

        svcinfo = (svc_info_t *) malloc (sizeof (svc_info_t));
        if (!svcinfo)
        {
            fprintf (stderr, "no enough memory\n");
            exit (1);
        }
        svcinfo->env = env;
        t_client = axis2_svc_client_create_with_conf_ctx_and_svc(env, client_home, conf_ctx, svc);
        svcinfo->svc_client = t_client;
        svcinfo->address = (axis2_char_t *) address;
        pool->run( job, (void *) svcinfo, true );
    }

    pool->sync_all();
    axis2_svc_client_free(svc_client, env);
    printf("success\n");
    return 0;
}

/* build SOAP request message content using OM */
axiom_node_t *
build_om_payload_for_echo_svc(
    const axutil_env_t * env)
{
    axiom_node_t *echo_om_node = NULL;
    axiom_element_t *echo_om_ele = NULL;
    axiom_node_t *text_om_node = NULL;
    axiom_element_t *text_om_ele = NULL;
    axiom_namespace_t *ns1 = NULL;
    axis2_char_t *om_str = NULL;

    ns1 =
        axiom_namespace_create(env, "http://ws.apache.org/axis2/services/echo",
                               "ns1");
    echo_om_ele =
        axiom_element_create(env, NULL, "echoString", ns1, &echo_om_node);
    text_om_ele =
        axiom_element_create(env, echo_om_node, "text", NULL, &text_om_node);
    axiom_element_set_text(text_om_ele, env, "Hello World!", text_om_node);
    om_str = axiom_node_to_string(echo_om_node, env);

    if (om_str)
    {
        AXIS2_FREE(env->allocator, om_str);
        om_str = NULL;
    }
    return echo_om_node;
}

static void
svc_client_send_request (void *v)
{
    svc_info_t *svcinfo;
    const axutil_env_t *env;
    axis2_svc_client_t *svc_client;
    axiom_node_t *payload = NULL;
    axiom_node_t *ret_node;
    axis2_options_t *options = NULL;
    axis2_endpoint_ref_t *endpoint_ref = NULL;
    axis2_char_t *address = NULL;

    svcinfo = (svc_info_t *)v;
    env = svcinfo->env;
    svc_client = svcinfo->svc_client;
    address = svcinfo->address;

    options = (axis2_options_t *) axis2_svc_client_get_options(svc_client, env);
    if(!options)
    {
        options = axis2_options_create(env);
        axis2_svc_client_set_options(svc_client, env, options);
    }

    endpoint_ref = axis2_endpoint_ref_create(env, address);

    axis2_options_set_to(options, env, endpoint_ref);
    axis2_options_set_action(options, env,
                             "http://ws.apache.org/axis2/c/samples/echoString");

    /* Build the SOAP request message payload using OM API. */
    payload = build_om_payload_for_echo_svc(env);

    /* Send request */
    ret_node = axis2_svc_client_send_receive(svc_client, env, payload);

    if (ret_node)
    {
        axiom_node_free_tree(payload, env);
        axiom_node_free_tree(ret_node, env);
        ret_node = NULL;
        printf("Invoke SUCCESSFUL\n");
    }
    else
    {
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
                        "Stub invoke FAILED: Error code:" " %d :: %s",
                        env->error->error_number,
                        AXIS2_ERROR_GET_MESSAGE(env->error));
        printf("echo client invoke FAILED\n");
    }

    if(svcinfo)
    {
        AXIS2_FREE(env->allocator, svcinfo);
        svcinfo = NULL;
    }
    axis2_svc_client_free(svc_client, env);
}

build.sh

gcc *.cpp -oecho -I./src libthrpool.a -lstdc++ -lpthread -L/axis2c/deploy/lib -lm -laxis2_engine -laxutil -laxis2_axiom -I. -I/axis2c/deploy/include/axis2-1.6.0/

Read Full Post »

I found no documentation on basic memory handling conventions in Axis2/C. Until this content appear under a developer guide for Axis2/C, here are some facts that could be useful in preparing such document. Here I don’t talk about advance facilities provided regarding memory management in Axis2/C. However I’ll provide links below for such documents. I just talk about few points that could be useful for service and client developers in handling memory which are not included in the above mentioned documents.

Memory handling in services

Axis2/C services should be written implementing the API defined in axis2_svc_skeleton.h. Basically if your service name is echo you will have two implementation files echo_skeleton.c and echo.c. echo_skeleton.c will contain the functions implementing the API including life-cycle management functions of the service. They are echo_create(), echo_init(), echo_free, echo_invoke and echo_on_fault(). Within the create function you will instantiate axis2_svc_skeleton_t stuct and assign your services operation structure to the svc_skeleton_t structures operation structure so that your functions will be called from withing the Axis2/C engine.
Within free function you will free the sekelton structure you allocated in create function. When the service unloaded this function is called by the engine to free the service resources. If you allocate any additional stuff withing the service create function it is your responsibility to free them then and there.
In invoke function you can check the operation requested and call the appropriate service function from echo.c where all the service logic functions are implemented. The response nodes if any are created withing these service functions will be freed by the Axis2/C engine. Also any property you set there into Axis2/C configuration context structures will be garbaged by the Axis2/C engine according to their life scope. Any additional stuff you created there must be handled by your self.

In the on_fault function you can create a fault node which could be inserted as detail element in creating soap faults by the engine when something goes wrong when invoking your service. It is the responsibility of the Axis2/C engine to free such nodes.

Memory handling in clients

Most of the memory allocated in the client side (including SOAP request and reply messages), should be cleaned in the client side itself. Memory allocated for properties are taken care of by the SOAP engine. SOAP engine reclaims the memory allocated for properties based on the scope (Request, Session or Application) you set for each property.

You can read more advance information regarding memory management in Axis2/C in the following articles. However some of these articles are old so if you find it is difficult to understand them with the current Axis2/c code base don’t hesitate to ask in the Axis2/C developer list.

Overcoming Memory Related Issues in Axis2/C

Memory Management with Apache Axis2/C

Read Full Post »

Older Posts »