The ICMP id and seqnum fields are unused in the protocol; the values are chosen by the client, with the restriction that the id field is constant over the entire communication. The server just mirrors the chosen values in the echo replies. All protocol information is contained in the payload part. In the following, 'seqnum' refers to the protocol sequence number, not the ICMP seqnum field. Each message containing data has a sequence number. This sequence number is in the seqnum range [0, SEQ_SIZE = 256). Windowing ARQ is applied for efficiency, with a window size of WIN_SIZE = 16. Each party has an independent seqnum counter. Only messages in the current window range may be sent. The first message byte is the message type. The message types are described below. All structs are packed. struct prot_data { uint8_t type = 1; uint8_t seqnum, rr; uint32_t size; uint8_t data[size]; } Transmits application data, with piggy-back of a prot_rr message with nrej=0. - 'seqnum' is the sequence number of this message. - 'rr' is the expected next seqnum, as in the prot_rr message. This can shift the window. - 'size' is the number of bytes of data sent in this packet. - 'data' contains the next-protocol-level data sent in this message. struct prot_rr { uint8_t type = 2; uint8_t rr, nrej; uint8_t rej[nrej]; } Acknowledgement of arrival of messages and indication of need of resending. 'rr-1' should lie in the current window, and the seqnums in 'rej' should lie in the current window. All messages before seqnum 'rr' are acknowledged, and the recipient is asked to resend its messages with seqnums in 'rej'. - 'rr' is the expected next seqnum. Seqnums in window before this id are considered successfully received. - 'nrej' is the number of seqnums in 'rej'. - 'rej' contains the seqnums that need to be resent. struct prot_rr_poll { uint8_t type = 3; } Asks for a prot_rr message, because the sender has new data to send but thinks the window is full. The receiver of a prot_rr_poll should send its current prot_rr message.