/*******************************************************************************
 * Copyright (c) 2005, 2009 Intel Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Andy Kaylor, Intel - Initial API and Implementation
 *    Karla Callaghan, Intel - Added Command Parsing functions
 *
 * $Id: TPTPUtils.h,v 1.29 2009/09/24 21:02:06 jwest Exp $
 *******************************************************************************/ 

#ifndef __TPTPUTILS_H__
#define __TPTPUTILS_H__

#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#endif

#ifdef MVS
        #include <sys/sem.h>
#endif

#include "tptp/TPTPTypes.h"
#include "tptp/TPTPErrorCode.h"

#ifdef __cplusplus
extern "C"
{
#endif

#define	BIN_DIR	"bin"
#define SHUTDOWNCONNECTION_XML_NAME	"shutdownConnectionInfo"

/* Functions for letting this library manage memory */
void* tptp_malloc( unsigned int size );
void tptp_free( void* block );
void* tptp_realloc( void* ptr, unsigned int size );


/* List utilities */
typedef struct _tptp_node_t
{
	void*                data;
	struct _tptp_node_t* next;
} tptp_node_t;

typedef tptp_int32 (*tptp_node_destructor_ptr_t)( tptp_node_t* node );
typedef tptp_int32 (*tptp_node_copy_ptr_t)( const tptp_node_t* orig, tptp_node_t* copy );

typedef struct
{
	tptp_node_t* head;
	tptp_node_t* tail;
	long count;
	tptp_node_destructor_ptr_t destroyNode;
	tptp_node_copy_ptr_t       copyNode;
} tptp_list_t;

void tptp_list_init( tptp_list_t* list );
tptp_int32 tptp_list_add( tptp_list_t* list, void *data );
tptp_int32 tptp_list_remove( tptp_list_t* list, void *data );
void tptp_list_clear( tptp_list_t* list );
tptp_int32 tptp_list_clone( tptp_list_t* list, const tptp_list_t* orig );
void tptp_list_setNodeDestructor( tptp_list_t* list, tptp_node_destructor_ptr_t destructorFunc );
void tptp_list_setNodeCopier( tptp_list_t* list, tptp_node_copy_ptr_t copyFunc );

typedef struct _tptp_param_t
{
	char* name;
	char* value;
} tptp_param_t;

tptp_param_t* initParamT(const char* name, const char* value);
tptp_param_t* cloneParamT(const tptp_param_t* param);
int copyParamNode(const tptp_node_t* node, tptp_node_t* nodeCopy);
void destroyParamT(tptp_param_t* param);
int destroyParamNode(tptp_node_t* node);



typedef struct {
	int portNumber;
	char *hostConfig;
	char *allowHosts;
	int securityEnabled;
	char *sslProviderLib;
	tptp_list_t* params;
} SocketConfigInfo;

/* Define the various types of host addressing wildcards and types */
#ifdef __cplusplus
	typedef enum tptp_host_wildcard_t {TPTP_HW_ALL, TPTP_HW_LOCAL, TPTP_HW_UNKNOWN, TPTP_HW_KNOWN, TPTP_HW_NET, TPTP_HW_NAMED, TPTP_HW_MAX_VALUE};
#else
	enum _tptp_host_wildcard_t {TPTP_HW_ALL, TPTP_HW_LOCAL, TPTP_HW_UNKNOWN, TPTP_HW_KNOWN, TPTP_HW_NET, TPTP_HW_NAMED, TPTP_HW_MAX_VALUE};
	typedef enum _tptp_host_wildcard_t tptp_host_wildcard_t;
#endif

typedef struct {
	int  allow;						/* Is this an Allow entry or a Deny? */
	tptp_host_wildcard_t  wildcard;		/* Is this a range of addresses or an exact address? */
	unsigned char net[4];				/* The network address information in network byte order.  Note that this is IPV4 specific */
	unsigned char mask[4];				/* the subnet mask information in network byte order.  Note that this is IPV4 specific */
	char *hostname;

	unsigned char netipv6[16];
	unsigned char maskipv6[16];

	int netAndMaskAreIpv4;

}network_t;

typedef struct _network_list_node {
	network_t  *entry;
	struct _network_list_node *next;
	struct _network_list_node *previous;
}network_list_node_t;

typedef struct {
	network_list_node_t *head;
	network_list_node_t *tail;
}network_list_t;

/* Command parsing utilities */
int getDestinationID( const char* cmd, int *dest );
/* these next 3 are for TL configuration via the serviceconfig.xml file */
int getSocketConfigInfo( const char* config, SocketConfigInfo *socketInfo );
int getNamedPipeConfigInfo( const char* config, char **pipeName);
int getSharedMemConfigInfo( const char* config, char **memName);

int parseCommand( const char*       cmd, 
                  int*              sourceID,
                  int*              context,
                  char**            interfaceID,
                  char**            cmdName,
                  tptp_list_t**		paramList );

int getIntegerParam( const char*          paramName,
                     const tptp_list_t*	  paramList,
                     int*                 value );

int getPIDParam( const char*          paramName,
                 const tptp_list_t*	  paramList,
                 PID*                 value );

int getStringParam( const char*          paramName,
                    const tptp_list_t*	 paramList,
                    char**               value );

int getStringListParam( const char*          paramName,
                        const tptp_list_t*	 paramList,
                        tptp_list_t*         value );

int getXmlFragmentParam( const char*         paramName,
                         const tptp_list_t*  paramList,
                         char**              value );

int parsePropertyListEntry( char* property, char** name, char** type, char** value );

int getXMLElements( const char* cmd, tptp_list_t** paramList);

int getXmlFragmentElementString( const char* fragment, char* rootName, char* elemName, char **value );
int getXmlFragmentElementInt( const char* fragment, char* rootName, char* elemName, int* value );
int getXmlFragmentElementPID( const char* fragment, char* rootName, char* elemName, PID *value );

/* String utilities */
int isEqualString( const char* str1, const char* str2 );


/* Lock utilities */
#ifdef _WIN32

/* The single-writer/multiple-reader guard
   compound synchronization object */
typedef struct _SWMR 
{
   /* This critical section guards access to the other objects
    * managed by this data structure and also indicates
    * whether any writer threads are writing.                    */
   CRITICAL_SECTION cs;

   /* This manual-reset event is signaled when
    * no reader threads are reading.            */
   HANDLE hEventNoReaders;

   LONG numReaders;
} Lock_t;

#else /* Not _WIN32 */

#if defined _LINUX_X86 || defined _LINUX_390 || defined _HPUX
  #include <pthread.h>

  typedef struct 
  {
    pthread_mutex_t mutex;
    pthread_cond_t  rcond;
    pthread_cond_t  wcond;
    long readCount;
    short waiting_writers;
    short active_writers;
  } Lock_t;
  extern void rwlock_WaitingReaderCleanup(void *arg);
  extern void rwlock_WaitingWriterCleanup(void *arg);
#else
  #ifdef __MVS__
    #include <pthread.h>
  #endif
  typedef pthread_rwlock_t Lock_t;
#endif

#endif /* Ends ifdef _WIN32 */

int tptp_initializeLock(Lock_t *lock);
void tptp_deleteLock(Lock_t *lock);
int tptp_getWriteLock(Lock_t *lock);
void tptp_releaseWriteLock(Lock_t* lock);
int tptp_getReadLock(Lock_t *lock);
void tptp_releaseReadLock (Lock_t *lock);

#if defined _LINUX_X86 || defined _LINUX_390 || defined _HPUX
void rwlock_WaitingReaderCleanup(void *arg);
void rwlock_WaitingWriterCleanup(void *arg);
#endif

/* Semaphore utilities */
#ifdef _WIN32
typedef struct 
{
	HANDLE hSem;
} Semaphore_t;

#else /* Not _WIN32 */

	#ifdef __MVS__ /* OS390 */
	    #include <sys/sem.h>

	    typedef struct
	    {
	        key_t sem;
	    } Semaphore_t;
	#else
		//#include <pthread.h>
		#include <semaphore.h>

		typedef struct
		{
			sem_t sem;
		} Semaphore_t;
	#endif /* Ends ifdef __MVS__ */
#endif /* Ends ifdef _WIN32 */

int tptp_initializeSemaphore(Semaphore_t *pSem);
int tptp_deleteSemaphore(Semaphore_t *pSem);
int tptp_waitSemaphore(Semaphore_t *pSem);
int tptp_postSemaphore(Semaphore_t *pSem);


#ifdef MVS

/** This must be called before the following two functions may be used. */
void tptp_zosInitializeSemaphoreLock();

/** This is used to register semaphores which are not properly deleted, and 
 * therefore must be deleted at program end. */
void tptp_zosRegisterUndeletedSemaphore(Semaphore_t *pSem);

/** This deletes all undeleted semaphores. This should only be called ONCE at program termination. */
void tptp_zosDeleteUndeletedSemaphores();


#endif

/*int tptp_waitSemaphoreTimeout(Semaphore_t *pSem, int timeoutInSecs);*/

int getFileSize(char *fileName);
int validateDirectory(char* dirName);
int isAbsolutePath(const char* path);
char* getTempDir();

/* String utilities */
void tptp_strcopy(tptp_string* destination, const tptp_string* source);

void tptp_strcreate(tptp_string* newString, const char* stringBuffer);

void tptp_strconcat(tptp_string* destString, tptp_string* srcString);

void tptp_strdestroy(tptp_string* tptpstring);

tptp_int32 tptp_strlen(const tptp_string* source);

tptp_int32 tptp_strcmp(const tptp_string* string1,const tptp_string* string2);

char *tptp_getErrorString(int tptpErrNum);

int tptp_encodeBase64(unsigned char* binaryData, int dataLen, tptp_string* encodedData, int bufferLen);
int tptp_decodeBase64(tptp_string* base64Data, int encodedLen, unsigned char* decodedData, int bufferLen);

/* ICONV functions - src from RAC */
extern size_t native2unicode(char** out, char* in, size_t size_in);
extern size_t unicode2native(char** out, char* in, size_t size_in);
#ifdef _WIN32
int mb2wc(wchar_t** lpWideCharStr, char* lpMultiByteStr, int cbMultiByte, int cp);
int wc2mb(char** lpMultiByteStr, wchar_t* lpWideCharStr, int cchWideChar, int cp);
#else
int convert(char** out, char* in, size_t size_in, char* to_cp, char* from_cp);
#endif

void initializeXMLPlatformUtils();
void terminateXMLPlatformUtils();

int parseHostList(const char *initString, network_list_t **nList);
int parseUserList(const char *initString, char **user, char **userlist);

char* trim(char *str);

int vrfusrpwd(tptp_string *userid, tptp_string *password);

#ifdef __cplusplus
} /* Ends extern C */
#endif

#endif /* __TPTPUTILS_H__ */
