/**********************************************************************
 * Copyright (c) 2005, 2009 IBM 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
 * $Id: RAComm.h,v 1.14 2009/08/26 14:59:53 jwest Exp $
 *
 * Contributors:
 * IBM - Initial API and implementation
 **********************************************************************/

#ifndef _RACOMM_H_
#define _RACOMM_H_

#include "RATypes.h"
#include "java.h"

/* Mutex */
#ifdef _WIN32
	#define ra_critsec_t CRITICAL_SECTION
#else
	#define ra_critsec_t pthread_mutex_t
#endif

/* Macros for shared library */
#ifdef _WIN32
	#define MODULE_REFERENCE HMODULE
	#define DLL_REFERENCE HINSTANCE
	#define RESOLVE_MODULE(name) GetModuleHandle(name)
	#define LOAD_LIBRARY(name) LoadLibrary(name)
	#define RESOLVE_ENTRY_POINT(mod, entry) GetProcAddress(mod, entry)
	#ifndef CDECL
		#define CDECL __cdecl
	#endif
#elif MVS
	#include <dll.h>
	#include <dlfcn.h>
	#define MODULE_REFERENCE dllhandle *
	#define DLL_REFERENCE dllhandle *
	#define RESOLVE_MODULE(name) dlopen(name, RTLD_LAZY)
	#define LOAD_LIBRARY(name) dlopen(name, RTLD_LAZY)
	#define RESOLVE_ENTRY_POINT(mod, entry) dlsym(mod, entry)
// old: #define RESOLVE_MODULE(name) dllload(name)
// old: #define LOAD_LIBRARY(name) dllload(name)
// old: #define RESOLVE_ENTRY_POINT(mod, entry) dllqueryfn(mod, entry)
	#ifndef CDECL
		#define CDECL
	#endif
#elif _HPUX
	#include <dlfcn.h>
	#define MODULE_REFERENCE void *
	#define DLL_REFERENCE void *
	#define RESOLVE_MODULE(name) dlopen(name, RTLD_LAZY)
	#define LOAD_LIBRARY(name) dlopen(name, RTLD_LAZY)
	#define RESOLVE_ENTRY_POINT(mod, entry) dlsym(mod, entry)
	#ifndef CDECL
		#define CDECL
	#endif
#elif __OS400__
	#define MODULE_REFERENCE void *
	#define DLL_REFERENCE void *
	#define RESOLVE_MODULE(name) loadServicePgm(name)
	#define LOAD_LIBRARY(name) loadServicePgm(name)
	#define RESOLVE_ENTRY_POINT(mod, entry) findServicePgmEntry(mod, entry)
	#ifndef CDECL
		#define CDECL
	#endif
#else
	#include <dlfcn.h>
	#define MODULE_REFERENCE void *
	#define DLL_REFERENCE void *
	#define RESOLVE_MODULE(name) dlopen(name, RTLD_LAZY)
	#define LOAD_LIBRARY(name) dlopen(name, RTLD_LAZY)
	#define RESOLVE_ENTRY_POINT(mod, entry) dlsym(mod, entry)
	#ifndef CDECL
		#define CDECL
	#endif
#endif

/* Macros to ease the readability of multiplatform code */
#ifdef _WIN32										/* Win32 */
	#define BZERO(mem, len) ZeroMemory(mem,len)
	#define SLEEP(millisec) Sleep(millisec)
	#define STRDUP(dest, src)  dest=strdup(src)
	#define RA_HANDLE_NULL	NULL
	#define CLOSE_RA_HANDLE(handle)		CloseHandle(handle)
#else												/* else */
	#define _MAX_PATH 256 /* This is already defined on Windows */
	#if defined (__OS400__)
		#define BZERO(mem, len) memset(mem, '\0', len)
		#define STRDUP(dest, src)  dest=(char*)malloc(strlen(src)+1); BZERO(dest, strlen(src)+1); strcpy(dest, src) /* 236501 */
	#elif defined (_HPUX)
		#define BZERO(mem, len) memset(mem, '\0', len)
		#define STRDUP(dest, src)  dest=strdup(src)
	#else
		#define BZERO(mem, len) bzero(mem,len)
		#define STRDUP(dest, src)  dest=strdup(src)
	#endif
	#define SLEEP(millisec) sleep(millisec/1000)
	#define RA_HANDLE_NULL 0
	#define CLOSE_RA_HANDLE(handle)		close(handle)
	#define WINAPI " "
