Last active
January 3, 2024 04:55
-
-
Save aziflaj/8d0620f5dca818f7bcbb 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
#define MAX_PKT 1024 /* packet size in bytes */ | |
typedef enum { false, true } boolean; /* boolean type */ | |
typedef unsigned int seq_nr; /* sequence or ACK numbers */ | |
typedef struct { | |
unsigned char data[MAX_PKT]; | |
} packet; /* packet definition */ | |
typedef enum { data, ack, nak } frame_kind; /* frame kind definition */ | |
typedef struct { | |
frame_kind kind; /* what kind of frame? */ | |
seq_nr seq; /* sequence number */ | |
seq_nr ack; /* ACK number */ | |
packet info; /* the Network layer packet */ | |
} frame; | |
/* wait for an event to happen; return its type of event */ | |
void wait_for_event(event_type *event); | |
/* fetch a packet from the network layer for transmission */ | |
void from_network_layer(packet *p); | |
/* deliver information from an inbound frame to the network layer */ | |
void to_network_layer(packet *p); | |
/* get an inbound frame from the physical layer */ | |
void from_physical_layer(frame *r); | |
/* pass the frame to the physical layer */ | |
void to_physical_layer(frame *s); | |
/* start the clock and enable the timeout event */ | |
void start_timer(seq_nr k); | |
/* stop the clock and disable the timeout event */ | |
void stop_timer(seq_nr k); | |
/* start an auxiliary timer and enable the ack_timeout event */ | |
void start_ack_timer(seq_nr k); | |
/* stop an auxiliary timer and disable the ack_timeout event */ | |
void stop_ack_timer(seq_nr k); | |
/* allow the network to cause a network_layer_ready event */ | |
void enable_network_layer(void); | |
/* forbid the network to cause a network_layer_ready event */ | |
void disable_network_layer(void); | |
/* macro inc */ | |
#define inc(k) if (k < MAX_SEQ) k = k + 1; else k = 0 |
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
#define MAX_SEQ 7 /* should be 2*n-1 */ | |
#define NR_BUFS ((MAX_SEQ+1)/2) | |
typedef enum { | |
frame_arrival, | |
cksum_err, | |
timeout, | |
network_layer_ready, | |
ack_timeout | |
} event_type; | |
#include "protocol.h" | |
boolean no_nak= true; /* no nak has been sent yet */ | |
seq_nr oldest_frame = MAX_SEQ + 1; | |
static boolean between(seq_nr a, seq_nr b, seq_nr c) { | |
return ( | |
(a <= b && b < c) || | |
(c < a && a <= b) || | |
(b < c && c < a) | |
); | |
} | |
static void send_frame(frame_kind fk, seq_nr frame_nr, seq_nr frame_expected, packet buffer[]) { | |
/* construct and send a data, ack or nak frame */ | |
frame s; /* scratch variable */ | |
s.kind = fk; /* kind of frame: data|ack|nak */ | |
if (fk == data) | |
s.info = buffer[frame_nr % NR_BUFS]; | |
s.seq = frame_nr; | |
s.ack = (frame_expected + MAX_SEQ) % (MAX_SEQ + 1); | |
if (fk == nak) | |
no_nak = false; | |
to_physical_layer(&s); /* transmit the frame */ | |
if (fk == data) | |
start_timer(frame_nr % NR_BUFS); | |
stop_ack_timer(); /* no need for separate ack frame */ | |
} | |
void protocol6() { | |
seq_nr ack_expected; /* lower edge of sender's window */ | |
seq_nr next_frame_to_send; /* upper edge + 1 */ | |
seq_nr frame_expected; /* lower edge of receiver's window */ | |
seq_nr too_far; /* upper edge + 1 */ | |
int i; /* buffer pool index */ | |
frame r; /* scratch variable */ | |
packet out_buff[NR_BUFS]; /* outbound stream buffers */ | |
packet in_buff[NR_BUFS]; /* inbound stream buffers */ | |
boolean arrived[NR_BUFS]; /* inbound bit map */ | |
seq_nr nbuffered; /* output buffers in use */ | |
event_type event; | |
enable_network_layer(); /* init */ | |
ack_expected = 0; /* ack expected on inbound stream */ | |
next_frame_to_send = 0; /* the outgoing frame */ | |
frame_expected = 0; | |
too_far = NR_BUFS; | |
nbuffered = 0; /* no buffers in use */ | |
for (i = 0; i < NR_BUFS; i++) | |
arrived[i] = false; | |
while (true) { | |
wait_for_event(&event); /* 5 different events */ | |
switch(event) { | |
/* accept, save and transmit a new frame */ | |
case network_layer_ready: | |
nbuffered++; /* 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; | |
/* a data/control frame arrived */ | |
case frame_arrival: | |
from_physical_layer(&r); /* fetch frame */ | |
/* data frame OK */ | |
if(r.kind == data) { | |
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 accepted in any order */ | |
arrived[r.seq % NR_BUFS] = true; /* buffer marked 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 */ | |
inc(too_far) /* advance upper edge of receiver */ | |
start_ack_timer(); /* check if separated ack is needed */ | |
} | |
} | |
} | |
if((r.kind == nak) && | |
between(ack_expended, (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--; /* handle piggyback ack */ | |
stop_timer(ack_expected % NR_BUFS); /* frame arrived OK */ | |
inc(ack_expected); /* advance lower edge of sender */ | |
} | |
} | |
break; | |
/* damaged frame */ | |
case cksum_err: | |
if (no_nak) | |
send_frame(nak, 0, frame_expected, out_buf); | |
break; | |
/* we timed out */ | |
case timeout: | |
send_frame(data, oldest_frame, frame_expected, out_buf); | |
break; | |
/* ack timer expired; resend ack */ | |
case ack_timeout: | |
send_frame(ack, 0, frame_expected, out_buf); | |
break; | |
} | |
if (nbuffered < NR_BUFS) | |
enable_network_layer(); | |
else | |
disable_network_layer(); | |
} | |
} |
Phobia-Cosmos
commented
Jan 3, 2024
via email
Oh, that's still a bit of a pity, I'm studying in China, but our textbook doesn't have the specific code on top, only the introduction of the relevant protocols, and then the code that the teacher gave us was your protocal.h (which he hadn't yet given completely), well in that case I'll just go and see how to run it again, thank you for your answer!
Idiot
***@***.***
…------------------ 原始邮件 ------------------
发件人: "reply+AZRLT3576FN3J2KLW2UHZPODUF2DFEVBM7HACX7W24" ***@***.***>;
发送时间: 2024年1月3日(星期三) 凌晨1:02
***@***.***>;
***@***.***>;
主题: Re: aziflaj/protocol.h
@aziflaj commented on this gist.
@Phobia-Cosmos it has been a really long time since I published this. I don't really remember what the point of these protocols was, but most likely they were part of a Networking homework/course project when I was in college. I'd suggest you take a look at Tanenbaum's Computer Networks; as far as I remember there were a bunch of networking protocols listed there and the book might have more details as to how this code can be ran.
Out of curiosity, where/what are you studying? I didn't know there's a teacher out there using my code from ~10 years ago as a reference
—
Reply to this email directly, view it on GitHub or unsubscribe.
You are receiving this email because you were mentioned.
Triage notifications on the go with GitHub Mobile for iOS or Android.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment