-
Notifications
You must be signed in to change notification settings - Fork 0
/
protocol.c
122 lines (104 loc) · 4.98 KB
/
protocol.c
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
/* Protocol 5 (Go-back-n) allows multiple outstanding frames. The sender may
* transmit up to MAX_SEQ frames without waiting for an ack. In addition, unlike
* in the previous protocols, the network layer is not assumed to have a new
* packet all the time. Instead, the network layer causes a network layer ready
* event when there is a packet to send. */
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include "protocol.h"
#include "simulator.h"
static bool between(seq_nr a, seq_nr b, seq_nr c) {
/* Return true if a <= b < c circularly; false otherwise. */
if (((a <= b) && (b < c)) || ((c < a) && (a <= b)) || ((b < c) && (c < a)))
return (true);
else
return (false);
}
static void send_data(simulator_state *simulator, seq_nr frame_nr,
seq_nr frame_expected, packet buffer[]) {
printf("Sending Frame #%d: %s\n", frame_nr, buffer[frame_nr].data);
/* Construct and send a data frame.*/
frame s; /* scratch variable */
s.info = buffer[frame_nr]; /* insert packet into frame */
s.seq = frame_nr; /* insert sequence number into frame */
s.ack = (frame_expected + MAX_SEQ) % (MAX_SEQ + 1); /* piggyback ack */
to_physical_layer(simulator, &s); /* transmit the frame */
start_timer(simulator, frame_nr); /* start the timer running */
}
int main(int argc, char **argv) {
char *mode_of_operation = argv[1];
bool is_server = strncmp(mode_of_operation, "server", 6) == 0 ? true : false;
simulator_state simulator;
simulator_init(&simulator, 1024, is_server);
struct sigaction sig_int_handler;
sig_int_handler.sa_handler = handle_signals;
sigemptyset(&sig_int_handler.sa_mask);
sig_int_handler.sa_flags = 0;
sigaction(SIGINT, &sig_int_handler, NULL);
seq_nr next_frame_to_send; /* MAX_SEQ > 1; used for outbound stream */
seq_nr ack_expected; /* oldest frame as yet unacknowledged */
seq_nr frame_expected; /* next frame expected on inbound stream */
frame r; /* scratch variable */
packet buffer[MAX_SEQ + 1]; /* buffers for the outbound stream */
seq_nr nbuffered; /* number of output buffers currently in use */
seq_nr i; /* used to index into the buffer array */
event_type event;
enable_network_layer(&simulator); /* allow network layer ready events */
ack_expected = 0; /* next ack expected inbound */
next_frame_to_send = 0; /* next frame going out */
frame_expected = 0; /* number of frame expected inbound */
nbuffered = 0; /* initially no packets are buffered */
while (true) {
wait_for_event(&simulator,
&event); /* four possibilities: see event type above */
switch (event) {
case network_layer_ready: /* the network layer has a packet to send */
/* Accept, save, and transmit a new frame. */
from_network_layer(&simulator,
&buffer[next_frame_to_send]); /* fetch new packet */
printf("Received Frame #%d from the network layer: %s\n",
next_frame_to_send, buffer[next_frame_to_send].data);
nbuffered = nbuffered + 1; /* expand the sender’s window */
send_data(&simulator, next_frame_to_send, frame_expected,
buffer); /* transmit the frame */
inc(next_frame_to_send); /* advance sender’s upper window edge */
break;
case frame_arrival: /* a data or control frame has arrived */
from_physical_layer(&simulator,
&r); /* get incoming frame from physical layer */
printf("Received Frame #%d from the physical layer: %s\n", r.seq,
r.info.data);
if (r.seq == frame_expected) {
/* Frames are accepted only in order. */
to_network_layer(&simulator,
&r.info); /* pass packet to network layer */
inc(frame_expected); /* advance lower edge of receiver’s window */
}
/* Ack n implies n − 1, n − 2, etc. Check for this. */
while (between(ack_expected, r.ack, next_frame_to_send)) {
/* Handle piggybacked ack.*/
nbuffered = nbuffered - 1; /* one frame fewer buffered */
stop_timer(&simulator,
ack_expected); /* frame arrived intact; stop timer */
inc(ack_expected); /* contract sender’s window */
}
break;
case cksum_err:
break; /* just ignore bad frames */
case timeout: /* trouble; retransmit all outstanding frames */
printf("Frame #%d timed out\n", ack_expected);
next_frame_to_send = ack_expected; /* start retransmitting here */
for (i = 1; i <= nbuffered; i++) {
send_data(&simulator, next_frame_to_send, frame_expected,
buffer); /* resend frame */
inc(next_frame_to_send); /* prepare to send the next one */
}
}
if (nbuffered < MAX_SEQ)
enable_network_layer(&simulator);
else
disable_network_layer(&simulator);
}
simulator_free(&simulator, is_server);
}