On Sat, Nov 29, 2014 at 2:07 PM, Dan Fandrich <[email protected]>
wrote:
Well, if you only do some of those thing, then you'll have to expect that
your
program will only fail "some" of the time. In particular, I don't see any
code
to set OpenSSL locking callbacks, nor do I see a call to curl_global_init().
Perhaps there's more.  Please read those entire sections again.

>>> I have made the call curl_global_init() in my application but forgot to
put it in the sample code which i attached.
 I came across the http://curl.haxx.se/libcurl/c/threaded-ssl.html sample
multi-threaded application which uses
the SSL locking.
I have modified this application to suit my needs. Please find the attached
one (modified application)
I am creating two threads one thread will check the connection (will call
waitForHostConnection function) and other
thread will post the data (will call postDataToUrl).

Please see results of this application in different scenarios:

Starting of the application : Both the functions
return(waitForHostConnection and postDataToUrl) successful values

Pull the Ethernet cable: postDataToUrl returns 7 on curl_easy_perform and
waitForHostConnection returns 6 on curl_easy_perform

Connect the Ethernet cable back:  postDataToUrl function is successful and
waitForHostConnection continues to give 6 on curl_easy_perform

I thought some problem with my waitForHostConnection function, i have
modified my application so that both threads call postDataToUrl function.
Please see the results of this modified application in different scenarios:

Starting of the application : Both the threads(both are calling
postDataToUrl) return successful values

Pull the Ethernet cable: Both the threads returns 6 on curl_easy_perform

Connect the Ethernet cable back:  One thread will always be successful,
other thread will be successful sometimes (returns 6 for failure cases)

>
The problem arises when i pull the ethernet cable and connect it back.

I have set CURLOPT_NOSIGNAL to 1 for both handlers and set the SSL locking
callback.

Am I missing something here?? In my application both threads running
simultaneously and posting data parallely  are must. I made sure that both
threads are having different curl handlers.

Could you please let me know where I am going wrong. Your help is greatly
appreciated.

Thank you for for your help and time.
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2011, Daniel Stenberg, <[email protected]>, et al.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
 * are also available at http://curl.haxx.se/docs/copyright.html.
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 * copies of the Software, and permit persons to whom the Software is
 * furnished to do so, under the terms of the COPYING file.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ***************************************************************************/ 
/* A multi-threaded example that uses pthreads and fetches 4 remote files at
 * once over HTTPS. The lock callbacks and stuff assume OpenSSL or GnuTLS
 * (libgcrypt) so far.
 *
 * OpenSSL docs for this:
 *   http://www.openssl.org/docs/crypto/threads.html
 * gcrypt docs for this:
 *   http://gnupg.org/documentation/manuals/gcrypt/Multi_002dThreading.html
 */ 

#define USE_OPENSSL  

#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
#include <curl/easy.h>
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <syslog.h>
#include <pthread.h>

#define NUMT 2


#define TRUE 1
#define FALSE 0

# define SUCCESS 0
# define FAILURE -1

typedef enum
{
	PRIMARY_URL = 0,
	SECONDARY_URL
}
HOST_URL_ENUM;

typedef struct
{
	int		iTotSize;
	int		iWritten;
	char *	szMsg;
}
RESP_DATA_STYPE, * RESP_DATA_PTYPE;


#define CA_CERT_FILE	"ca-bundle.crt"

/* we have this global to let the callback get easy access to it */ 
static pthread_mutex_t *lockarray;

static struct curl_slist *	headers			= NULL;

static int initSSICURLHandle(CURL **, char*);
static void commonInit(CURL *, int);
static int sendDataToHost(CURL *, char *, int, char **, int *);
static size_t saveResponse(void *, size_t, size_t, void *);
static int initializeRespData(RESP_DATA_PTYPE);
static void waitForHostConnection(void);
static int chkConn(CURL *);

#ifdef USE_OPENSSL
#include <openssl/crypto.h>
static void lock_callback(int mode, int type, char *file, int line)
{
	(void)file;
	(void)line;
	if (mode & CRYPTO_LOCK) {
		pthread_mutex_lock(&(lockarray[type]));
	}
	else {
		pthread_mutex_unlock(&(lockarray[type]));
	}
}

static unsigned long thread_id(void)
{
	unsigned long ret;

	ret=(unsigned long)pthread_self();
	return(ret);
}

