
/*
 *  All we want to know about a TCP packet, in one place.
 *   Compare with Linux's SKB structure.
 */

#include <netinet/ip.h>
#include <netinet/tcp.h>

// This structure is suboptimal. The buffer be just a pointer,
//   managed with malloc() as needed (or, better yet, obtained
//   from a special heap for packets; see BSD's mbuf structure,
//   see https://www.openbsd.org/papers/asiabsdcon08-network.pdf
//       or https://www.youtube.com/watch?v=V85It0dGUF4).

typedef struct pkt {

     struct pkt *next;       // linked list of all packets   
     struct pkt *prev; 

     int invalid;            // packet could not be received, ignore it
     
     char buf[IP_MAXPACKET]; // buffer holding the packet's raw bytes
     int len;                // length of raw packet

     struct iphdr *ip;       // points to packet's IP header in buf
                             //   (for us, same as buf's address, but viewed as
                             //    a different type) 
     struct tcphdr *tcp;     // points to packet's TCP header in buf

     int sockfd;             // the raw socket used to receive or send 
     struct sockaddr_in sin; //   and its sockaddr struct.
     socklen_t clilen;       //   and its length
     
     char *payload;          // TCP segment payload 
     int payload_sz;         //   and its size
     uint32_t seq;           // this packet's TCP segment's SEQ
     uint32_t ack;           //   and ACK to send back with it

     int rto_fd;             // retransmission timout timer
     int polled_slot;        // in pollfd array, same as fd
} pkt_t;

#define IS_SYN(p)    ((p)->tcp->syn  && !(p)->tcp->ack)
#define IS_ACK(p)    ((p)->tcp->ack  && !(p)->tcp->syn && \
		        !(p)->tcp->rst && !(p)->tcp->fin)
#define IS_RST(p)    ((p)->tcp->rst)
#define IS_FIN(p)    ((p)->tcp->fin && !(p)->tcp->ack)
#define IS_FINACK(p) ((p)->tcp->fin &&  (p)->tcp->ack)

#define GET_ACK(p)   (ntohl((p)->tcp->ack_seq))

char *tcp_states[] = { "NO_SUCH_STATE",
		      "TCP_ESTABLISHED",
		      "TCP_SYN_SENT",
		      "TCP_SYN_RECV",
		      "TCP_FIN_WAIT1",
		      "TCP_FIN_WAIT2",
		      "TCP_TIME_WAIT",
		      "TCP_CLOSE",
		      "TCP_CLOSE_WAIT",
		      "TCP_LAST_ACK",
		      "TCP_LISTEN",
		      "TCP_CLOSING" }; 

#define ADDR2A(n)  (inet_ntoa(*(struct in_addr *)&(n)))

typedef struct {
     uint8_t kind;
     uint8_t size;
} tcp_option_t;

