Created
March 11, 2018 15:30
-
-
Save wudaown/baed8684d47e15d4acdf74535b030ddb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*===============================================================* | |
* File: SWP.java * | |
* * | |
* This class implements the sliding window protocol * | |
* Used by VMach class * | |
* Uses the following classes: SWE, Packet, PFrame, PEvent, * | |
* * | |
* Author: Professor SUN Chengzheng * | |
* School of Computer Engineering * | |
* Nanyang Technological University * | |
* Singapore 639798 * | |
*===============================================================*/ | |
import java.util.Timer; | |
import java.util.TimerTask; | |
public class SWP { | |
/*========================================================================* | |
the following are provided, do not change them!! | |
*========================================================================*/ | |
//the following are protocol constants. | |
public static final int MAX_SEQ = 7; | |
public static final int NR_BUFS = (MAX_SEQ + 1) / 2; | |
// the following are protocol variables | |
private int oldest_frame = 0; | |
private PEvent event = new PEvent(); | |
private Packet out_buf[] = new Packet[NR_BUFS]; | |
//the following are used for simulation purpose only | |
private SWE swe = null; | |
private String sid = null; | |
//Constructor | |
public SWP(SWE sw, String s) { | |
swe = sw; | |
sid = s; | |
} | |
//the following methods are all protocol related | |
private void init() { | |
for (int i = 0; i < NR_BUFS; i++) { | |
out_buf[i] = new Packet(); | |
} | |
} | |
/** | |
* @param e Packet Event | |
*/ | |
private void wait_for_event(PEvent e) { | |
swe.wait_for_event(e); //may be blocked | |
oldest_frame = e.seq; //set timeout frame seq | |
} | |
private void enable_network_layer(int nr_of_bufs) { | |
//network layer is permitted to send if credit is available | |
swe.grant_credit(nr_of_bufs); | |
} | |
private void from_network_layer(Packet p) { | |
swe.from_network_layer(p); | |
} | |
private void to_network_layer(Packet packet) { | |
swe.to_network_layer(packet); | |
} | |
private void to_physical_layer(PFrame fm) { | |
System.out.println("SWP: Sending frame: seq = " + fm.seq + | |
" ack = " + fm.ack + " kind = " + | |
PFrame.KIND[fm.kind] + " info = " + fm.info.data); | |
System.out.flush(); | |
swe.to_physical_layer(fm); | |
} | |
private void from_physical_layer(PFrame fm) { | |
PFrame fm1 = swe.from_physical_layer(); | |
fm.kind = fm1.kind; | |
fm.seq = fm1.seq; | |
fm.ack = fm1.ack; | |
fm.info = fm1.info; | |
} | |
/*===========================================================================* | |
implement your Protocol Variables and Methods below: | |
*==========================================================================*/ | |
// Input buffer | |
private boolean no_ack = true; | |
private boolean between(int a, int b, int c) { | |
return ((a <= b) && (b < c)) || ((c < a) && (a <= b)) || ((b < c) && (c < a)); | |
} | |
private void send_frame(int fk, int frame_nr, int frame_expected, Packet buffer[]) { | |
PFrame s = new PFrame(); // temporary variable to hold the frame | |
s.kind = fk; // Assign the Event type to outgoing frame | |
if (fk == PFrame.DATA) { | |
s.info = buffer[frame_nr % NR_BUFS]; // encapsulate packet if it is data frame | |
} | |
s.seq = frame_nr; // assign frame number | |
s.ack = (frame_expected + MAX_SEQ) % (MAX_SEQ + 1); // piggybacking the acknowledge number for frame receive | |
if (fk == PFrame.NAK) { | |
no_ack = false; // generate NAK | |
} | |
to_physical_layer(s); // push to physical layer | |
if (fk == PFrame.DATA) { | |
start_timer(frame_nr); // start timer for retransmission | |
} | |
stop_ack_timer(); // stop ack timer if any | |
} | |
public void protocol6() { | |
init(); | |
Packet in_buff[] = new Packet[NR_BUFS]; // Inbound Buffer | |
int ack_expected = 0; // Acknowledgement Number expected from other party | |
int next_frame_to_send = 0; // Frame Number to be send | |
int frame_expected = 0; | |
int too_far = NR_BUFS; | |
int i = 0; | |
PFrame frame = new PFrame(); | |
boolean arrived[] = new boolean[NR_BUFS]; | |
Timer timeout[] = new Timer[NR_BUFS]; | |
for (int j = 0; j < NR_BUFS; j++) { | |
arrived[j] = false; | |
in_buff[j] = new Packet(); | |
} | |
// attach timer to each frame or rather buffer | |
for (int k=0; k<=NR_BUFS; k++) { | |
frameTimer[k] = new Timer(); | |
} | |
enable_network_layer(NR_BUFS); | |
while (true) { | |
wait_for_event(event); | |
switch (event.type) { | |
case (PEvent.NETWORK_LAYER_READY): | |
// When network layer is ready | |
// retrieve packet from upper network layer | |
from_network_layer(out_buf[next_frame_to_send % NR_BUFS]); | |
// encapsulate the packet into data frame and push to physical layer | |
send_frame(PFrame.DATA, next_frame_to_send, frame_expected, out_buf); | |
// increment counter for next frame to be send | |
next_frame_to_send = inc(next_frame_to_send); | |
break; | |
case (PEvent.FRAME_ARRIVAL): | |
// Frame arrival event trigger the virtual machine | |
// to retrieve frame from physical layer | |
// if it is a data frame check the sequence number | |
// and NAK flag from here either start a ACK timer | |
// or issue a NAK packet | |
from_physical_layer(frame); | |
if (frame.kind == PFrame.DATA) { | |
// NAK frame send if frame is not expected | |
if ((frame.seq != frame_expected) && no_ack) { | |
send_frame(PFrame.NAK, 0, frame_expected, out_buf); | |
} else { | |
// else start timer | |
start_ack_timer(); | |
} | |
if (between(frame_expected, frame.seq, too_far) && (!arrived[frame.seq % NR_BUFS])) { | |
arrived[frame.seq % NR_BUFS] = true; | |
in_buff[frame.seq % NR_BUFS] = frame.info; | |
while (arrived[frame_expected % NR_BUFS]) { | |
// handle piggybacked ack frame | |
// pass frame and advance in window | |
to_network_layer(in_buff[frame_expected % NR_BUFS]); | |
no_ack = true; | |
arrived[frame_expected % NR_BUFS] = false; | |
// advance lower bound of receiver window | |
frame_expected = inc(frame_expected); | |
// advance upper bound of receiver window | |
too_far = inc(too_far); | |
// start ack timer to check whether ack is needed | |
start_ack_timer(); | |
} | |
} | |
} | |
if ((frame.kind == PFrame.NAK) && between(ack_expected, (frame.ack + 1) % (MAX_SEQ + 1), next_frame_to_send)) { | |
send_frame(PFrame.DATA, (frame.ack + 1) % (MAX_SEQ + 1), frame_expected, out_buf); | |
} | |
while (between(ack_expected, frame.ack, next_frame_to_send)) { | |
// stop timer since frame arrive correctly | |
stop_timer(ack_expected % NR_BUFS); | |
// increment the next ack number expected | |
ack_expected = inc(ack_expected); | |
// granted credit | |
enable_network_layer(1); | |
} | |
break; | |
case (PEvent.CKSUM_ERR): | |
if (no_ack) { | |
send_frame(PFrame.NAK, 0, frame_expected, out_buf); | |
} | |
break; | |
case (PEvent.TIMEOUT): | |
send_frame(PFrame.DATA, oldest_frame, frame_expected, out_buf); | |
break; | |
case (PEvent.ACK_TIMEOUT): | |
send_frame(PFrame.ACK, 0, frame_expected, out_buf); | |
break; | |
default: | |
System.out.println("SWP: undefined event type = " | |
+ event.type); | |
System.out.flush(); | |
} | |
} | |
} | |
/* Note: when start_timer() and stop_timer() are called, | |
the "seq" parameter must be the sequence number, rather | |
than the index of the timer array, | |
of the frame associated with this timer, | |
*/ | |
private static final int TIMER_DURATION = 600; | |
private static final int ACK_DURATION = 300; | |
private Timer[] frameTimer = new Timer [NR_BUFS + 1]; //+1 is for the final buffer for frame timer | |
private class EventTimerTask extends TimerTask { | |
private int seq; | |
public EventTimerTask(int seq) { | |
this.seq = seq; | |
} | |
@Override | |
public void run(){ | |
swe.generate_timeout_event(seq); | |
} | |
} | |
private class Ack_TimerTask extends TimerTask { | |
@Override | |
public void run(){ | |
swe.generate_acktimeout_event(); | |
} | |
} | |
private void start_timer(int seq) { | |
//frameTimer starts with seq | |
stop_timer(seq); //cancel timer if it is still on | |
frameTimer[seq%NR_BUFS] = new Timer(); | |
frameTimer[seq%NR_BUFS].schedule(new EventTimerTask(seq), TIMER_DURATION); //scheduling of time task | |
} | |
private void stop_timer(int seq) { | |
// Stop the timer attach to the frame | |
frameTimer[seq%NR_BUFS].cancel(); | |
} | |
private void start_ack_timer() { | |
// Only one timer exists at any point of time | |
// stop the current first | |
// ACK_DURATION has to be shorted than TIMER_DURATION | |
// so that frame retransmission timer does not expired | |
// and retransmit. | |
stop_ack_timer(); | |
frameTimer[NR_BUFS] = new Timer(); | |
frameTimer[NR_BUFS].schedule(new Ack_TimerTask(), ACK_DURATION); | |
} | |
private void stop_ack_timer() { | |
// Stop the timer attach to the frame | |
frameTimer[NR_BUFS].cancel(); | |
} | |
private int inc(int frame_nr) { | |
frame_nr = (frame_nr + 1) % 8; | |
return frame_nr; | |
} | |
}//End of class | |
/* Note: In class SWE, the following two public methods are available: | |
. generate_acktimeout_event() and | |
. generate_timeout_event(seqnr). | |
To call these two methods (for implementing timers), | |
the "swe" object should be referred as follows: | |
swe.generate_acktimeout_event(), or | |
swe.generate_timeout_event(seqnr). | |
*/ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment