文件导入

selective repeat

和网络层/物理层的接口是由库函数提供,所以只是把数据链路层对包的处理贴上
[c]
/* file: datalink.c */
/* use: complete protocol 6, the selective repeat */
/* date: 2009 11 22 11:55:21 CST */
/* */
/* */
/* */
#include"protocol.h"
#include"datalink.h"
//no nak has been send yet
boolean no_nak = true;
static int phl_ready = 0;
/* check if the coming frame falls into the window */
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));
}
/* send frame throught pysical layer */
/* frame kind can be data/ack/nak */
static void send_out_frame(frame_kind fk, seq_nr frame_nr, seq_nr frame_expected, packet buffer[])
{
frame s;
unsigned int hold;
s.kind = fk;
if (fk == data) {
s.info = buffer[frame_nr % NR_BUFS];
dbg_frame("Send DATA %u %u, ID %d/n", s.seq, s.ack, *(short *)&(s.info));
}
s.seq = frame_nr;
s.ack = (frame_expected + MAX_SEQ) % (MAX_SEQ + 1); //ack the last received one
if (fk == nak) {
no_nak = false;
}
*((unsigned int *)((unsigned char *)&s + PKT_LEN + 12)) = crc32((unsigned char *)&s, PKT_LEN + 12);
send_frame((unsigned char *)&s, PKT_LEN + 12 + 4);
phl_ready = 0;
if (fk == data) {
start_timer(frame_nr % NR_BUFS, DATA_TIMER);
}
stop_ack_timer(); //no need for separate ack frame
}

/* main part, protocol 6, selective repeat */
int main(int argc, char **argv)
{
seq_nr ack_expected; //sender window lower edge
seq_nr next_frame_to_send; //sender window upper edge
seq_nr frame_expected; //receiver window lower edge
seq_nr too_far; //receiver window upper edge+1
int i, len, arg; //len->the length received from pysical layer, arg->who's data-timer is out
frame r;
packet out_buf[NR_BUFS];
packet in_buf[NR_BUFS];
boolean arrived[NR_BUFS]; //in bound bit map
seq_nr nbuffered; //how many output buffers currently used
int event;
//initialize, begin
protocol_init(argc, argv);
disable_network_layer();
lprintf("Designed by GuoZan && Luo Yaqun && MiYan BUPT-SCS, build:" __DATE__ "" __TIME__ "/n");
ack_expected = 0;
next_frame_to_send = 0;
frame_expected = 0;
too_far = NR_BUFS;
nbuffered = 0;
for (i = 0; i < NR_BUFS; ++i) {
arrived[i] = false;
}
//initialize end
while (true) {
event = wait_for_event(&arg);
switch (event) {
case NETWORK_LAYER_READY: //get one packet from network layer, then transimit to physical layer
++nbuffered; //expend the window
get_packet((unsigned char *)&(out_buf[next_frame_to_send % NR_BUFS]));
send_out_frame(data, next_frame_to_send, frame_expected, out_buf);//through physical layer
inc(next_frame_to_send); //advance upper window edge
break;
case FRAME_RECEIVED: //get from physical layer, put to network layer
len = recv_frame((unsigned char *)&r, sizeof(r));
if (len < 5 || (crc32((unsigned char *)&r, len) != 0)) {
dbg_event("****ReceiverError,BadCRCChecksum/n");
break;
}
if (r.kind == data) {
dbg_frame("Recv DATA %u %u,ID %d/n", r.seq, r.ack, *(short *) &(r.info));
if ((r.seq != frame_expected) && no_nak) {
send_out_frame(nak, 0, frame_expected, out_buf);
}
else {
start_ack_timer(ACK_TIMER);
}
if (between(frame_expected, r.seq, too_far) && ((arrived[r.seq % NR_BUFS]) == false)) {
//frames can be accepted in any order
arrived[r.seq % NR_BUFS] = true;
in_buf[r.seq % NR_BUFS] = r.info;
while (arrived[frame_expected % NR_BUFS]) {
//pass packet to network layer in order, and must be in order
put_packet((unsigned char *)&(in_buf[frame_expected % NR_BUFS]), len - 4 - 12);
no_nak = true;
arrived[frame_expected%NR_BUFS] = false;
inc(frame_expected); //reciver window low ++;
inc(too_far); //reciver windwo up ++
start_ack_timer(ACK_TIMER); //to see if seperate ack is needed
}
}
}
//the other side didn't want this packet, want another one, send him
if ((r.kind == nak)
&& between(ack_expected, (r.ack+1) % (MAX_SEQ+1), next_frame_to_send)) {
send_out_frame(data, (r.ack+1) % (MAX_SEQ+1), frame_expected, out_buf);
}
if (r.kind == ack) { //seperate ack received
dbg_frame("Recv ACK %d/n", r.ack);
}
//handle the acks
while (between(ack_expected, r.ack, next_frame_to_send)) {
--nbuffered; //window size decrease
stop_timer(ack_expected % NR_BUFS); //yeah, he received this packet, we can go forward now
inc(ack_expected); //sender window low ++
}
break;
case PHYSICAL_LAYER_READY:
phl_ready = 1;
break;
case DATA_TIMEOUT:
dbg_event("----DATA %d timeout/n", arg);
send_out_frame(data, arg, frame_expected, out_buf);
break;
case ACK_TIMEOUT:
send_out_frame(ack, 0, frame_expected, out_buf);
dbg_frame("Send ACK %d/n", r.ack);
break;
default:
lprintf("what? another event, there must be some fatal wrong!!!/n");
break;
}
//decide whether to receive more packet from network layer
(nbuffered < NR_BUFS) && phl_ready ? enable_network_layer() : disable_network_layer();
}
return 0;
}
[/c]

评论