static void init_locks(void)
{
	int i;

	lockarray=(pthread_mutex_t *)OPENSSL_malloc(CRYPTO_num_locks() *
			sizeof(pthread_mutex_t));
	for (i=0; i<CRYPTO_num_locks(); i++) {
		pthread_mutex_init(&(lockarray[i]),NULL);
	}

	CRYPTO_set_id_callback((unsigned long (*)())thread_id);
	CRYPTO_set_locking_callback((void (*)())lock_callback);
}

static void kill_locks(void)
{
	int i;

	CRYPTO_set_locking_callback(NULL);
	for (i=0; i<CRYPTO_num_locks(); i++)
		pthread_mutex_destroy(&(lockarray[i]));

	OPENSSL_free(lockarray);
}
#endif

#ifdef USE_GNUTLS
#include <gcrypt.h>
#include <errno.h>

GCRY_THREAD_OPTION_PTHREAD_IMPL;

void init_locks(void)
{
	gcry_control(GCRYCTL_SET_THREAD_CBS);
}

#define kill_locks()
#endif

/*
 * ============================================================================
 * Function Name: commonInit
 *
 * Description	: This function contains the code for common initialization of
 * 					all the three handles needed for communication with the PWC
 *
 * Input Params	: CURL * handle	-> curl handle that needs to be configured
 *
 * Output Params: void
 * ============================================================================
 */
static void commonInit(CURL * handle, int certValdReq)
{

	printf("%d: %s: --- enter ---\n", pthread_self(), pthread_self(), __FUNCTION__);


	/* Set the NO SIGNAL option, This option is very important to set in case
	 * of multi-threaded applications like ours, because otherwise the libcurl
	 * uses signal handling for the communication and that causes the threads
	 * to go crazy and even crash. Fix done for issue 1659 (Church of LDS AmDocs
	 * Case# 130826-3983) */
	curl_easy_setopt(handle, CURLOPT_NOSIGNAL, 1L);

	/* Set the HTTP post option */
	curl_easy_setopt(handle, CURLOPT_POST, 1L);

	/* Add the headers */
	curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);

/*#ifdef DEBUG
	/* Add the debug function
	curl_easy_setopt(handle, CURLOPT_DEBUGFUNCTION, curlDbgFunc);
#endif*/

	if (certValdReq == TRUE)
	{
		printf("%d: %s: Url starts with https. Doing certificate validation\n", pthread_self(), __FUNCTION__);


		curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 1L);
		curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, 2L);
	}

	/* Set the CA certificate */
	curl_easy_setopt(handle, CURLOPT_CAINFO, CA_CERT_FILE);

	/* Set the write function */
	curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, saveResponse);

	/* Set the detection as TRUE for HTTP errors */
	curl_easy_setopt(handle, CURLOPT_FAILONERROR, TRUE);

	printf("%d: %s: --- returning ---\n", pthread_self(), pthread_self(), __FUNCTION__);

	return;
}




/*
 * ============================================================================
 * Function Name: initSSICURLHandle
 *
 * Description	:
 *
 * Input Params	:
 *
 * Output Params: SUCCESS / FAILURE
 * ============================================================================
 */
static int initSSICURLHandle(CURL ** handle, char* pszHostUrl)
{
	int					rv				= SUCCESS;
	char				szTmpURL[100]	= "";
	CURL *				locHandle		= NULL;
	int					certValdReq 	= TRUE;

	printf("%d: %s: --- enter ---\n", pthread_self(), __FUNCTION__);

	while(1)
	{
		/* Initialize the handle using the CURL library */
		locHandle = curl_easy_init();
		if(locHandle == NULL)
		{
			printf("%d: %s: Curl initialization for handle failed\n",
					pthread_self(), __FUNCTION__);
			rv = FAILURE;
			break;
		}

		curl_easy_setopt(locHandle, CURLOPT_URL, pszHostUrl);

		printf("%d: %s: Setting PWC URL = [%s]\n", pthread_self(), __FUNCTION__, pszHostUrl);


		/* Set the connection timeout */
		curl_easy_setopt(locHandle, CURLOPT_CONNECTTIMEOUT, 10);

		/* Set the total timeout */

		curl_easy_setopt(locHandle, CURLOPT_TIMEOUT, 20);


		/* Set the other common features */
		commonInit(locHandle, certValdReq);
		*handle = locHandle;

		break;
	}

	printf("%d: %s: Returning [%d]\n", pthread_self(), __FUNCTION__, rv);


	return rv;
}


