/**********************************************************************
 * Copyright (c) 2005, 2008 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: RASocket.h,v 1.5 2008/05/20 16:52:04 jkubasta Exp $
 * 
 * Contributors: 
 * IBM - Initial API and implementation
 **********************************************************************/

#ifndef _RASOCKET_H_
#define _RASOCKET_H_

#ifndef _WIN32
#include <sys/socket.h>
#endif
#include "RAComm.h"
#include "RAError.h"

#if defined __cplusplus
extern "C" {
#endif


/* The command handler signature */
typedef void (*ra_commandHandler_t)(ra_command_t *command);

/* The acknowledgement handler signature */
typedef void (*ra_acknowledgementHandler_t)(ra_uint_t ticket);

/* IPV4 and IPV6 ipaddress compatable structure */
typedef struct {
	unsigned char addrLength;
	unsigned char *addr;
}ra_ipaddr_t;


typedef struct {
	BOOL connected;
	SOCKET sockfd;
	TID    tid;
	ra_commandHandler_t  commandHandler;
	ra_acknowledgementHandler_t acknowledgementHandler;
	PID processID;
	ra_string_t agentUUID;
	ra_string_t processUUID;
	ra_string_t nodeUUID;
	ra_string_t agentType;
	ra_string_t agentName;
}ra_serverInfo_t;

typedef struct {
	unsigned short addressLength;
	unsigned char *addresses;	   	
}ra_IPAddresses_t;


/** CREATE_BOUND_UDP_SERVER *****************************************
  * Creates a UDP socket server on a separate thread.  Once the server
  * is created the file descriptor and the thread ID of the server are
  * returned in a Server_info structure.
  * @param   portNum - the port you wish the server to be bound to.
  * @param resultSet - The ra_serverInfo_t structure with the
  *                    socket file descriptor, thread ID of the server,
  *                    and the function that will be called to process
  *                    incomming messages. The prototype of the fuction
  *                    must be of the type ra_messageProcessor.
  *					   THIS MEMORY MUST BE VALID FOR THE LIFE OF THE SERVER.
  * @returns  0 - create server was successful.
  *         <>0 - create failed, call ra_getlastErrorMajor/Minor
  *               to get the failure details.
  * IPV4-ONLY
  */
extern int ra_createBoundUDPServer(short portNum,
								   ra_serverInfo_t *resultSet);

/** CREATE_TCP_SERVER *****************************************
  * Creates a TCP socket server on a separate thread.  Once the server
  * is created the file descriptor and the thread ID of the server are
  * returned in a Server_info structure.
  * @param   portNum - the port you wish the server to be bound to.
  * @param resultSet - The ra_serverInfo structure with the
  *                    socket file descriptor, thread ID of the server,
  *                    and the function that will be called to process
  *                    incomming messages. The prototype of the fuction
  *                    must be of the type ra_messageProcessor.
  *					   THIS MEMORY MUST BE VALID FOR THE LIFE OF THE SERVER.
  * @returns  0 - create server was successful.
  *         <>0 - create failed, call ra_getlastErrorMajor/Minor
  *               to get the failure details.
  * IPV4-ONLY
  */
extern int ra_createTCPServer(unsigned short portNum,
							  ra_serverInfo_t *resultSet);

/** CONNECT_TO_TCP_SERVER **************************************
  * Opens a connection to a remote TCP server socket specified.
  * @param       ip  - the IP address of the remote server. THIS
  *                    IS ASSUMED TO BE IN NETWORK BYTE ORDER.
  * @param   portNum - The port the remote server is listening on.
  * @param    socket - The socket file descriptor that the resulting
  *                    connection is managed on. MUST BE PREALLOCATED.
  * @returns   0 - connect was successful
  *           <0 - connect failed, can ra_getLastErrorMajor/Minor
  *                to get the failure details.
  */
extern int ra_connectToTCPServer(ra_uint_t ip,
								 unsigned short portNum,
								 SOCKET *sockfd);

/** WRITE_TO_SOCKET  ****************************************************
  * Place a buffer of data on the sockets buffer.  The current implementation
  * only loop stupidly trying to place the data on the buffer.  A future
  * implementation should leverage a queue for each socket and handle the IO
  * asynchronously to avoid blocking until information is placed on the wire.
  * @param        fd - the file descriptor of the socket to write to.
  * @param    buffer - address to start pulling data from.
  * @param byteCount - the nuber of bytes to write to the buffer.
  * @returns     >-1 - the number of bytes written to the socket.
  *               -1 - severe socket error, write failed.
  * TO_DO: add error code settings for severe socket errors.
  */
extern int ra_writeToSocket(SOCKET fd,
							char *buffer,
							ra_uint_t byteCount);

/**
 * Resolves the formatted (e.g dot-delimited, null-terminated) local network 
 * order IPv4 address.
 * 
 * The local IP address is the network order IPv4 address of the first network 
 * interface bound to this physical host.
 *
 * The format of the local network order IPv4 address is:
 *
 *		nnn.nnn.nnn.nnn\0
 *
 * where n is a non-padded decimal (base 10) numeric.
 *
 * NOTE:  This function only supports formatting IPv4 addresses.
 *
 * @param ipAddressBuffer
 *           The string buffer to contain the formatted (e.g dot-delimited, 
 *           null-terminated) local network order IPv4 address.  This buffer
 *           must be sized sufficiently for an IPv4 (e.g. nnn.nnn.nnn.nnn\0) 
 *           address.
 * @returns  
 *           The number of characters written to the parameter buffer (excluding 
 *           null terminator character.  Otherwise, -1 if a severe error occurred. 
 *           Call ra_getLastErrorMajor/Minor() to determine the error conditions.
 * IPV4-ONLY
 */
extern short ra_getFormattedLocalIPAddress(char *ipAddressBuffer);

/** GET_LOCAL_IP_ADDRESS *******************************************
  * Determine the IP address of the first network interface bound to
  * this physical host.
  * @returns >-1 - the 32bit, network order, IPv4 address of this
  *                interface.
  *           -1 - severe error occured getting the IP address.  Call
  *                ra_getLastErrorMajor/Minor to determine the
  *                error conditions.
  */
extern long ra_getLocalIPAddress();

/** GET_LOCAL_IP_ADDRESSES *******************************************
  * Get all the IP addresses associated with this physical host.
  * @param  addr - the address of a ra_IPAddrresses_t structure to load
  *				   the IP addresses into.  THE USER MUST FREE THE STORAGE
  *                SPECIFIED IN THE addresses MEMBER when they are finished
  *                with the data.  The addresses will be in NETWORK BYTE ORDER.
  * @returns   0 - success.
  *           -1 - severe error occured getting the IP address.  Call
  *                ra_getLastErrorMajor/Minor to determine the
  *                error conditions.
  */
extern short ra_getLocalIPAddresses(ra_IPAddresses_t *addr);


/** CLOSE_SOCKET  **********************************************
  * Close and release the resources held by a socket.
  */
extern void ra_closeSocket(SOCKET sock);

/** GET_LOCAL_HOST_NAME  ***************************************
  * Load the local host name into a buffer.
  * @param        buffer - the buffer to locad the host name into.
  * @param maxNameLength - the length of the buffer.
  * @returns  0 - successfuly resolved host name
  *			 -1 - resolution failed.
  */
extern int ra_getLocalHostName(char *buffer,
							   unsigned int maxNameLength);




#ifdef _WIN32
extern int ra_win32InitializeSockets();
#endif


#if defined __cplusplus
}
#endif

#endif
