#ifndef _CSH_
#define _CSH_ 1
using namespace std;
#include <string>
#include <iostream>
#include <thread>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <time.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 <libgen.h>
#include <math.h>
#include "Debug.h"
typedef struct ShareS { // shared items between procs or threads
int conns; // overall connections# both in ring and mash
int msgs; // overall forwards# both in ring and mash
int act; // active nodes# both in ring and mash
sem_t counterSem; // semaphore for counters
} ShareT, *ShareP;
#define ShareA(v) if((v = (ShareP) mmap(NULL, sizeof(ShareT), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0)) < 0) SYSERR("mmap")
typedef struct CSS { // top level attributes
string text; // text to be sent in messages
int ttl; // TTL for circulating msgs
int mp0; // TCP port of first mash node
int mn; // intended # of nodes in mash
int rp0; // TCP port of first ring node
int rn; // intended # of nodes in ring
struct timespec pace; // pacing time quantum
int pacing; // pacing indicator
int issl; // ssl switch: 0=no_ssl, 1=ssl, 2=both
int connThreshold; // connection retry threshhold
int connTO; // connection timeout in usecs
int selTO; // selection timeout in secs
string cePath; // SSL certs path
string caPath; // CA certs path
ShareP shP;
CSS(DebugP, char*);
} *CSP;
typedef struct HeaderS { // container header
int ttl;
int ts;
int remPort;
HeaderS();
HeaderS(int);
int len();
} *HeaderP;
typedef struct PayloadS { // payload structure
time_t ts;
char text;
PayloadS();
PayloadS(const char *);
int check(PayloadS*);
char *deliver();
string digest();
void sabotage();
int len();
} *PayloadP;
typedef struct ContainerS { // data container sent throug mash or ring
HeaderS hdr;
PayloadS payl;
int len();
} ContainerT, *ContainerP;
typedef class DataC { // data sent and received
public:
DebugP deP;
ContainerP contP;
int dataLen;
// int transferLen;
DataC();
DataC(DebugP);
int dttl();
int ttl();
void load(int, const char*);
string unld();
string digest();
bool dataOk();
int ts();
int remPort();
int remPort(int);
} *DataP;
typedef struct SocketS { // info about sockets allocated in node
int remPort;
int sc;
SSL *sslP;
} *SocketP;
typedef enum{ring, mash} topology;
typedef enum{client, server} nodeside;
class ConstellationC { // constellation of communication nodes (mash or ring)
DebugP deP;
public:
topology topo;
int ssl, first, nodes, *forwP;
ConstellationC();
ConstellationC(topology, int);
int run();
};
typedef ConstellationC *ConstellationP;
class NodeC : public ConstellationC { // attributes and operations of one node of constellation (mash or ring)
public:
DebugP deP;
int locPort;
int last;
int kicker;
int closing;
thread closingThread; // thread to close client side sockets
DataC data;
int len;
int ssc;
SocketP cliSides;
SocketP srvSides;
SSL_CTX *ctxP;
NodeC(ConstellationP, int);
int run();
void mainLoop();
void bindN();
void conn(int, int);
void acc(int);
void closeSocket(int, nodeside);
int getN(int);
int readN(int);
int putN(int);
int writeN(int);
int next_node();
void forward(int);
void closeClients();
};
typedef NodeC *NodeP;
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(char*);
extern void abend();
#define SYSERR(e) LOG(0, "%s: %s (%d)", (char*)e, strerror(errno), errno), abend(deP)
#define SSLERR(e) ssl_err((char*)e, deP), abend(deP)
#define SOFTERR(e) LOG(0, e), fflush(stderr)
#define HARDERR(e) SOFTERR(e), abend(deP);
extern CSP csP;
#endif