static void postDataToUrl()
{
	int			rv;
	char*		szHostUrl		= "URL1";
	CURL *		curlHandle		= NULL;
	char		req[2560]		= "Message";
	int			reqSize			= strlen(req);
	char*		resp			= NULL;
	int			respSize		= 0;


	rv = initSSICURLHandle(&curlHandle, szHostUrl);

	rv = sendDataToHost(curlHandle, req, reqSize, &resp, &respSize);
	if(rv != SUCCESS)
	{
		printf("%d: %s: Failed to post data to server\n", pthread_self(), __FUNCTION__);
	}

	if (resp != NULL)
	{
		printf("%d: %s Response Received: %s \n", pthread_self(), __FUNCTION__, resp);
		free(resp);
		resp = NULL;
	}

	curl_easy_cleanup(curlHandle);
}

static void *pull_one_url(void *i)
{
	int iOption = *(int*)i;
	/*  CURL *curl;

  curl = curl_easy_init();
  curl_easy_setopt(curl, CURLOPT_URL, url);
   this example doesn't verify the server's certificate, which means we
     might be downloading stuff from an impostor
  curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
  curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
  curl_easy_perform(curl);  ignores error
  curl_easy_cleanup(curl);*/
	while(1)
	{
		switch(iOption)
		{
		case 0:
			postDataToUrl();
			break;

		case 1:
			waitForHostConnection();
			break;
		}
		sleep(3);
	}

	return NULL;
}

/*
 * ============================================================================
 * Function Name: waitForHostConnection
 *
 * Description	:
 *
 * Input Params	:
 *
 * Output Params:
 * ============================================================================
 */
static void waitForHostConnection()
{
	int 		iRetVal 	          = SUCCESS;

	while(1)
	{
		if(isHostConnected() == TRUE)
		{
			printf( "%d: %s: Host connection is available\n",pthread_self(), __FUNCTION__);
		}
		else
		{
			printf( "%d: %s: Host connection is not available, checking once more...\n",pthread_self(), __FUNCTION__);
		}

		sleep(3);
	}
}

/*
 * ============================================================================
 * Function Name: isHostConnected
 *
 * Description	:
 *
 * Input Params	: none
 *
 * Output Params: TRUE / FALSE
 * ============================================================================
 */
int isHostConnected()
{
	int	bRv				= TRUE;

	printf( "%d: %s: --- enter ---\n", pthread_self(), __FUNCTION__);


	if(SUCCESS == checkHostConn())
	{
		bRv = TRUE;
	}
	else
	{
		bRv = FALSE;
	}

	printf( "%d: %s: Returning [%s]\n", pthread_self(), __FUNCTION__,
			(bRv == TRUE)? "TRUE" : "FALSE");


	return  bRv;
}

/*
 * ============================================================================
 * Function Name: checkHostConn
 *
 * Description	:
 *
 * Input Params	:
 *
 * Output Params: SUCCESS / FAILURE
 * ============================================================================
 */
int checkHostConn()
{
	int			rv				= SUCCESS;
	int			iCnt			= 0;
	static int	host			= PRIMARY_URL;
	CURL *		curlHandle		= NULL;
	char*		szHostUrl		= "url1";
#ifdef DEBUG
	char		szDbgMsg[512]	= "";
#endif

	printf( "%d: %s: --- enter ---\n", pthread_self(), __FUNCTION__);


	while(iCnt < 2)
	{
		rv = initSSICURLHandle(&curlHandle, szHostUrl);

		if(rv == SUCCESS)
		{
			/* Curl handler initialized successfully
			 * Checking connection */
			rv = chkConn(curlHandle);
			if(rv != SUCCESS)
			{
				printf( "%d: %s: FAILED to check Host connection\n",
						pthread_self(), __FUNCTION__);
			}
			else
			{
				printf( "%d: %s: Host connection available\n", pthread_self(), __FUNCTION__);
			}
		}

		if(rv == SUCCESS)
		{
			printf( "%d: %s: Breaking from the loop\n", pthread_self(), __FUNCTION__);

			break;
		}

		/* If the first host is not working then try the next host */
		host ^= 1;
		iCnt++;

		printf( "%d: %s: Trying again..\n", pthread_self(), __FUNCTION__);
	}

	printf( "%d: %s: Returning [%d]\n", pthread_self(), __FUNCTION__, rv);


	return rv;
}

/*
 * ============================================================================
 * Function Name: chkConn
 *
 * Description	:
 *
 * Input Params	:
 *
 *
 * Output Params: SUCCESS / FAILURE
 * ============================================================================
 */
static int chkConn(CURL * curlHandle)
{
	int				rv				= SUCCESS;
	long			lCode			= 0L;
#ifdef DEBUG
	char			szDbgMsg[256]	= "";
#endif

	printf( "%d: %s: --- enter ---\n", pthread_self(), __FUNCTION__);

	while(1)
	{
		curl_easy_setopt(curlHandle, CURLOPT_POST, 0L);
		curl_easy_setopt(curlHandle, CURLOPT_NOBODY, 1);
		curl_easy_setopt(curlHandle, CURLOPT_FOLLOWLOCATION, 1);

		rv = curl_easy_perform(curlHandle);
		if(rv == CURLE_OK)
		{
			printf( "%d: %s: Perform SUCCESS\n", pthread_self(), __FUNCTION__);

		}
		else
		{
			printf( "%d: %s: Return Value from PERFORM = [%d]\n",
					pthread_self(), __FUNCTION__, rv);

		}

		rv = curl_easy_getinfo(curlHandle, CURLINFO_RESPONSE_CODE, &lCode);

		printf( "%d: Return Value RESPONSE CODE = [%d], [%ld]\n",
				pthread_self(), __FUNCTION__, rv, lCode);


		if(rv == 0 && lCode == 200)
		{
			printf( "%d: Got Successful respcode from host\n",
					pthread_self(), __FUNCTION__);


			rv = SUCCESS;
		}
		else
		{
			printf( "%d: Didnt get the good resp code from host\n"
					, pthread_self(), __FUNCTION__);
			rv = FAILURE;
		}

		break;
	}

	if(curlHandle != NULL)
	{
		curl_easy_cleanup(curlHandle);
	}

	printf( "%d: %s: Returning [%d]\n", pthread_self(), __FUNCTION__, rv);

	return rv;
}

int main(int argc, char **argv)
{
	pthread_t tid[NUMT];
	int i;
	int error;
	(void)argc; /* we don't use any arguments in this example */
	(void)argv;

	/* Add data to the headers */
	headers = curl_slist_append(headers, "Content-Type:text/xml");

	/* Must initialize libcurl before any threads are started */
	curl_global_init(CURL_GLOBAL_ALL);

	init_locks();

	for(i=0; i< NUMT; i++) {
		error = pthread_create(&tid[i],
				NULL, /* default attributes please */
				pull_one_url,
				(void *)(&i));
		if(0 != error)
			fprintf(stderr, "Couldn't run thread number %d, errno %d\n", i, error);
		else
			fprintf(stderr, "Thread %d, gets %d\n", i, tid[i]);
	}

	/* now wait for all threads to terminate */
	for(i=0; i< NUMT; i++) {
		error = pthread_join(tid[i], NULL);
		fprintf(stderr, "Thread %d terminated\n", i);
	}

	kill_locks();

	return 0;
}


/*
 * ============================================================================
 * Function Name: sendDataToHost
 *
 * Description	: This function sends the XML data to the PWC server, using the
 * 					appropriate CURL handle.
 *
 * Input Params	:
 * 				PWC_URL_TYPE_ENUM urlType -> constant telling which handle to
 * 												use
 * 				unsigned char *	  data	  -> the XML data that needs to be sent
 * 				int				  size	  -> size of the data
 *
 * Output Params: SUCCESS / FAILURE
 * ============================================================================
 */
static int sendDataToHost(CURL * curlHandle, char * req, int reqSize,
												char ** resp, int * respSize)
{
	int				rv				   = SUCCESS;
	char			szCurlErrBuf[4096] = "";
	RESP_DATA_STYPE	stRespData;

	printf("%d: %s: --- enter ---\n", pthread_self(), __FUNCTION__);

	while(1)
	{
		/* Initialize the response data */
		rv = initializeRespData(&stRespData);
		if(rv != SUCCESS)
		{
			printf("%d: %s: Initialization of response data FAILED\n"
																, pthread_self(), __FUNCTION__);



			break;
		}

		/* Set some curl library options before sending the data */
		curl_easy_setopt(curlHandle, CURLOPT_WRITEDATA, &stRespData);
		curl_easy_setopt(curlHandle, CURLOPT_POSTFIELDS, (void *) req);
		curl_easy_setopt(curlHandle, CURLOPT_POSTFIELDSIZE, reqSize);
		curl_easy_setopt(curlHandle, CURLOPT_ERRORBUFFER, szCurlErrBuf);

		printf("%d: %s: Posting the data to the server\n", pthread_self(), __FUNCTION__);



		/* post the data to the server */
		rv = curl_easy_perform(curlHandle);

		printf("%d: %s: curl_easy_perform done, rv = %d\n", pthread_self(), __FUNCTION__, rv);



		if(rv == CURLE_OK)
		{
			*resp = stRespData.szMsg;
			*respSize = stRespData.iWritten;

			printf("%d: Data Posted Succesfully\n");

			printf("%d: %s: Response Len = [%d]\n", pthread_self(), __FUNCTION__,
														stRespData.iWritten);


		}
		else
		{
			switch(rv)
			{
			case CURLE_UNSUPPORTED_PROTOCOL: /* 1 */
				/*
				 * The URL you passed to libcurl used a protocol that this libcurl does not support.
				 * The support might be a compile-time option that you didn't use,
				 * it can be a misspelled protocol string or just a protocol libcurl has no code for.
				 */
				printf("%d: %s: protocol not supported by library\n",
																pthread_self(), __FUNCTION__);

				break;

			case CURLE_URL_MALFORMAT: /* 3 */
				/*
				 * The URL was not properly formatted.
				 */
				printf("%d: %s: URL not properly formatted\n",
																pthread_self(), __FUNCTION__);

				break;

			case CURLE_COULDNT_RESOLVE_HOST: /* 6 */
				/*
				 * Couldn't resolve host. The given remote host was not resolved.
				 */
				printf("%d: %s: Couldnt resolve server's address\n", pthread_self(), __FUNCTION__);

				break;

			case CURLE_COULDNT_CONNECT: /* 7 */
				/*
				 * Failed to connect() to host or proxy.
				 */
				printf("%d: %s: Failed to connect server\n",
																pthread_self(), __FUNCTION__);

				break;

			case CURLE_HTTP_RETURNED_ERROR: /* 22 */
				/*
				 * This is returned if CURLOPT_FAILONERROR is set TRUE
				 * and the HTTP server returns an error code that is >= 400.
				 */
				printf("%d: %s: Got HTTP error while posting\n",
																pthread_self(), __FUNCTION__);

				break;

			case CURLE_WRITE_ERROR: /* 23 */
				/*
				 * An error occurred when writing received data to a local file,
				 * or an error was returned to libcurl from a write callback.
				 */
				printf("%d: %s: Failed to save the response data\n",
																pthread_self(), __FUNCTION__);



				rv = FAILURE;
				break;

			case CURLE_OUT_OF_MEMORY: /* 27 */
				/*
				 * A memory allocation request failed.
				 * This is serious badness and things are severely screwed up if this ever occurs.
				 */
				printf("%d: %s: Facing memory shortage \n",
																pthread_self(), __FUNCTION__);



				rv = FAILURE;
				break;

			case CURLE_OPERATION_TIMEDOUT: /* 28 */
				/*
				 * Operation timeout.
				 * The specified time-out period was reached according to the conditions.
				 */
				printf("%d: %s: Timeout happened while receiving\n",
																pthread_self(), __FUNCTION__);

				break;

			case CURLE_SSL_CONNECT_ERROR: /* 35 */
				/*
				 * A problem occurred somewhere in the SSL/TLS handshake.
				 *
				 */
				printf("%d: %s: SSL/TLS Handshake FAILED\n",
																pthread_self(), __FUNCTION__);

				break;

			case CURLE_PEER_FAILED_VERIFICATION: /* 51 */
				/*
				 * The remote server's SSL certificate or SSH md5 fingerprint was deemed not OK.
				 */
				printf("%d: %s: Server's SSL certificate verification FAILED\n",
							pthread_self(), __FUNCTION__);

				break;

			case CURLE_SEND_ERROR: /* 55 */
				/*
				 * Failed sending network data.
				 */
				printf("%d: %s: Failed to post the request data\n", pthread_self(), __FUNCTION__);

				break;

			case CURLE_RECV_ERROR: /* 56 */
				/*
				 * Failure with receiving network data.
				 */
				printf("%d: %s: Failed to receive the response\n",
																pthread_self(), __FUNCTION__);

				break;

			case CURLE_SSL_CACERT: /* 60 */
				/*
				 * Peer certificate cannot be authenticated with known CA certificates.
				 */
				printf("%d: %s: Couldnt authenticate peer certificate\n",
																pthread_self(), __FUNCTION__);

				break;

			case CURLE_SSL_CACERT_BADFILE: /* 77 */
				/*
				 * Problem with reading the SSL CA cert (path? access rights?)
				 */
				printf("%d: %s: Cant find SSL CA sertificate [%s]\n",
												pthread_self(), __FUNCTION__, CA_CERT_FILE);

				break;

			default:
				printf("%d: %s: Error [%d] occured while posting\n",
															pthread_self(), __FUNCTION__, rv);

				break;
			}

			if(stRespData.szMsg != NULL)
			{
				free(stRespData.szMsg);
				stRespData.szMsg = NULL;
			}


			printf("%d: %s: Lib Curl Error [%s]\n",pthread_self(), __FUNCTION__, szCurlErrBuf);
		}

		break;
	}

	printf("%d: %s: Returning [%d]\n", pthread_self(), __FUNCTION__, rv);


	return rv;
}


