import java.applet.Applet;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class gbn extends
Applet implements ActionListener, Runnable
{
final int window_len_def
= 5; // Default values of parameters
final int pack_width_def
= 10;
final int pack_height_def
= 30;
final int h_offset_def
= 100;
final int v_offset_def
= 50;
final int v_clearance_def
= 300;
final int total_packet_def
= 20;
final int time_out_sec_def
= 30;
final Color unack_color
= Color.red; // Default colors of different packets
final Color ack_color
= Color.yellow;
final Color sel_color
= Color.green;
final Color roam_pack_color
= Color.red;
final Color roam_ack_color
= Color.yellow;
final Color dest_color
= Color.blue;
int base, nextseq,
fps, selected=-1;
boolean timerFlag,
timerSleep;
Button send, stop,
fast, slow, kill, reset;
Thread gbnThread,
timerThread;
Dimension offDimension;
// flashing eliminator: double buffering
Image
offImage;
Graphics
offGraphics;
String statusMsg,
strCurrentValues;
packet sender[];
// Declaring properties
int window_len,
pack_width, pack_height, h_offset, v_offset, v_clearance, total_packet,
time_out_sec;
public void init()
{
String strWinLen,
strPackWd, strPackHt, strHrOff, strVtOff, strVtClr, strTotPack, strTimeout;
strWinLen = getParameter("window_length"); // Start collecting parameters
strPackWd = getParameter("packet_width");
strPackHt = getParameter("packet_height");
strHrOff = getParameter("horizontal_offset");
strVtOff = getParameter("vertical_offset");
strVtClr = getParameter("vertical_clearance");
strTotPack = getParameter("total_packets");
strTimeout = getParameter("timer_time_out");
// Get the values of the parameters into properties.
try {
if (strWinLen != null) window_len = Integer.parseInt(strWinLen);
if (strPackWd != null) pack_width = Integer.parseInt(strPackWd);
if (strPackHt != null) pack_height = Integer.parseInt(strPackHt);
if (strHrOff != null) h_offset = Integer.parseInt(strHrOff);
if (strVtOff != null) v_offset = Integer.parseInt(strVtOff);
if (strVtClr != null) v_clearance = Integer.parseInt(strVtClr);
if (strTotPack != null) total_packet = Integer.parseInt(strTotPack);
if (strTimeout != null) time_out_sec = Integer.parseInt(strTimeout);
} catch (Exception e) {}
// If parameter is not found, use default values.
window_len = (window_len > 0) ? window_len : window_len_def;
pack_width =
(pack_width > 0) ? pack_width : pack_width_def;
pack_height =
(pack_height > 0) ? pack_height : pack_height_def;
h_offset = (h_offset
> 0) ? h_offset : h_offset_def;
v_offset = (v_offset
> 0) ? v_offset : v_offset_def;
v_clearance =
(v_clearance > 0) ? v_clearance : v_clearance_def;
total_packet
= (total_packet > 0) ? total_packet : total_packet_def;
time_out_sec
= (time_out_sec > 0) ? time_out_sec : time_out_sec_def;
base = 0;
// Defining base
nextseq = 0;
// Defining Next sequence number.
fps = 5;
// Defining default Frame per Second.
sender = new
packet[total_packet];
statusMsg = "Ready
to run. Press 'Send New' button to start.";
strCurrentValues
= "Window Base = "+ base +". Next Sequence No. = "+ nextseq;
// Defining the
buttons
send = new Button("Send
New");
send.setActionCommand("rdt");
send.addActionListener(this);
stop = new Button("Stop
Animation");
stop.setActionCommand("stopanim");
stop.addActionListener(this);
fast = new Button("Faster");
fast.setActionCommand("fast");
fast.addActionListener(this);
slow = new Button("Slower");
slow.setActionCommand("slow");
slow.addActionListener(this);
kill = new Button("Kill
Packet");
kill.setActionCommand("kl");
kill.addActionListener(this);
kill.setEnabled(false);
reset = new Button("Reset");
reset.setActionCommand("rst");
reset.addActionListener(this);
// Adding the
buttons
add(send);
add(stop);
add(fast);
add(slow);
add(kill);
add(reset);
}
public void start()
{
if (gbnThread==null)
// Creating main thread and start it
gbnThread
= new Thread(this);
gbnThread.start();
}
public void run()
{
Thread currenthread
= Thread.currentThread();
while (currenthread==gbnThread)
// While the animation is running
if (onTheWay(sender))
// Checks if any of the packets are travelling
{
for
(int i=0; i<total_packet; i++)
if (sender[i]!= null)
if (sender[i].on_way) // If packet is roaming
if (sender[i].packet_pos < (v_clearance-pack_height))
sender[i].packet_pos+=5; // Move packet
else if (sender[i].packet_ack) // If it is moving to destination
{
sender[i].reached_dest = true;
if (check_upto_n(i)) // Send acknowledgement if all preceeding
{ // packets are received.
sender[i].packet_pos = pack_height+5;
sender[i].packet_ack = false;
statusMsg = "Packet "+i+" received. Acknowledge sent.";
}
else
{
sender[i].on_way = false;
statusMsg = "Packet "+i+" received. No acknowledge sent.";
if (i==selected)
{
selected = -1;
kill.setEnabled(false);
}
}
}
else if (!sender[i].packet_ack) // acknowledgement
{
statusMsg = "Packet "+ i +" acknowledge received.";
sender[i].on_way = false;
for (int n=0; n<=i; n++)
sender[n].acknowledged = true;
if (i==selected)
{
selected = -1;
kill.setEnabled(false);
}
timerThread = null; //resetting timer thread
if (i+window_len<total_packet)
base = i+1;
if (nextseq < base+window_len) send.setEnabled(true);
if (base != nextseq)
{
statusMsg += " Timer restarted.";
timerThread = new Thread(this);
timerSleep = true;
timerThread.start();
}
else
statusMsg += " Timer stopped.";
}
strCurrentValues
= "Window Base = "+ base +". Next Sequence No. = "+ nextseq;
repaint();
try
{
Thread.sleep(1000/fps);
} catch (InterruptedException e)
{
System.out.println("Help");
}
}
else
gbnThread
= null;
while (currenthread
== timerThread)
if (timerSleep)
{
timerSleep=false;
try
{
Thread.sleep(time_out_sec*1000);
} catch (InterruptedException e)
{
System.out.println ("Timer interrupted.");
}
}
else
{
for
(int n=base; n<base+window_len; n++)
if (sender[n] != null)
if (!sender[n].acknowledged)
{
sender[n].on_way = true;
sender[n].packet_ack = true;
sender[n].packet_pos = pack_height+5;
}
timerSleep
= true;
if
(gbnThread == null)
{
gbnThread = new Thread (this);
gbnThread.start();
}
statusMsg
= "Packets resent by timer. Timer restarted.";
}
}
public void actionPerformed(ActionEvent
e)
{
String cmd =
e.getActionCommand();
if (cmd == "rdt"
&& nextseq < base+window_len) // Send button is pressed
{
sender[nextseq]
= new packet(true,pack_height+5);
statusMsg
= "Packet "+ nextseq +" sent.";
if (base
== nextseq)
{
// i.e. the window is empty and a new data is getting in
statusMsg
+= " Timer set for packet "+ base +".";
if
(timerThread == null)
timerThread = new Thread(this);
timerSleep
= true;
timerThread.start();
}
repaint();
nextseq++;
if (nextseq
== base+window_len)
send.setEnabled(false);
start();
}
else if (cmd
== "fast") // Faster button pressed
{
fps+=2;
statusMsg
= "Simulation speed increased by 2 fps.";
}
else if (cmd
== "slow" && fps>2)
{
fps-=2;
statusMsg
= "Simulation speed decreased by 2 fps.";
}
else if (cmd
== "stopanim")
{
gbnThread
= null;
if (timerThread
!= null)
{
timerFlag
= true;
timerThread
= null; // added later
}
stop.setLabel("Resume");
stop.setActionCommand("startanim");
// disableing
all the buttons
send.setEnabled(false);
slow.setEnabled(false);
fast.setEnabled(false);
kill.setEnabled(false);
statusMsg
= "Simulation paused.";
repaint();
}
else if (cmd
== "startanim")
{
statusMsg
= "Simulation resumed.";
stop.setLabel("Stop
Animation");
stop.setActionCommand("stopanim");
if (timerFlag)
{
statusMsg
+= " Timer running.";
timerThread
= new Thread(this);
timerSleep
= true;
timerThread.start();
}
// enabling
the buttons
send.setEnabled(true);
slow.setEnabled(true);
fast.setEnabled(true);
kill.setEnabled(true);
repaint();
// repainted to show new messages
start();
}
else if (cmd
== "kl")
{
if (sender[selected].packet_ack)
statusMsg
= "Packet "+ selected +" destroyed. Timer running for packet "+base+".";
else
statusMsg
= "Acknowledgement of packet "+ selected +" destroyed. Timer running for
packet "+base+".";
sender[selected].on_way
= false;
kill.setEnabled(false);
selected
= -1;
repaint();
}
else if (cmd
== "rst")
reset_app();
}
public boolean
mouseDown(Event e, int x, int y)
{
int i, xpos,
ypos;
i = (x-h_offset)/(pack_width+7);
if (sender[i]!=
null)
{
xpos =
h_offset+(pack_width+7)*i;
ypos =
sender[i].packet_pos;
if (x>=xpos
&& x<= xpos+pack_width && sender[i].on_way)
{
if
((sender[i].packet_ack && y>=v_offset+ypos && y<=v_offset+ypos+pack_height)
|| ((!sender[i].packet_ack) && y>=v_offset+v_clearance-ypos &&
y<=v_offset+v_clearance-ypos+pack_height))
{
statusMsg = "Packet "+ i +" selected.";
sender[i].selected = true;
selected = i;
kill.setEnabled(true);
}
else
statusMsg = "Click on a moving packet to select.";
}
else
statusMsg
= "Click on a moving packet to select.";
}
return true;
}
public void paint(Graphics
g) // To eliminate flushing, update is overriden
{
update(g);
}
public void update(Graphics
g)
{
Dimension d =
size();
//Create the
offscreen graphics context, if no good one exists.
if ((offGraphics == null) || (d.width != offDimension.width) || (d.height
!= offDimension.height))
{
offDimension = d;
offImage = createImage(d.width, d.height);
offGraphics = offImage.getGraphics();
}
//Erase the previous
image.
offGraphics.setColor(Color.white);
offGraphics.fillRect(0, 0, d.width, d.height);
//drawing window
offGraphics.setColor(Color.black);
offGraphics.draw3DRect(h_offset+base*(pack_width+7)-4,
v_offset-3, (window_len)*(pack_width+7)+1, pack_height+6,true);
for (int i=0;
i<total_packet; i++)
{
// drawing
the sending row
if (sender[i]==null)
{
offGraphics.setColor(Color.black);
offGraphics.draw3DRect(h_offset+(pack_width+7)*i,
v_offset, pack_width,pack_height,true);
offGraphics.draw3DRect(h_offset+(pack_width+7)*i,
v_offset+v_clearance, pack_width,pack_height,true);
}
else
{
if
(sender[i].acknowledged)
offGraphics.setColor(ack_color);
else
offGraphics.setColor(unack_color);
offGraphics.fill3DRect
(h_offset+(pack_width+7)*i, v_offset,pack_width,pack_height,true);
//
drawing the destination packets
offGraphics.setColor
(dest_color);
if
(sender[i].reached_dest)
offGraphics.fill3DRect (h_offset+(pack_width+7)*i, v_offset+v_clearance,pack_width,pack_height,true);
else
offGraphics.draw3DRect (h_offset+(pack_width+7)*i, v_offset+v_clearance,pack_width,pack_height,true);
//
drawing the moving packets
if
(sender[i].on_way)
{
if (i==selected)
offGraphics.setColor (sel_color);
else if (sender[i].packet_ack)
offGraphics.setColor (roam_pack_color);
else
offGraphics.setColor (roam_ack_color);
if (sender[i].packet_ack)
offGraphics.fill3DRect (h_offset+(pack_width+7)*i, v_offset+sender[i].packet_pos,pack_width,pack_height,true);
else
offGraphics.fill3DRect (h_offset+(pack_width+7)*i, v_offset+v_clearance-sender[i].packet_pos,pack_width,pack_height,true);
}
}
}
// for loop ends
// drawing
message boxes
offGraphics.setColor(Color.black);
int newvOffset
= v_offset+v_clearance+pack_height;
int newHOffset
= h_offset;
offGraphics.drawString(statusMsg,newHOffset,newvOffset+25);
//offGraphics.drawString(strCurrentValues,newHOffset,newvOffset+40);
offGraphics.drawString("Packet",newHOffset+15,newvOffset+60);
offGraphics.drawString("Acknowledge",newHOffset+85,newvOffset+60);
offGraphics.drawString("Received
Pack",newHOffset+185,newvOffset+60);
offGraphics.drawString("Selected",newHOffset+295,newvOffset+60);
offGraphics.drawString("Base
= "+base,h_offset+(pack_width+7)*total_packet+10,v_offset+v_clearance/2);
offGraphics.drawString("NextSeq
= "+nextseq,h_offset+(pack_width+7)*total_packet+10,v_offset+v_clearance/2+20);
offGraphics.setColor(Color.blue);
offGraphics.drawString("Sender",h_offset+(pack_width+7)*total_packet+10,v_offset+12);
offGraphics.drawString("Receiver",h_offset+(pack_width+7)*total_packet+10,v_offset+v_clearance+12);
offGraphics.setColor(Color.gray);
offGraphics.draw3DRect(newHOffset-10,newvOffset+42,360,25,true);
offGraphics.setColor(Color.red);
offGraphics.draw3DRect(h_offset+(pack_width+7)*total_packet+5,v_offset+v_clearance/2-15,80,40,true);
offGraphics.setColor(roam_pack_color);
offGraphics.fill3DRect(newHOffset,
newvOffset+50,10,10,true);
offGraphics.setColor(roam_ack_color);
offGraphics.fill3DRect(newHOffset+70,
newvOffset+50,10,10,true);
offGraphics.setColor(dest_color);
offGraphics.fill3DRect(newHOffset+170,
newvOffset+50,10,10,true);
offGraphics.setColor(sel_color);
offGraphics.fill3DRect(newHOffset+280,
newvOffset+50,10,10,true);
g.drawImage(offImage,
0, 0, this);
}
// method paint ends
// checks out
if an array is on the way to source or destination
public boolean
onTheWay(packet pac[])
{
for (int i=0;
i<pac.length; i++)
if (pac[i]
== null)
return
false;
else if
(pac[i].on_way) return true;
return false;
}
// checkes all
the packets before packno. Returns false if any packet has
// not reached
destination and true if all the packets have reached destination.
public boolean
check_upto_n(int packno)
{
for (int i=0;
i<packno; i++)
if (!sender[i].reached_dest)
return
false;
return true;
}
public void reset_app()
{
for (int i=0;
i<total_packet; i++)
if (sender[i]
!= null)
sender[i]
= null;
base = 0;
nextseq = 0;
selected = -1;
fps = 5;
timerFlag = false;
timerSleep =
false;
gbnThread = null;
timerThread =
null;
if(stop.getActionCommand()=="startanim")
// in case of pause mode, enable all buttons
{
slow.setEnabled(true);
fast.setEnabled(true);
}
send.setEnabled(true);
kill.setEnabled(false);
stop.setLabel("Stop
Animation");
stop.setActionCommand("stopanim");
statusMsg = "Simulation
restarted. Press 'Send New' to start.";
repaint();
}
}
class packet
{
boolean on_way,
reached_dest, acknowledged, packet_ack, selected;
int packet_pos;
packet()
{
on_way = false;
selected = false;
reached_dest
= false;
acknowledged
= false;
packet_ack =
true;
packet_pos =
0;
}
packet(boolean
onway, int packetpos)
{
on_way = onway;
selected = false;
reached_dest
= false;
acknowledged
= false;
packet_ack =
true;
packet_pos =
packetpos;
}
}