-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSWP.java
318 lines (275 loc) · 13.2 KB
/
SWP.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
/*===============================================================*
* 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(); //Event that have 5 type
private Packet out_buf[] = new Packet[NR_BUFS];
private Packet[] in_buf = new Packet[NR_BUFS]; /* ADDED buffers for the inbound stream */
//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();
in_buf[i] = new Packet();/*ADDED*/
}
}
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:
*==========================================================================*/
private boolean no_nak = true; /*no nak has been sent yet*/
private Timer[] sender_timer = new Timer[NR_BUFS];
private Timer receiver_timer;
/**
* Increment to the next number within the possible sequence number
* @param num number to increment from
*
* num++ if num < MAX_SEQ
* num = 0 if num is currently MAX_SEQ
*/
public int increment(int num) {
return (num + 1) % (MAX_SEQ + 1);
}
/**
* Checks the circular condition of the frames
* Same as between in protocol 5, but shorter and more obscure
* @param a frame a
* @param b frame b
* @param c frame c
*/
public static boolean between(int a, int b, int c) {
return ((a <= b) && (b < c)) || ((c < a) && (a <= b)) || ((b < c) && (c < a));
}
/**
* Construct and send a data, ack, or nak frame
* @param fk frame kind 1)data 2)ack 3)nak
* @param frame_nr sequence/frame number
* @param frame_expected sequence/frame number expected
* @param buffer buffer Packet(s)
*/
public void send_frame(int fk, int frame_nr, int frame_expected, Packet buffer[]) {
PFrame s = new PFrame(); /* scratch variable*/
s.kind = fk; /* kind == data, ack, or nak */
if (fk == PFrame.DATA) s.info = buffer[frame_nr % NR_BUFS]; /* if frame kind is data*/
s.seq = frame_nr; /* only meaningful for data frames*/
s.ack = (frame_expected + MAX_SEQ) % (MAX_SEQ + 1);
if (fk == PFrame.NAK) no_nak = false; /*one nak per frame, please */
to_physical_layer(s); /*transmit the frame*/
if (fk == PFrame.DATA) start_timer(frame_nr);/*if data frame is received, start timer*/
stop_ack_timer(); /*no need for separate ack frame*/
}
/**
* Sliding window protocol6 method
*/
public void protocol6() {
int ack_expected = 0; /* lower edge of sender’s window & next ack expected on the inbound stream */
int next_frame_to_send = 0; /* upper edge of sender's window + 1 & number of next outgoing frame */
int frame_expected = 0; /*lower edge of receiver's window*/
int too_far = NR_BUFS; /*upper edge of receiver's window +1 */
//int nbuffered = 0; /*how many output buffers currently used & initially no packets are buffered*/
PFrame r = new PFrame(); /*scratch variable*/
/*following code added to the front*/
//Packet[] in_buf = new Packet[NR_BUFS]; /* buffers for the inbound stream */
boolean[] arrived = new boolean[NR_BUFS]; /*inbound bit map*/
for (int i = 0; i < NR_BUFS; i++) arrived[i] = false;
enable_network_layer(NR_BUFS); /*sender can send up to 4 frames before the ack for the first frame come back*/
init(); /*initialize outbound stream buffer*/
while (true) {
/**
* Types of event:
* 1)NETWORK_LAYER_READY - transmit new frame
* 2)FRAME_ARRIVAL - receive frame
* 3)CKSUM_ERR - frame damaged
* 4)TIMEOUT - timer expired, sender resend frame since no ack from receiver
* 5)ACK_TIMEOUT - ack timer expired, send ack again
*/
wait_for_event(event); /*five possibilites: see event_type above*/
switch (event.type) {
case (PEvent.NETWORK_LAYER_READY):
/*Network Layer Ready & accept, save and transmit a new frame*/
//nbuffered += 1; /*expand the window*/
from_network_layer(out_buf[next_frame_to_send % NR_BUFS]); /*fetch new packets*/
send_frame(PFrame.DATA, next_frame_to_send, frame_expected, out_buf); /* transmit the frame */
next_frame_to_send = increment(next_frame_to_send); /* advance upper window edge */
break;
case (PEvent.FRAME_ARRIVAL):
/* a data or control frame has arrived */
from_physical_layer(r); /* fetch incoming frame from physical layer */
if (r.kind == PFrame.DATA) { /* An undamaged frame has arrived. */
if ((r.seq != frame_expected) && no_nak) /*the frame's sequence number is not within the receiver's window and no nak sent*/
send_frame(PFrame.NAK, 0, frame_expected, out_buf);
else /*seq number arrived is expected*/
start_ack_timer(); /*time duration that the ack should wait to be piggybacked, else, ack should be sent as a separate frame*/
if (between(frame_expected, r.seq, too_far) && (arrived[r.seq % NR_BUFS] == false)) { /* Frames may be accepted in any order. */
/*if frame received is between the expected frames of the sliding window and if it has not been received before*/
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]) { /* frame expected is received, Pass frames from physical to network layer and advance window. */
to_network_layer(in_buf[frame_expected % NR_BUFS]);
no_nak = true;
arrived[frame_expected % NR_BUFS] = false;
frame_expected = increment(frame_expected); /* advance lower edge of receiver’s window */
too_far = increment(too_far); /* advance upper edge of receiver’s window */
start_ack_timer(); /* to see if a separate ack is needed */
}
}
}
if ((r.kind == PFrame.NAK) && between(ack_expected, (r.ack + 1) % (MAX_SEQ + 1), next_frame_to_send))
/*if NAK, check the frame is between the expected frames of the sliding window */
send_frame(PFrame.DATA, (r.ack + 1) % (MAX_SEQ + 1), frame_expected, out_buf);/*resend frame for that NAK*/
while (between(ack_expected, r.ack, next_frame_to_send)) {
enable_network_layer(1); //generate network_layer_ready event
stop_timer(ack_expected % NR_BUFS);/*frame has been received and acked, stop timer */
ack_expected = increment(ack_expected); /* advance lower edge of sender’s window */
}
break;
case (PEvent.CKSUM_ERR):
/**
*damaged frame arrived, send nak if no_nak
*/
if (no_nak)
send_frame(PFrame.NAK, 0, frame_expected, out_buf); /* damaged frame */
break;
case (PEvent.TIMEOUT):
/**
* timer expired for the frame, resend
* frame not ack by receiver and time out
* NAK or ACk could be lost
*/
send_frame(PFrame.DATA, oldest_frame, frame_expected, out_buf); /* we timed out */
break;
case (PEvent.ACK_TIMEOUT):
/**
* ack timer expired, send ack again
* ack could be lost or damaged
*/
send_frame(PFrame.ACK, 0, frame_expected, out_buf); /* ack timer expired; send ack */
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,
*/
/**
* Start a normal timer for frame
* @param seq sequence no
*/
private void start_timer(int seq) {
stop_timer(seq); /* stop timer*/
sender_timer[seq % NR_BUFS] = new Timer(); /*stop timer*/
sender_timer[seq % NR_BUFS].schedule(new FrameTimerTask(seq), 200);
}
/**
* Stop a normal timer for frame
* @param seq sequence no
*/
private void stop_timer(int seq) {
if (sender_timer[seq % NR_BUFS] != null) {
sender_timer[seq % NR_BUFS].cancel();
sender_timer[seq % NR_BUFS] = null;
}
}
/**
* Start an auxiliary ack timer for a frame
*/
private void start_ack_timer() {
if (receiver_timer == null) {
receiver_timer = new Timer(); /*start timer*/
receiver_timer.schedule(new AckTimerTask(), 50);
}
}
/**
* Stop an ack timer for a frame
*/
private void stop_ack_timer() {
if (receiver_timer != null) {
receiver_timer.cancel(); /*stop timer*/
receiver_timer = null;
}
}
class FrameTimerTask extends TimerTask {
private int seq;
public FrameTimerTask(int seq) {
this.seq = seq;
}
@Override
public void run() {
stop_timer(seq);
swe.generate_timeout_event(seq);
}
}
class AckTimerTask extends TimerTask {
@Override
public void run() {
stop_ack_timer();
swe.generate_acktimeout_event();
}
}
} //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).
*/