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 and an independent window. 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 protm_estab { uint8_t type = 1; uint8_t ack; } Requests that a new connection is to be established; this message should be sent by the client. If ack=0, then this is an establishment request: the receiving part is asked to respond with a protm_estab(ack=1) message to finish the connection establishment. If ack=1, then this is an establishment acknowledgement, which makes the connection ready to use for both parties. If an ack=0 message is received by a client, the message can be ignored. If an ack=0 message is received by a server that already has a connection with that client, the connection should be terminated and the request replied with a protm_term(ack=0). If an ack=1 message is received by a server, the message can be ignored. If an ack=1 message is received by a client while no unanswered ack=0 message had been sent to that server, the client should reply with a protm_term(ack=0) message. struct protm_term { uint8_t type = 2; uint8_t ack; } Communicates termination requests and acknowledgements. If ack=0, then this is a termination request: the receiving party is asked to respond with a protm_term(ack=1) message to acknowledge the termination. If ack=1, then this is a termination acknowledgement, which terminates the connection for both parties. If an ack=0 message is received while no connection is active, the program should respond with an ack=1 message (an earlier ack=1 message could have been lost). If an ack=1 message is received while no connection is active, the message can be ignored. struct protm_data { uint8_t type = 3; uint8_t seqnum, rr; uint32_t size; uint8_t data[size]; } Transmits application data, with piggy-back of a protm_rr message with nrej=0. - 'seqnum' is the sequence number of this message. - 'rr' is the expected next seqnum, as in the protm_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 protm_rr { uint8_t type = 4; 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 protm_rr_poll { uint8_t type = 5; } Asks for a protm_rr message, because the sender has new data to send but thinks the window is full. The receiver of a protm_rr_poll should send its current protm_rr message.