#endif


/* The master adddress of the RAC */
#define RA_MASTER_ADDRESS			"ramaster"
#ifdef _WIN32
 #define RA_PIPE_NAMESPACE			"\\\\.\\pipe\\IBMAC\\"
#else
 #define RA_PIPE_NAMESPACE			"/tmp/IBMRAC/"
 #define RA_PIPE_NAMESPACE_SHORT	"/tmp/IBMRAC"
#endif

#define JAVA_PROPERTY_CLASSPATH		"-Djava.class.path="
#define JAVA_OPTION_REDUCESIGNAL	"-Xrs"

/**
 * GENERAL PROTOCOL FORMAT:
 */

/* Constant portion of the header */
#define RA_MAGIC		0x82656780
#define RA_VERSION		0x00000100

/* The message types */
#define RA_ACKNOWLEDGEMENT_MESSAGE		0x00000000
#define RA_CONTROL_MESSAGE				0x00000001




/* The various COMMAND_ID's types from the client (server targeted flows) */
#define RA_AUTHENTICATE							0x00000001

#define RA_LAUNCH_PROCESS						0x00000010
#define RA_KILL_PROCESS							0x0000001B
#define RA_QUERY_PROCESS_LIST					0x00000011
#define RA_QUERY_AGENT_LIST						0x00000012
#define RA_QUERY_AGENT_DETAILS					0x0000001C
#define RA_REGISTER_AGENT_NOTIFICATION			0x00000013
#define RA_ATTACH_TO_AGENT						0x00000014
#define RA_DETACH_FROM_AGENT					0x00000015
#define RA_START_MONITORING_AGENT_REMOTE		0x00000016
#define RA_START_MONITORING_AGENT_LOCAL			0x00000017
#define RA_STOP_MONITORING_AGENT				0x00000018
#define RA_SET_NAME_VALUE_PAIR					0x00000019
#define RA_GET_PROPERTY_LIST					0x0000001E
/* Changed from 0x00000070 */
#define RA_MANAGE_FILE							0x0000001F



/* The extension point for custom protocol piggy-backing */
#define RA_CUSTOM_COMMAND						0x0000001A
#define RA_BINARY_CUSTOM_COMMAND				0x0000001D


/* The various COMMAND_ID's from the Remoteable Agent Controller (client targeted flows) */
#define RA_AUTHENTICATION_FAILED				0x00000002
#define RA_AUTHENTICATION_SUCCESSFUL			0x00000003
#define RA_SERVER_SECURITY_REQUIREMENTS         0x00000004
#define RA_PROCESS_LAUNCHED						0x00000020
#define RA_PROCESS_EXITED						0x00000029
#define RA_PROCESS_LIST							0x00000021
#define RA_AGENT_LIST							0x00000022
#define RA_AGENT_ACTIVE							0x00000023
#define RA_AGENT_INACTIVE						0x00000024

#define RA_AGENT_DETAILS						0x00000028
#define RA_ERROR_STRING							0x00000025
#define RA_ATTACH_SUCCESSFUL					0x00000026
#define RA_ATTACH_FAILED						0x00000027
#define RA_PROPERTY_LIST						0x0000002A

#define RA_AGENT_QUERY_STATE					0x0000002B /* Bug 54376 */
#define RA_AGENT_ATTACHED						0x0000002C /* Bug 54376 */
#define RA_AGENT_DETACHED						0x0000002D /* Bug 54376 */

/* Services provided by the server for the agents */
#define RA_LOCAL_AGENT_ACTIVE					0x00000030
#define RA_AGENT_SCOPING_INFORMATION			0x00000031
#define RA_AGENT_CONFIGURATION					0x00000032

/* Services provided by the bindings for the agent */
#define RA_AGENT_CONTROLER_AVAILABLE			0x00000050
#define RA_AGENT_CONTROLER_UNAVAILABLE			0x00000051

