/*	File		:	F1Socket.h
**	Author		:	drclue@drclue.net	( A.K.A. Ian A Storms )
**	Description	:	Provides a handy tool for making clients and servers for TCP/IP
**				The server can be forking or non forking
**
**				Depending what system your building this under , it
**				might fuss a bit about some platform configuration issue , but
**				once you solve those minor issues , it should work.
**				Typically issues involve either library inclusion switches
**				such as -lnsl -lsocket which may or may not be configured
**				in the compiler's default library inclusions.
**
**	Platform Tweaks	:
**				  If you see something about multiply defined objects in the 
**				linkers output , it means both the compiler and the F1makefile
**				reference the library and one should edit the F1makefile to
**				comment out th eoffending library switch.
**				  If you see something about undefined objects in the 
**				linkers output , it means neither the compiler nor the F1makefile
**				reference the library and one should edit the F1makefile to
**				add the missing library inclusin switch.
**
**				Some systems store include files in different places with 
**				different names. 
**	Urls		:	http://www.kmutt.ac.th/knowledge/programming/c/unix_socket/faq/unix-socket-faq.html
*/

#ifndef _SOCKET_H
#define _SOCKET_H

#include <ctype.h>
#include <stdio.h>
#include <F1String.h>
#include <F1Memory.h>
//#define SUN 1

#include <F1types.h>		// Shared by all F1xxxx code , typically in ../F1All_c
#include <netdb.h>		// gethostbyname()

#define HIDE_BSTRING 1
#ifndef HIDE_BSTRING
 #include <bstring.h>
#endif

#include <errno.h>	//
#include <fcntl.h>	//
#include <arpa/inet.h>	//

#include <stdarg.h>	//
#include <stdio.h>	//
#include <stdlib.h>   	//
#include <signal.h>	//
#include <string.h>	//           
#include <unistd.h>	//

#include <sys/param.h>	//
#include <sys/socket.h>	//
#include <sys/time.h>	//
#include <sys/types.h>	//
#include <sys/uio.h>	//     
#include <sys/wait.h>	//
//#include <sys/systeminfo.h>    

extern F1_int	NOBLOCK(F1_int SHand);


/*	Error trapping code
**
**
*/
#define SIG_PARAM int // ... | int
void Dr_KavorkianSIGCHLD(SIG_PARAM);	// this eliminates zombie children in server mode   
void Dr_KavorkianSIGPIPE(SIG_PARAM);	// this addresses broken communication pipes
void Dr_KavorkianSIGSEGV(SIG_PARAM);	// this addresses segment violations

/*
**	Socket State
**
*/
enum	SocketStatus			{
	SocketStatusOk			, //0
	SocketStatusFailed		, //1
	SocketStatusServerFailed	, //2
	SocketStatusInitializationFailed, //3
	SocketStatusPermissionDenied	, //4
	SocketStatusAddressInUse	, //5
	SocketStatusSocketFailed	, //6
	SocketStatusAlreadyConnected	, //7
	SocketStatusTimedOut		, //8
	SocketStatusBindFailed		, //9
	SocketStatusConnectionRefused	, //10
	SocketStatusNetworkUnreachable	, //11
	SocketStatusConnectionFailed	, //12
	SocketStatusHostNotFound	, //13
	SocketStatusOutOfResources	, //14
	SocketStatusNoMoreData		, //15
	SocketStatusNoHandle		, //16
	SocketStatusCount		};//17
/*
**	select() socket function timeout 
*/
#define SELECT_TIMEOUT 1
/*
**	Defines for control characters
**
*/
#define SOH   1
#define STX   2
#define ETX   3
#define EOT   4
#define ENQ   5
#define ACK   6
#define BEL   7
#define BS    8
#define HT    9
#define LF    10
#define VT    11
#define FF    12
#define CR    13
#define SO    14
#define SI    15
#define DLE   16

