//..............................................................................
//
// Packet definitions for TCP/IP stack
//

namespace io {

//..............................................................................

enum EthernetType: bigendian uint16_t
{
	Ip  = 0x0800,
	Arp = 0x0806,
	Ip6 = 0x86dd,
}

// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

struct EthernetHdr
{
	uint8_t m_dstAddress[6];
	uint8_t m_srcAddress[6];
	EthernetType m_type;
}

//..............................................................................

enum ArpHardwareType: bigendian uint16_t
{
	Ethernet = 1,
}

enum ArpProtocolType: bigendian uint16_t
{
	Ip = 0x0800,
}

enum ArpOpcode: bigendian uint16_t
{
	Request        = 1,
	Reply          = 2,
	RequestReverse = 3,
	ReplyReverese  = 4,
}

struct ArpHdr
{
	ArpHardwareType m_hardwareType;
	ArpProtocolType m_protocolType;
	uint8_t m_hardwareLength;
	uint8_t m_protocolLength;
	ArpOpcode m_opcode;
}

//..............................................................................

enum IpProtocol: uint8_t
{
	Icmp = 1,
	Tcp  = 6,
	Udp  = 17,
}

// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

bitflag enum IpFlags
{
	Mf = 0x01,
	Df = 0x02,
}

// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

struct IpHdr
{
	uint8_t m_headerLength: 4;
	uint8_t m_version: 4;
	uint8_t m_typeOfService;
	bigendian uint16_t m_totalLength;
	uint16_t m_identification;
	bigendian uint16_t m_flags: 3;
	bigendian uint16_t m_fragmentOffset: 13;
	uint8_t m_timeToLive;
	IpProtocol m_protocol;
	bigendian uint16_t m_headerChecksum;
	bigendian uint32_t m_srcAddress;
	bigendian uint32_t m_dstAddress;
}

struct Ip6Hdr
{
	uint32_t m_flowLabel: 20;
	uint32_t m_trafficClass: 8;
	uint32_t m_version: 4;
	bigendian uint16_t m_payloadLength;
	uint8_t m_nextHeader;
	uint8_t m_hopLimit;
	uint16_t m_srcAddress[8];
	uint16_t m_dstAddress[8];
}

struct IpPseudoHdr
{
	bigendian uint32_t m_srcAddress;
	bigendian uint32_t m_dstAddress;
	uint8_t m_zero;
	uint8_t m_protocol;
	bigendian uint16_t m_length;
}

//..............................................................................

enum IcmpType: uint8_t
{
	EchoReply               = 0,
	DestinationUnreachable  = 3,
	SourceQuench            = 4,
	Redirect                = 5,
	Echo                    = 8,
	RouterAdvertisement     = 9,
	RouterSelection         = 10,
	TimeExceeded            = 11,
	ParameterProblem        = 12,
	TimestampRequest        = 13,
	TimestampReply          = 14,
	InformationRequest      = 15,
	InformationReply        = 16,
	AddressMaskRequest      = 17,
	AddressMaskReply        = 18,
	TraceRoute              = 30,
}

// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

struct IcmpHdr
{
	IcmpType m_type;
	uint8_t m_code;
	bigendian uint16_t m_checksum;
	bigendian uint16_t m_id;
	bigendian uint16_t m_seqNumber;
}

//..............................................................................

bitflag enum TcpFlags: uint8_t
{
	Fin,
	Syn,
	Rst,
	Psh,
	Ack,
	Urg,
	Bog,
}

// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

struct TcpHdr
{
	bigendian uint16_t m_srcPort;
	bigendian uint16_t m_dstPort;
	bigendian uint32_t m_seqNumber;
	bigendian uint32_t m_ackNumber;
	uint8_t m_reserved: 4;
	uint8_t m_dataOffset: 4;
	TcpFlags m_flags;
	bigendian uint16_t m_window;
	bigendian uint16_t m_checksum;
	bigendian uint16_t m_urgentData;
}

//..............................................................................

struct UdpHdr
{
	bigendian uint16_t m_srcPort;
	bigendian uint16_t m_dstPort;
	bigendian uint16_t m_length;
	bigendian uint16_t m_checksum;
}

//..............................................................................

} // namespace io {