/* Services for peer to peer actions */
#define RA_AGENT_REQUEST_MONITOR				0x00000061
#define RA_CONTROLLER_REQUEST_MONITOR			0x00000062
#define RA_PEER_UNREACHABLE						0x00000063
#define RA_CONTROLLER_MONITOR_PEER				0x00000064 /* Not being used in native code at all? */
#define RA_AGENT_REQUEST_MONITOR_PORT			0x00000065 /* Temporary solution, should replace RA_AGENT_REQUEST_MONITOR */
#define RA_CONTROLLER_REQUEST_MONITOR_PORT		0x00000066 /* Temporary solution, should replace RA_CONTROLLER_REQUEST_MONITOR */

/* File management ids */
/* Since these constants are internal to RA_MANAGE_FILE command,
   they are not visible outside, and there is no chance of
   collision with other constants with same value */
	
#define RA_GET_FILE								0x00000001
#define RA_PUT_FILE								0x00000002
#define RA_DELETE_FILE							0x00000003

/* We might have to change this */
#define RA_RESOURCE_LOCATION					0x00000070

/* NOOP */
#define RA_NOOP									0x00000040

/**
 * Various constants that both the client and server must adhere to.
 */
#define RA_ACKNOWLEDGEMENT_MESSAGE_LENGTH 16
#define RA_CTL_PORT_NUM_SERVER	10002   /* The agent controller server port */
#define RA_SECURE_PORT_NUM_SERVER 10003;
#define RA_FILE_PORT_NUM_SERVER	10005
/* #define CTL_PORT_NUM_CLIENT		10003    The starting port wher agents will be assigned ports from */
#define MAX_DATA_LENGTH			4096	/* The size of the data buffer for sockets */

/* RKD: TO_DO: Remove the need for these constants */
#define MAX_HOST_NAME_LENGTH	128
/* end TO_DO */