/*
 * ============================================================================
 * Function Name: initializeRespData
 *
 * Description	: This function is used for the initial setting of the response
 * 					data structure which would then be used for storing XML
 * 					response retrieved from the server being contacted.
 *
 * Input Params	: RESP_DATA_PTYPE stRespPtr -> pointer to response structure
 *
 * Output Params: SUCCESS / FAILURE
 * ============================================================================
 */
static int initializeRespData(RESP_DATA_PTYPE stRespPtr)
{
	int		rv				= SUCCESS;
	char *	cTmpPtr			= NULL;


	printf("%d: %s: --- enter ---\n", pthread_self(), __FUNCTION__);


	cTmpPtr = (char *) malloc(4096 * sizeof(char));
	if(cTmpPtr != NULL)
	{
		/* Initialize the memory */
		memset(cTmpPtr, 0x00, 4096 * sizeof(char));
		memset(stRespPtr, 0x00, sizeof(RESP_DATA_STYPE));

		/* Assign the data */
		stRespPtr->iTotSize = 4096;
		stRespPtr->iWritten = 0;
		stRespPtr->szMsg	= cTmpPtr;
	}
	else
	{
		printf("%d: %s: Memory allocation FAILED\n", pthread_self(), __FUNCTION__);



		rv = FAILURE;
	}

	printf("%d: %s: Returning [%d]\n", pthread_self(), __FUNCTION__, rv);



	return rv;
}


/*
 * ============================================================================
 * Function Name: saveResponse
 *
 * Description	: This function performs the job of saving the XML response
 * 					coming from the server into a buffer provided as parameter.
 * 					This function is passed to the CURL library, and the
 * 					library would call this function, not us.
 *
 * Input Params	:
 * 					void * ptr -> pointer to the data that needs to be copied
 * 					size_t size-> size of one element of data
 * 					size_t cnt -> count of data members
 * 					void * des -> our buffer where the response is saved
 *
 * Output Params: totLen -> length of data saved
 * ============================================================================
 */
static size_t saveResponse(void * ptr, size_t size, size_t cnt, void * des)
{
	int				rv				= SUCCESS;
	int				iSizeLeft		= 0;
	int				totLen			= 0;
	int				iReqdLen		= 0;
	char *			cTmpPtr			= NULL;
	RESP_DATA_PTYPE	respPtr			= NULL;


	printf("%d: %s: --- enter ---\n", pthread_self(), __FUNCTION__);

	while(1)
	{

		respPtr = (RESP_DATA_PTYPE) des;
		totLen = size * cnt;
		iSizeLeft = respPtr->iTotSize - respPtr->iWritten;

		if(totLen > iSizeLeft)
		{
			iReqdLen = (respPtr->iTotSize + totLen - iSizeLeft) + 1/* one extra buffer for NULL at the end for safety purpose*/;

			cTmpPtr = (char *) realloc(respPtr->szMsg, iReqdLen);
			if(cTmpPtr == NULL)
			{
				printf("%d: %s: Reallocation of memory FAILED\n",
						pthread_self(), __FUNCTION__);



				rv = FAILURE;
				break;
			}

			memset(cTmpPtr + respPtr->iWritten, 0x00, iReqdLen - respPtr->iWritten);

			respPtr->iTotSize = iReqdLen;
			respPtr->szMsg = cTmpPtr;
		}

		memcpy(respPtr->szMsg + respPtr->iWritten, ptr, totLen);
		respPtr->iWritten += totLen;

		rv = totLen;

		break;
	}

	printf("%d: %s: Returning [%d]\n", pthread_self(), __FUNCTION__, rv);



	return rv;
}
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html

Reply via email to