typedef void	(*BUFFPRINT)	(void *		,int iLen	,void *vUserData);
extern	void	SockPrintBuffer	(void *BUFFER	,int iLen	,void *vUserData=NULL);
typedef	class	Socket	F1_SOCKET;
typedef			F1_SOCKET*	F1_pSOCKET;
#define dHOST_NAME "127.0.0.1"
class	Socket	{
protected:
	F1_int		iSHandle			;//File handle associated with socket
	F1_int		iSPortnumber			;//communicating on port number
	F1_int		iEcho				;
	F1_int		Hit_Cnt				;
	F1_char		szINBUFFER	[2048	]	;
	F1_STRING	obSHostname	;//[50	]	;
//	F1_char	szSHostname	[50	]	;
	F1_char		szHOST_NAME	[64	]	;
	struct		sockaddr_in	sa_in		;
//	struct  sockaddr_in	sa_client	;
	struct		timeval		TV_TIME		;//Used In Select Function.
	F1_int		SetStatus()			;//Assign the status of this socket class 
public:
	F1_MEMORY	omHEADERS;
	SocketStatus	iSStatus			;//Status of socket in socket class
	F1_int		GetStatus(){return iSStatus;};
	F1_pChar	setHostname(F1_pChar szHost)
			{strcpy(szHOST_NAME,szHost);return szHOST_NAME;};
	F1_int		GetPort(){return iSPortnumber;};
	F1_long		Write_Total	;//Total bytes written by this socket;
	F1_int		Write_Last	;//Number of bytes sent on last write.
	F1_long		Read_Total	;//Total bytes read by this socket;
	F1_int		Read_Last	;//Number of bytes received on last read.

		//############## Connection timing
	F1_int 		iW_sec		,iW_Msec	;
	F1_int		iSW_sec		,iSW_Msec	;
	F1_int		iR_sec		,iR_Msec	,
			iSR_sec		,iSR_Msec	;

	// Receive Hit Function
	F1_int  ((*RHF		)	(		)		);     
	//	Pointer Receive Data Function Headers
	void	((*RDFHDR	)	(void *,int	,void *vUserData)		);
	//	Pointer Recieve Data Function
	void	((*RDF		)	(void *,int	,void *vUserData)		);
	//	Received Data Function
	F1_int	RDF_PRINT		(F1_int		W_Sec	=SELECT_TIMEOUT	,
					 F1_int		W_MSec	=0		,
					 F1_int		SW_Sec	=0		,
					 F1_int		SW_MSec	=500		,
					 F1_pVoid	vUserData	=NULL	); 
	//	Displays Bytes written total and last write 
	F1_int	COUNTS			(				);

virtual void		SockPrintBuffer	(F1_pVoid	BUFFER		,
					 F1_int		LEN		,
					 F1_pVoid	vUserData=NULL	);
			//	Return Current IP Address
	F1_pChar	IP		(				);
	F1_int		ECHO		(				)
					{return(iEcho);			};
	F1_int		ECHO		(F1_int i			)
					{iEcho=i;return(iEcho)	;	};
	F1_int		HAND		(				)
					{return(iSHandle)	;	};
	F1_int		HITS		(				)
					{return Hit_Cnt		;	};
	F1_long		WTOTAL		(				)
					{return Write_Total	;	};
	F1_long		RTOTAL		(				)
					{return Read_Total	;	};
	F1_int		WLAST		(				)
					{return Write_Last	;	};
	F1_int		RLAST		(				)
					{return Read_Last	;	};
	F1_int		CLOSE		()				;

	F1_int		zprintf		(const F1_pChar fmt, ...	);

virtual	void		callbackSTATUS	(F1_pChar szStatus);

	SocketStatus	CONNECT		(F1_pChar	Hostname	,
					 F1_int		Portnumber	);
	SocketStatus	SERVER		(F1_int		Portnumber	,
					 F1_int		Max_Connect=10	);
	F1_pChar	HOSTNAME	(F1_pChar	szHostname	);
	F1_pChar	HOSTNAME	(				)
					{return(obSHostname.toString());		};
//					{return(szSHostname);		};
	F1_int		IS_OPEN		(				)
					{return(iSHandle>-1)	;	};
	F1_int		IS_READABLE	(F1_int		W_Sec	=SELECT_TIMEOUT,
					 F1_int		W_uSec	=0	);
	F1_int		IS_WRITABLE	(F1_int		W_Sec	=SELECT_TIMEOUT,
					 F1_int		W_uSec	=0	);
	F1_int		READ		(F1_pVoid	Buffer		,
					 F1_int		len		,
					 F1_int		W_Sec	=-1	,
					 F1_int		W_MSec	=-1	,
					 F1_int		SW_Sec	=-1	,
					 F1_int		SW_MSec	=-1	);
	F1_int		WRITE		(F1_pVoid	Buffer		,
					 F1_int		len		);
	F1_int		SEND_FILE	(F1_pChar	filename	);
	F1_SOCKET	&operator<<	(F1_pChar	outstring	);
	F1_SOCKET	&operator<<	(F1_char	outchar		);
	F1_SOCKET	&operator<<	(F1_STRING	outstring	);
	 Socket();
	~Socket();
	};
#endif
