void main1(int argc, char** argv) { srand(time(0)); //init protocol_init(argc, argv); //arguments windowSize = 22; retimer = 3300;//retransmit timer acktimer = 600; bufferSize = windowSize / 2;//buffer size //init datalink layer senderLeft = 0;//left edge of sender senderRight = 0;//right edge of sender, which has data unfilled receiverLeft = 0;//left edge of receiver //receiverRight = bufferSize - 1;//right edge of receiver isPhysicalLayerReady = -1; lastAck = windowSize - 1; //init buffer sender = (buffer*)malloc(sizeof(buffer)* bufferSize); receiver = (buffer*)malloc(sizeof(buffer)* bufferSize); for (int i = 0; i < bufferSize; i++) { sender[i].frameArrived = false; receiver[i].frameArrived = false; sender[i].hasSent = false; receiver[i].hasSent = false; } //init interfcace enable_network_layer(); bool isNetworkEnabled = true; //init event args int eventArgs = -1; int eventKind = -1; //allocate temp space unsigned char temp[MAX_PACKET_SIZE + 11]; //main loop while (true) { static int frameLength; eventKind = wait_for_event(&eventArgs);//get event switch (eventKind) { case PHYSICAL_LAYER_READY: isPhysicalLayerReady = 1; break; case NETWORK_LAYER_READY: //if buffer nearly full if (((senderRight > senderLeft) && (senderRight - senderLeft == bufferSize - 1)) || (senderRight < senderLeft) && (windowSize - senderLeft + senderRight == bufferSize - 1)) { disable_network_layer(); isNetworkEnabled = false; } //store frame in buffer sender[senderRight % bufferSize].length = get_packet(sender[senderRight % bufferSize].data); //slide window senderRight = (senderRight + 1) % windowSize; break; case FRAME_RECEIVED: //init temperory variables frameLength = recv_frame(temp, MAX_PACKET_SIZE + 7); if (frameLength > MAX_PACKET_SIZE + 7) ;//frame is too large, discard it else { //check crc if (crc32(temp, frameLength) != 0) {//crc faild if (isInBuffer(senderLeft, senderRight, temp[0] == FRAME_DATA ? temp[2] : temp[1], false)) { //send nak temp[0] = FRAME_NAK;//if the 2nd byte is error, it may sends false nak, but it doesn't matter mySendFrame(temp, 2); } } else { if (temp[0] == FRAME_ACK) {//if it's an ack frame if (isInBuffer(senderLeft, senderRight, temp[1], false)) { if (isInBuffer(lastAck, senderRight, temp[1], false)) lastAck = temp[1]; //else do noting break; } } else if (temp[0] == FRAME_NAK) {//if it's a nak frame if (isInBuffer(senderLeft, senderRight, temp[1], false)) { //retranmit temp[0] = 1; memcpy(temp + 3, sender[temp[1] % bufferSize].data, sender[temp[1] % bufferSize].length * sizeof(unsigned char)); mySendFrame(temp, sender[temp[1] % bufferSize].length + 3); break; } } else if (temp[0] == FRAME_DATA) {//if it's a data frame if (isInBuffer(lastAck, senderRight, temp[2], false)) lastAck = temp[2]; if (isInBuffer(receiverLeft, (receiverLeft + bufferSize) % windowSize, temp[1], true)){ if (!receiver[temp[1] % bufferSize].frameArrived) { receiver[temp[1] % bufferSize].frameArrived = true; receiver[temp[1] % bufferSize].length = frameLength - 7; for (int i = 0; i < frameLength - 7; i++) { receiver[temp[1] % bufferSize].data[i] = temp[3 + i]; } } } } } } break; case DATA_TIMEOUT: //just retransmit the frame if (isInBuffer(lastAck, senderRight, eventArgs, false) && isInBuffer(senderLeft, senderRight, eventArgs, false)) { if (sender[eventArgs % bufferSize].hasSent) {//if it has been sent if (eventArgs == senderLeft || rand() % 10 > 10) { //build the frame temp[0] = FRAME_DATA; temp[1] = eventArgs; memcpy((void*)(temp + 3), sender[eventArgs % bufferSize].data, sender[eventArgs % bufferSize].length * sizeof(unsigned char)); //transmit mySendFrame(temp, sender[eventArgs % bufferSize].length + 3); } else start_timer(eventArgs, retimer * (rand() % 10 / 10.0 + 1)); } } break; case ACK_TIMEOUT: //just send an ack temp[0] = FRAME_ACK; mySendFrame(temp, 2); break; } //sliding the sender window //send { int i = senderLeft; while (isInBuffer(senderLeft, senderRight, i, false)) { if (sender[i % bufferSize].hasSent == false){ if (isPhysicalLayerReady == 1 || isPhysicalLayerReady == -1 || phl_sq_len() < 1000) { //build the frame temp[0] = FRAME_DATA; temp[1] = i % windowSize; memcpy((void*)(temp + 3), sender[i % bufferSize].data, sender[i % bufferSize].length * sizeof(unsigned char)); //transmit mySendFrame(temp, sender[i % bufferSize].length + 3); sender[i % bufferSize].hasSent = true; isPhysicalLayerReady = 0; } break; } i = (i + 1) % windowSize; } } //slide while (isInBuffer(senderLeft, senderRight, lastAck, false)) {//·â×°º¯Êý sender[senderLeft % bufferSize].hasSent = false; stop_timer(senderLeft); senderLeft = (senderLeft + 1) % windowSize; } //enable network layer if (!(((senderRight > senderLeft) && (senderRight - senderLeft == bufferSize)) || (senderRight < senderLeft) && (windowSize - senderLeft + senderRight == bufferSize)) && !isNetworkEnabled) { enable_network_layer(); isNetworkEnabled = true; } //sliding the receiver window { int i = 0; for (i = 0; i < bufferSize; i++) { if (receiver[(receiverLeft + i) % bufferSize].frameArrived) { put_packet(receiver[(receiverLeft + i) % bufferSize].data, receiver[(receiverLeft + i) % bufferSize].length); receiver[(receiverLeft + i) % bufferSize].frameArrived = false; } else break; } receiverLeft = (receiverLeft + i) % windowSize; } } }
void protocol6(void) { seq_nr ack_expected; /* lower edge of sender's window */ seq_nr next_frame_to_send; /* upper edge of sender's window + 1 */ seq_nr frame_expected; /* lower edge of receiver's window */ seq_nr too_far; /* upper edge of receiver's window + 1 */ int i; /* index into buffer pool */ frame r; /* scratch variable */ packet out_buf[NR_BUFS]; /* buffers for the outbound stream */ packet in_buf[NR_BUFS]; /* buffers for the inbound stream */ boolean arrived[NR_BUFS]; /* inbound bit map */ seq_nr nbuffered; /* how many output buffers currently used */ event_type event; enable_network_layer(); /* initialize */ ack_expected = 0; /* next ack expected on the inbound stream */ next_frame_to_send = 0; /* number of next outgoing frame */ frame_expected = 0; /* frame number expected */ too_far = NR_BUFS; /* receiver's upper window + 1 */ nbuffered = 0; /* initially no packets are buffered */ for (i = 0; i < NR_BUFS; i++) arrived[i] = false; while (true) { wait_for_event(&event); /* five possibilities: see event_type above */ switch(event) { case network_layer_ready: /* accept, save, and transmit a new frame */ nbuffered = nbuffered + 1; /* expand the window */ from_network_layer(&out_buf[next_frame_to_send % NR_BUFS]); /* fetch new packet */ send_frame(data, next_frame_to_send, frame_expected, out_buf); /* transmit the frame */ inc(next_frame_to_send); /* advance upper window edge */ break; case frame_arrival: /* a data or control frame has arrived */ from_physical_layer(&r); /* fetch incoming frame from physical layer */ if (r.kind == data) { /* An undamaged frame has arrived. */ if ((r.seq != frame_expected) && no_nak) send_frame(nak, 0, frame_expected, out_buf); else start_ack_timer(); if (between(frame_expected, r.seq, too_far) && (arrived[r.seq%NR_BUFS] == false)) { /* Frames may be accepted in any order. */ arrived[r.seq % NR_BUFS] = true; /* mark buffer as full */ in_buf[r.seq % NR_BUFS] = r.info; /* insert data into buffer */ while (arrived[frame_expected % NR_BUFS]) { /* Pass frames and advance window. */ to_network_layer(&in_buf[frame_expected % NR_BUFS]); no_nak = true; arrived[frame_expected % NR_BUFS] = false; inc(frame_expected); /* advance lower edge of receiver's window */ inc(too_far); /* advance upper edge of receiver's window */ start_ack_timer(); /* to see if (a separate ack is needed */ } } } if((r.kind==nak) && between(ack_expected,(r.ack+1)%(MAX_SEQ+1),next_frame_to_send)) send_frame(data, (r.ack+1) % (MAX_SEQ + 1), frame_expected, out_buf); while (between(ack_expected, r.ack, next_frame_to_send)) { nbuffered = nbuffered - 1; /* handle piggybacked ack */ stop_timer(ack_expected % NR_BUFS); /* frame arrived intact */ inc(ack_expected); /* advance lower edge of sender's window */ } break; case cksum_err: if (no_nak) send_frame(nak, 0, frame_expected, out_buf); break; /* damaged frame */ case timeout: send_frame(data, get_timedout_seqnr(), frame_expected, out_buf); break; /* we timed out */ case ack_timeout: send_frame(ack,0,frame_expected, out_buf); /* ack timer expired; send ack */ } if (nbuffered < NR_BUFS) enable_network_layer(); else disable_network_layer(); } }
int main(int argc, char ** argv) { int event, arg; struct FRAME r; int len = 0; int i; protocol_init(argc, argv); lprintf("Designed by JackalDire\n"); disable_network_layer(); for (;;) { event = wait_for_event(&arg); switch (event) { case NETWORK_LAYER_READY: get_packet(buffer[next_frame_to_send]); // fetch new packet from physical layer nbuffered++; send_data_frame(); inc(&next_frame_to_send); break; case PHYSICAL_LAYER_READY: phl_ready = 1; break; case FRAME_RECEIVED: len = recv_frame((unsigned char *)&r, sizeof r); if (len < 5 || crc32((unsigned char *)&r, len) != 0) { /* discard the error packet with wrong crc checksum */ /* TODO : add NAK to accelerate resending */ dbg_event("**** receiver error, bad CRC checksum, packet discarded.\n"); break; } if (r.kind == FRAME_DATA) { dbg_frame("Recv DATA %d %d, ID %d\n", r.seq, r.ack, *(short *)r.data); if (r.seq == frame_expected) { /* transmit the receive packet to network layer */ put_packet(r.data, PKT_LEN); // 7 = 3B other fields + 4B crc code inc(&frame_expected); start_ack_timer(ACK_TIMER); } } /* ACK n means packets earlier than n were received correctly, * so make packet ack_expeced ~ r.ack acknowledged */ while (between(ack_expected, r.ack, next_frame_to_send)) { --nbuffered; stop_timer(ack_expected); inc(&ack_expected); } break; case DATA_TIMEOUT: dbg_event("---- DATA %d timeout\n", arg); next_frame_to_send = ack_expected; /* retransmit all packets in the buffer when timeout */ for (i = 1; i <= nbuffered; ++i) { send_data_frame(); inc(&next_frame_to_send); } break; case ACK_TIMEOUT: /* send a separate ACK frame if there is no outstream for a specific time */ dbg_event("---- ACK %d timeout\n", arg); send_ack_frame(); } /* disable networklayer when outstrem buffer if full */ if (nbuffered < MAX_SEQ && phl_ready) enable_network_layer(); else disable_network_layer(); } }