Blob Blame Raw
#ifndef COMMON_H
#define COMMON_H


#include <cstdio>


#define logf(...) do { fprintf(stdout, __VA_ARGS__); fflush(stdout); } while(0)


#define HideDebugMSG(...) do {} while(0)

#ifdef NDEBUG
#	define ShowDebugMSG(...) do {} while(0)
#else
#	define ShowDebugMSG(...) do { \
		logf("DEBUG %16lld %s:%s:%d:", monotonicTime(), __FILE__, __func__, __LINE__); \
		logf(" " __VA_ARGS__); \
		logf("\n"); \
	} while(0)
#endif



enum {
	PACKET_SIZE     = 470,
	PACKETS_COUNT   = 8*PACKET_SIZE,
	TCP_BUFFER_SIZE = PACKET_SIZE*PACKETS_COUNT,
	CRYPT_BLOCK     = 128,
	HASH_SIZE       = 32,
};


enum : unsigned short {
	CMD_SHIFT   = 12,
	CMD_MASK    = (unsigned short)(0xffff << CMD_SHIFT),
	SIZE_MASK   = (unsigned short)(~CMD_MASK),
	
	CMD_DATA      = 0,
	CMD_CONFIRM   = 1,
	CMD_TERM      = 2,
	CMDMAX        = 3,
};



typedef unsigned long long Time;
Time monotonicTime();
Time globalTime();
const char* bitsToString(const void *data, int size);


inline bool cycleLequal(unsigned int a, unsigned int b)
	{ return (b - a) <= 0x7fffffff; }
inline bool cycleLess(unsigned int a, unsigned int b)
	{ return !cycleLequal(b, a); }
inline bool timeLequal(Time a, Time b)
	{ return (b - a) <= 0x7fffffffffffffffull; }
inline bool timeLess(Time a, Time b)
	{ return !timeLequal(b, a); }



class Address {
public:
	union {
		struct { unsigned int ipUInt; };
		struct { unsigned char ip[4]; };
	};
	unsigned short port;
	inline Address(): ipUInt(), port() { }
	inline bool operator<(const Address &other) const {
		return ipUInt < other.ipUInt ? true
		     : other.ipUInt < ipUInt ? false
		     : port < other.port;
	}
	
	void print() const;
};


class ConnId {
public:
	Address address;
	unsigned int id;
	inline ConnId(): id() { }
	inline bool operator<(const ConnId &other) const {
		return address < other.address ? true
				: other.address < address ? false
				: id < other.id;
	}
};


struct __attribute__((__packed__)) Packet {
	unsigned int connId;
	unsigned int index;
	unsigned short cmdSize;
	unsigned char payload[PACKET_SIZE];
	
	
	inline Packet():
		connId(), index(), cmdSize(), payload() { }
		
	inline int getSize() const
		{ return cmdSize & SIZE_MASK; }
	inline int getCommand() const
		{ return cmdSize >> CMD_SHIFT; }
	
	inline void init(
		unsigned int connId,
		unsigned int index,
		unsigned short cmd,
		unsigned short size )
	{
		this->connId = connId;
		this->index = index;
		this->cmdSize = (cmd << CMD_SHIFT) | size;
	}
};


enum {
	FULL_PACKET_SIZE  = sizeof(Packet),
	HEADER_SIZE       = FULL_PACKET_SIZE - PACKET_SIZE,
	CRYPT_PACKET_SIZE = ((FULL_PACKET_SIZE + HASH_SIZE - 1)/CRYPT_BLOCK + 1)*CRYPT_BLOCK,
};



#endif