/* Protocol 7 Same as Protocol 5 except that this is simplex. */ #define MAX_SEQ 7 /* should be 2^n - 1 */ typedef enum {frame_arrival, cksum_err, timeout, network_layer_ready, ack_timeout} event_type; #include "protocol.h" static boolean between(seq_nr a, seq_nr b, seq_nr c) { if (((a <= b) && (b < c)) || ((c < a) && (a <= b)) || ((b < c) && (c < a))) return(true); else return(false); } /* same as before, except that no acks are piggybacked */ static void send_data(seq_nr frame_nr, packet buffer[]) { frame s; s.info = buffer[frame_nr]; s.seq = frame_nr; /* don't need to put anything in s.ack */ to_physical_layer(&s); start_timer(frame_nr); } /* for sending acks */ static void send_ack(seq_nr frame_expected) { frame s; s.ack = (frame_expected + MAX_SEQ) % (MAX_SEQ + 1); to_physical_layer(&s); } void sender7(void) { seq_nr next_frame_to_send; seq_nr ack_expected; frame r; packet buffer[MAX_SEQ+1]; seq_nr nbuffered; seq_nr i; event_type event; enable_network_layer(); ack_expected = 0; next_frame_to_send = 0; nbuffered = 0; while (true) { wait_for_event(&event); /* four possibilities as before */ switch(event) { case network_layer_ready: from_network_layer(&buffer[next_frame_to_send]); nbuffered = nbuffered + 1; send_data(next_frame_to_send, buffer); inc(next_frame_to_send); break; case frame_arrival: /* an ack (a control frame) has arrived */ from_physical_layer(&r); /* no need to check for r.seq here because the frame is not data */ while (between(ack_expected, r.ack, next_frame_to_send)) { nbuffered = nbuffered - 1; stop_timer(ack_expected); inc(ack_expected); } break; case cksum_err: break; case timeout: next_frame_to_send = ack_expected; for (i = 1; i <= nbuffered; i++) { send_data(next_frame_to_send, buffer); inc(next_frame_to_send); } } if (nbuffered < MAX_SEQ) enable_network_layer(); else disable_network_layer(); } } void receiver7(void) { seq_nr frame_expected; frame r; event_type event; frame_expected = 0; while (true) { wait_for_event(&event); /* frame_arrival or chksum_err */ switch(event) { case frame_arrival: from_physical_layer(&r); if (r.seq == frame_expected) { to_network_layer(&r.info); inc(frame_expected); } break; } /* send back an ack for each data frame arrived */ send_ack(frame_expected); } }