#ifndef _CSH_
#define _CSH_ 1

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <errno.h>
#include <time.h>
#include <math.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/time.h>
#include <openssl/ssl.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <sys/wait.h>
#include <sys/select.h>
#include <sys/mman.h>
#include <semaphore.h>
#include <signal.h>
#include <execinfo.h>
#include <libgen.h>

typedef struct DebugS {
	char id[128];
	char msg[256];
} DebugT, *DebugP;
#define DebugA() (DebugP)malloc(sizeof(DebugT))

typedef struct ShareS {
	int conns;
	int msgs;
	int act;
	int mashOpenClientCount;
	int mashOpenSSLClientCount;
	sem_t counterSem;
	sem_t debugSem;
} ShareT, *ShareP;
#define ShareA(v) if((v = mmap(NULL, sizeof(ShareT), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0)) < 0) SYSERR("mmap")

typedef struct CSS {
	DebugT debug;
	int debMaxLev;
	int port0;
	int portZ;
	char *text;
	int ttl;
	int mp0;
	int mn;
	int rp0;
	int rn;
   struct timespec pace;
   int pacing;
	int issl;
	int connThreshold;		// connection retry threshhold
	int connTO;					// connection timeout in usecs
	int selTO;					// selection timeout in secs
	char *ceP;					// -->SSL certs path
	char *caP;					//	-->CA  certs path
	ShareP shP;
	char home[128];
} CST, *CSP;
#define CSA(v) if((v = (CSP)malloc(sizeof(CST))) < 0) SYSERR("malloc")

typedef struct HeaderS {
	int ttl;
	int ts;
	int listPort;
} HeaderT, *HeaderP;
typedef struct PayloadS {
	time_t ts;
	char text;
} PayloadT, *PayloadP;
typedef struct ContainerS {
	HeaderT hdr;
	PayloadT payl;
} ContainerT, *ContainerP;
typedef struct DataS {
	DebugT debug;
	ContainerP contP;
	int dataLen;
} DataT, *DataP;
#define DataA(v) if((v = (DataP)malloc(sizeof(DataT))) < 0) SYSERR("malloc")

typedef struct SocketS {
	int remPort;
	int sc;
	SSL *sslP;
} SocketT, *SocketP;
#define SocketA(v) if((v = (SocketP)malloc(sizeof(SocketT))) < 0) SYSERR("malloc")

typedef enum{ring, mash} topology;
typedef struct NodeS {
	DebugT debug;
	topology topo;
	int ssc;
	int locPort;
	int first;
	int last;
	int nodes;
	int nodeIdx;
	int kicker;
	int *forw;
	int closing;
	pthread_t closingThread;
	SocketP cliSides;
	SocketP srvSides;
	DataT data;
	int len;
	int ssl;
	SSL_CTX *ctx;
	struct sigaction *sigactP;
} NodeT, *NodeP;
#define NodeA(v) if((v = (NodeP)malloc(sizeof(NodeT))) < 0) SYSERR("malloc")
typedef enum{client, server} nodeside;

extern void debug_init();
extern char *gpa(struct sockaddr *);
extern void gai(int, struct addrinfo *ai, DebugP);
#define GAI(level, ai) gai(level, ai, deP)
extern void ssl_err(DebugP, char*);
extern void abend(DebugP);
extern void Node(topology, int*, int, int, int, int);
extern void Data(DataP, DebugP);
extern int dttlData(DataP);
extern int ttlData(DataP);
extern int remPortData(DataP);
extern DataP loadData(DataP, int, char*);
extern char *unldData(DataP);
extern char *digest24Data(DataP, char *);
extern int chkData(DataP);
extern void sabotageData(DataP);
extern int tsData(DataP);
extern void back_trace();
extern void pre(char *);
extern void deb(int, DebugP);
extern void err(int, char *, DebugP);

#define DEBID(...) sprintf(deP->id, __VA_ARGS__)
#define LOG(level, ...) sprintf(deP->msg, __VA_ARGS__), deb(level, deP)
#define SYSERR(e) LOG(0, "%s: %s (%d)", e, strerror(errno), errno), abend(deP)
#define SSLERR(e) ssl_err(deP, e)
#define SOFTERR(e) LOG(0, e), fflush(stderr)
#define HARDERR(e) SOFTERR(e), abend(deP);
#define ERR(e) perror(e), exit(EXIT_FAILURE)

#define PACING SIGUSR1

extern CSP csP;

#endif