#ifdef __cplusplus
extern "C" {
#endif

/** CREATE_MESSAGE  ***********************************************************
  * Allocates the memory for a message and loads it with the specified type and
  * ticket.  In order to free the memory used for this message use ra_destroyMessage()
  * @param  type  - the type of message, be it an RA_ACKNOWLEDGEMENT_MESSAGE
  *                 or a RA_CONTROL_MESSAGE.
  * @param ticket - the ticket number for this message. If this is an
  *                 RA_ACKNOWLEDGEMENT_MESSAGE this should be the ticket of the
  *                 corresponding RA_CONTROL_MESSAGE.
  * @returns !NULL - the address of the newly allocated message.
  *           NULL - inappropriate message type.
  */
extern ra_message_t* ra_createMessage(ra_uint_t type,
									  ra_uint_t ticket);


/** DESTROY_MESSAGE  **********************************************************
  * Free's all the memory currenltly held by a message and it's associated commands.
  * @param  message - the message to free all the memory of.
  * @param deepFree - Control messages consist of a list of ra_command_t stuctures
  *                   that are maintained within containers, if deepFree is true,
  *                   the actual commands are deleted along with the containers.  If
  *                   deepFree is false, only the containers are deleted.  This is
  *                   usefull for occasions when commands are copied from one message
  *                   to another without a depp copy.
  */
extern void ra_destroyMessage(ra_message_t *message,
							  BOOL deepFree);


/** ADD_COMMAND_TO_MESSAGE  ***************************************************
  * Adds a command to the message command list.
  * @param  message - the previously allocated message to append the command to.
  * @param  command - the command to append to the message command list.  If this
  *                   is NULL, the memory for the command is allocated.
  * @retruns        - a pointer to the appended command.
  */
extern ra_command_t* ra_addCommandToMessage(ra_message_t *message,
											ra_command_t *command);

/** DETERMINE_MESSAGE_LENGTH  ***************************************************
  * Determines the size buffer required to fit the information that is stored in
  * the specified ra_message_t structure.
  * @param  message - the message to determine the length of.
  * @returns     >0 - the size of buffser required.
  *               0 - the message parameter was NULL
  */
extern int ra_determineMessageLength(ra_message_t *message);

/** WRITE_MESSAGE_TO_BUFFER  **************************************************
  * Walks the data structure associted with a message and formats this into a
  * buffer that can then be transfered over a TCP connection.
  * @param       buffer - the previously allocated buffer to copy the message data to.
  * @param bufferLength - the length of the buffer.
  * @param      message - the message data structure to extract the data from.
  * @returns         >0 - the length of the buffer used for the message.
  *                  <0 - buffer is not large enough.
  */
extern unsigned int ra_writeMessageToBuffer(unsigned char *buffer,
											unsigned int bufferLength,
											ra_message_t *message);


/** READ_MESSAGE_FROM_BUFFER  *************************************************
  * Read a buffer and create a message_t data structure with all the information
  * contained in the buffer.  Use ra_destroyMessage() to free the associated memory
  * for the message_t structure when finished with it.
  * @param        buffer - the buffer with the data for the message.
  * @param messageLength - the length of the buffer containing the message data.
  * @returns       !NULL - the address of the message created.
  *                 NULL - invalid message data.
  */
extern ra_message_t* ra_readMessageFromBuffer(unsigned char *buffer,
											  unsigned long messageLength);


/** COPY_RASTRING  **************************************************************
  * Creates a copy of the source ra_string_t to the destination ar_string_t.  This
  * does not free any memory currently associated with the destination ra_string_t
  * data portion.
  * @param	destination - the ra_string_t to copy the source data to.
  * @param       source - the source ra_string_t structure.
  */
extern void ra_copyRASTRING(ra_string_t* destination,
							const ra_string_t* source);


/** CREATE_RASTRING  ************************************************************
  * Creates an ra_string_t from a null terminated array of characters.  This does
  * a complete copy of the stringBuffer.
  * @param    newString - the address of a ra_string_t structure to load.
  * @param stringBuffer - null terminated buffer of characters to copy into the
  *                       ra_string_t structure.
  */
extern void ra_createRASTRING(ra_string_t *newString,
							  const char *stringBuffer);

/** CREATE_RASTRING2  ***********************************************************
  * Creates an ra_string_t structure from a character buffer.  The data portion
  * of the string is a duplicate of that which is contained in the stringBuffer.
  * @param stringBuffer - address of a null terminated buffer of octets that
  *                       constitutes the data that wii be copied into the new
  *                       ra_string_t structure.
  */
extern ra_string_t* ra_createRASTRING2(const char *stringBuffer);

/** CREATE_RASTRING3  ************************************************************
  * Creates an ra_string_t from an array of characters.  This does
  * a complete copy of the stringBuffer for length characters.
  * @param    newString - the address of a ra_string_t structure to load.
  * @param stringBuffer - null terminated buffer of characters to copy into the
  *                       ra_string_t structure.
  * @param       length - the number of octets to copy into the string.
  */
extern void ra_createRASTRING3(ra_string_t *newString,
							  const char *stringBuffer,
							  unsigned long length);


/** CREATE_RASTRING4  ***********************************************************
  * Creates an ra_string_t structure from a character buffer.  The data portion
  * of the string is a duplicate of that which is contained in the stringBuffer.
  * @param stringBuffer - address of a buffer of octets that
  *                       constitutes the data that wii be copied into the new
  *                       ra_string_t structure.
  * @param       length - the number of octets to copy into the string.
  */
extern ra_string_t* ra_createRASTRING4(const char *stringBuffer,
									   unsigned long length);


/** DESTROY_RASTRING  **********************************************************
  *
  */
extern void ra_destroyRASTRING(ra_string_t *rastring);

/** SET_LAST_ERROR ***********************************************
  * Whenever a call fails to to any of the "ra_" functions
  * set last error is called to store a global error code that
  * relates to the failure and return -1 to the caller.  These
  * errors are defined in RAError.h and can be retrieved by the
  * caller for error determination/logging.
  */
extern void ra_setLastError(ra_uint_t major, ra_uint_t minor);

/** GET_LAST_ERROR ***********************************************
  * Retrieves the major code of the last error posted to setLastError.
  * The Major codes are located in RAError.h
  * @returns  the contents of the major error flag.
  */
extern ra_uint_t ra_getLastErrorMajor(void);

/** GET_LAST_ERROR_MINOR *****************************************
  * Retrieves the minor code of the last error posted to setLastError.
  * The minor code is the platform specific error code.
  * @returns  the contents of the minor error flag.
  */
extern ra_uint_t ra_getLastErrorMinor(void);

/** GENERATE_UUID  ************************************************
  * Creates an ra_string_t containing a UUID.
  * @param  uuid - the address of the ra_string_t to load the UUID into.
  */
extern void ra_generateUUID(ra_string_t *uuid);

/** MALLOC  ********************************************************************
  * Localized malloc to ensure the same heap is used for all allocations and
  * deletions.
  */
extern void* ra_malloc(unsigned int blockSize);

/** FREE  **********************************************************************
  * Localized free to ensure the same heap is used for all allocations and
  * deletions.
  */
extern void ra_free(void *block);


/** ATOMIC_CAS  ****************************************************************
  * Atomic compare and swap of a 32 bit element.
  * @param         addr - the address of the data to change.
  * @param  oldval_addr - the address to store the previous value into.
  * @param       newval - the newvalue to put in the memory at addr.
  * @returns -  TRUE if the CAS was successful.
  *          -  FALSE otherwise.
  */
extern BOOL ra_atomicCAS(atomic_p addr, int *oldval_addr, int newval);

/** ATOMIC_INCREMENT_BY_VALUE  *************************************************
  * Atomic increment of a value by a specified amount.
  * @param     value - the address of the value to increment.
  * @param increment - the amount to increment value by.
  * @returns  - the new value.
  */
extern int ra_atomicIncVal(volatile int *value, int increment);


/** ATOMIC_INCREMENT  **********************************************************
  * Atomic increment a value by one(1).
  * @param value - the address of the value to increment
  * @returns - the new value
  */
extern int ra_atomicInc(volatile int *value);


/** CRITICAL_SECTION_CREATE  ***************************************************
  * Create a critical section.
  *
  * The mutex is non-reentrant: a thread will block if it has already
  * entered the mutex and tries to enter it again.
  *
  * A thread must enter the mutex once in order to own it.
  * 
  * When ra_mutexCreate returns, no thread owns the mutex.
  */
extern void ra_mutexCreate(ra_critsec_t *lock);

/** CRITICAL_SECTION_ENTER  ***********************************************************
  * Enter a previously created critical section on this thread.
  */
extern void ra_mutexEnter(ra_critsec_t *lock);

/** CRITICAL_SECTION_EXIT  ************************************************************
  * Exit a previously entered critical section on this thread.
  */
extern void ra_mutexExit(ra_critsec_t *lock);

/** CRITICAL_SECTION_DESTROY  *********************************************************
  * Destroy a critical section.
  */
extern void ra_mutexDestroy(ra_critsec_t *lock);

/** CREATE_PIPE  ***************************************************************
  * Create an anonymous pipe.
  * @param  readEnd - the address to store the file descriptor of the
  *                   end of the pipe that will be read from.
  * @param writeEnd - the address to store the file descriptor of the
  *                   end of the pipe that will be written to.
  * @returns   TRUE - pipe creation was successful.
  *           FALSE - otherwise - use ra_getLastErrorMajor/Minor for
  *                   details.
  */
extern BOOL ra_createPipe(RA_HANDLE *readEnd,
				   RA_HANDLE *writeEnd);

/** CREATE_NAMED_PIPE  *********************************************************
  * Create a named pipe to share data across processes.
  * @param  name - the name of the pipe.  THIS IS PLATFORM SPECIFIC.  On
  *                Windows the name must have the following structure
  *                \\.\pipe\pipename, where pipename is the unique name
  *                for the pipe.
  *                On Unix, the name must be a filename andhense must have
  *                a valid path.
  */
extern RA_HANDLE ra_createNamedPipe(const char *name);

/** CONNECT_NAMED_PIPE  ********************************************************
  * Used by the creater of a named pipe to connect to a previously created named
  * pipe and waits for another application to open the pipe.
  * @param handle - the handle returned from a successful call to
  *                 ra_createNamedPipe()
  */
extern BOOL ra_connectToNamedPipe(RA_HANDLE *handle, const char *name);


/** DISCONNECT_NAMED_PIPE  *****************************************************
  * Called by the server pipe to disconnect from a pipe.
  */
extern BOOL ra_disconnectFromNamedPipe(RA_HANDLE handle);


/** DESTROY_NAMED_PIPE  ********************************************************
  * Called on a server pipe to destroy the pipe.
  */
extern BOOL ra_destroyNamedPipe(const char *name);

/** OPEN_NAMED_PIPE  ***********************************************************
  * Used the pipe client to open an existing named pipe.
  * @param name - the name of the named pipe.
  */
extern RA_HANDLE  ra_openNamedPipe(const char *name);


/** CLOSE_NAMED_PIPE  **********************************************************
  * Closes an open named pipe.
  * @param handle - the handle to the open named pipe.
  */
extern BOOL ra_closeNamedPipe(RA_HANDLE handle);


/** READ_FROM_NAMED_PIPE  ******************************************************
  *
  */
extern int ra_readFromNamedPipe(RA_HANDLE handle,
								char *buffer,
								int offset,
								int length,
								int *bytesRead);


/**  WRITE_FROM_NAMED_PIPE  ****************************************************
  *
  */
extern int ra_writeToNamedPipe(RA_HANDLE handle,
							 char *buffer,
							 int offset,
							 int length,
							 int *bytesWritten);

extern BOOL disableAllSecurityOfKernalObject(RA_HANDLE object);

/*
 *  OS/400 code page conversion functions
 */
#ifdef __OS400__

/* writes etoa conversion into given buffer
 * @return buffer */ 
char *as400_etoa_tobuffer(char* from_str, char *buffer); 

/* writes etoa conversion into given buffer
 * @return buffer */ 
char* as400_atoe_tobuffer(char* from_str, char *buffer); 

char* as400_etoa(char* from_str); /* 236501 */
char* as400_atoe(char* from_str); /* 236501 */
char* as400_atou(char* from_str); /* 240091 */
char* as400_utoa(char* from_str); /* 240091 */

/*****************************************************************************/
/*                                                                                                                             */
/*  This function will resolve the service program and active it.                                          */
/*  If no service program is found, or any error occurs during the activation process,             */
/*  a NULL will be returned.                                                                                          */
/*                                                                                                                             */
/*  Bugzilla #57112 - adding LOADLIBRARY support for OS400                                          */
/*  format expected for srvpgmName:                                                                            */
/*         SRVPGMNAME          max 10 characters.                                                             */
/*         LIBNAME/SRVPGMNAME   max 10 characters for each part                                     */
/*  expect there is no leading and trailing white space in the srvpgmName string                 */
/*                                                                                                                             */
/*****************************************************************************/
void *loadServicePgm(char *inputSrvpgmName); 
/*****************************************************************************/
/*                                                                                                                             */
/*  This function will Then it will find the function pointer of the entry and return it.            */
/*  If no service program is found, or any error occurs during the activation process,             */
/*  a NULL will be returned.                                                                                          */
/*                                                                                                                             */
/*  Bugzilla #57112 - adding LOADLIBRARY support for OS400                                          */
/*                                                                                                                             */
/*****************************************************************************/
void *findServicePgmEntry(void *inputSrvpgmHandle, char* entryName);
#endif



#ifndef _WIN32
/** itoa
 *  This function will convert an interger to a string
 *
 *  @param value  The integer value to be converted
 *  @param string Points to the buffer which the result is to be stored
 *  @param radix  The base of the number
 */
extern char* itoa(int value, char* string, int radix);
#endif

/* Bug 59544 */
/*
 * This function return the environment variable
 *
 */
extern int ra_getEnvironmentVariable(char* name, char* buffer, int size);

/*
 * Platform dependent code to check whether a process is alive
 */
BOOL isProcessAlive(PID pid); 

/*
 * Native encoding to Unicode conversion functions
 */
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

#ifdef __cplusplus
}
#endif

#endif
