#ifndef COMMON_H
#define COMMON_H

#include <stdarg.h>
#include <stdio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <pthread.h>
#include <signal.h>

#define DEFAULT_SERVER_PORT 168888
#define DEFAULT_MBOX_PORT 169000
#define str(x) #x
#define xstr(x) str(x)

#define MAX_CONTEXT_LEN (100)

#ifndef UNUSED
#define UNUSED(X) ((void)(x))
#endif

#define MAXSTRLEN (1024)

/* error codes are made of two parts
 * the low 16 bits is a global enum for the type of error
 * the high 16 bits is a local enum that only means something
 * specific to the function that was called.
 * So, an error opening a file will produce a global error FILE_NOT_READABLE
 * but the local error will be used by the function to indicate which file and/or why
 */
#define MKERROR(eGlobalStatus,eLocalStatus) (((eLocalStatus)<<16 & 0xFFFF0000)|((eGlobalStatus)0x0000FFFF))
#define GETLOCALERROR(error,dest) ((dest)=(((error)>>16)&0xFFFF))
#define GETGLOBALERROR(error,dest) ((dest)=(error)&0xFFFF)
typedef enum eERROR_CODES {
	SUCCESS=0,
	INVALID_COMMAND_LINE_ARGS,
	FILE_NOT_FOUND,
	FILE_NOT_READABLE,
	FILE_NOT_WRITABLE,
	FILE_PARSE_ERROR,
	INVALID_POINTER,
	INTEGER_OUT_OF_RANGE,
	ARRAY_OVERFLOW,
	MEMORY_ALLOCATION_FAILURE,
	ERROR_IN_LIBRARY_CALL,
	NETWORK_CONNECT_FAIL,
	ERROR_INTERRUPT,
} ERROR_STATUS;

#define ID_CLIENT (1u)
#define ID_SERVER (2u)
#define ID_MIDDLEBOX_MIN (4u)
#define ID_MIDDLEBOX_MAX (255u)



/*function to wait for a specific FILE to be ready for reading*/
ERROR_STATUS
COMMON_ReadWaitFile(FILE *phF);
/*function to wait for a specific File Descriptor (file, socket, pipe) to be ready for reading*/
ERROR_STATUS
COMMON_ReadWaitFD(int iFD);
ERROR_STATUS
COMMON_ReadProxyListFile(SSL *ptSSL,
		const char *sFilename);
ERROR_STATUS
COMMON_InitProxySet(SSL *ptSSL);
ERROR_STATUS
COMMON_InitMulticontextSet(SSL *ptSSL);
ERROR_STATUS
COMMON_AppendProxy(SSL *ptSSL,
		const char *psProxyURL);
ERROR_STATUS
COMMON_AppendClientServer(SSL *ptSSL,
		const char *psURL, int isServer);
ERROR_STATUS
COMMON_AppendContext(SSL *ptSSL,
		const char *psContextDesc);
ERROR_STATUS COMMON_SetProxyAccessPermissionByID(SSL *ptSSL, int iSliceID, int iMiddleboxNum,
							int bGrantRead, int bGrantWrite);
ERROR_STATUS COMMON_TcpConnect(int *piSocket, const char *sHost, int iPort);
void COMMON_LogErrorAndExit(int iExitCode, FILE *pLog, const char *csFmtStr, ...);
void COMMON_CheckLogErrorAndExit(int iExitCode, FILE *pLog, const char *csFmtStr, ...);
void COMMON_Log(FILE *pLog, const char *csFmtStr, ...);
void COMMON_CheckLog(int iExitCode, FILE *pLog, const char *csFmtStr, ...);

ERROR_STATUS COMMON_InitializeSSLCtx(SSL_CTX **pptCtx,
		const char *sMyKeyfile, const char *sMyPassword,
		const char *sCAKeysFile,
		unsigned int iID); /*todo - check the name of this in spec - the byte that identifies the middlebox number, client or server*/
void COMMON_DestroyCtx(SSL_CTX *ptCtx);





#endif
