#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
/* ******************************************************************
ALTERNATING BIT AND GO-BACK-N NETWORK EMULATOR: VERSION 1.1 J.F.Kurose
This code should be used for PA2, unidirectional or bidirectional
data transfer protocols (from A to B. Bidirectional transfer of data
is for extra credit and is not required). Network properties:
- one way network delay averages five time units (longer if there
are other messages in the channel for GBN), but can be larger
- packets can be corrupted (either the header or the data portion)
or lost, according to user-defined probabilities
- packets will be delivered in the order in which they were sent
(although some can be lost).
**********************************************************************/
#define BIDIRECTIONAL 0 /* change to 1 if you're doing extra credit */
/* and write a routine called B_output */
/* a "msg" is the data unit passed from layer 5 (teachers code) to layer */
/* 4 (students' code). It contains the data (characters) to be delivered */
/* to layer 5 via the students transport level protocol entities. */
struct msg {
char data[20];
};
/* a packet is the data unit passed from layer 4 (students code) to layer */
/* 3 (teachers code). Note the pre-defined packet structure, which all */
/* students must follow. */
struct pkt {
int seqnum;
int acknum;
int checksum;
char payload[20];
};
struct event {
float evtime; /* event time */
int evtype; /* event type code */
int eventity; /* entity where event occurs */
struct pkt *pktptr; /* ptr to packet (if any) assoc w/ this event */
struct event *prev;
struct event *next;
};
/* possible events: */
#define TIMER_INTERRUPT 0
#define FROM_LAYER5 1
#define FROM_LAYER3 2
#define OFF 0
#define ON 1
#define A 0
#define B 1
/********* STUDENTS WRITE THE NEXT SEVEN ROUTINES *********/
//框架函数声明
void init();
void generate_next_arrival();
void printevlist();
void insertevent(struct event *p);
void stoptimer(int AorB);
void starttimer(int AorB, float increment);
void tolayer3(int AorB, struct pkt packet);
void tolayer5(int AorB, struct msg message);
//根据FSM图定义A和B的状态
#define A_wait_for_call_0_from_above 0
#define A_wait_for_ACK_0 1
#define A_wait_for_call_1_from_above 2
#define A_wait_for_ACK_1 3
#define B_wait_for_0_from_below 0
#define B_wait_for_1_from_below 1
#define MAXTIME 100.0 //最大等待时间
int A_status, B_status;
struct pkt buffer_pkt; //用来备份当前传输的包
//做包
struct pkt* make_pkt(int seqnum, int acknum, struct msg message)
{
struct pkt* mypkt = (struct pkt*)malloc(sizeof(struct pkt));
mypkt->seqnum = seqnum;
mypkt->acknum = acknum;
for (int i = 0; i < 20; i++)
mypkt->payload[i] = message.data[i];
//计算校验和
int sum = 0;
for (int i = 0; i < 20; i++)
sum += (seqnum + acknum + (int) message.data[i]);
mypkt->checksum = sum;
return mypkt;
}
//判断包是否损坏
bool notCorrupt(struct pkt mypkt)
{
int sum = 0;
for (int i = 0; i < 20; i++)
sum += (mypkt.seqnum + mypkt.acknum + (int) mypkt.payload[i]);
if (sum == mypkt.checksum)
return true;
else
return false;
}
//缓存备份当前包
void buffer(struct pkt* mypkt)
{
buffer_pkt.seqnum = mypkt->seqnum;
buffer_pkt.acknum = mypkt->acknum;
buffer_pkt.checksum = mypkt->checksum;
for (int i = 0; i < 20; i++)
buffer_pkt.payload[i] = mypkt->payload[i];
}
//B端拆包
void extract(struct pkt mypkt, struct msg *message)
{
for (int i = 0; i < 20; i++)
message->data[i] = mypkt.payload[i];
}
/* called from layer 5, passed the data to be sent to other side */
void A_output(struct msg message) //接收应用层的message
{
//等待应用层传入0号数据
if(A_status == A_wait_for_call_0_from_above)
{
struct pkt* sndpkt = make_pkt(0, 0, message);
buffer(sndpkt);
tolayer3(A, *sndpkt);
starttimer(A, MAXTIME);
A_status = A_wait_for_ACK_0; //更新状态,等待ack0
free (sndpkt);
}
//等待应用层传入1号数据
else if (A_status == A_wait_for_call_1_from_above)
{
struct pkt* sndpkt = make_pkt(1, 1, message);
buffer(sndpkt);
tolayer3(A, *sndpkt);
starttimer(A, MAXTIME);
A_status = A_wait_for_ACK_1; //更新状态,等待ack1
free (sndpkt);
}
//其他情况为等待ack的状态,不做处置
}
void B_output(struct msg message) /* need be completed only for extra credit */
{
//不做处理
}
/* called from layer 3, when a packet arrives for layer 4 */
void A_input(struct pkt mypkt) //接收网络层的pkt,检验ack
{
if (A_status == A_wait_for_ACK_0)
{
printf("-----A looking forword ack 0,recive ack %d-----\n", mypkt.acknum);
if(notCorrupt(mypkt) && mypkt.acknum == 0) //正确回应
{
stoptimer(A);
A_status = A_wait_for_call_1_from_above;
}
else
printf("-----Wrong pkt-----\n");
}
else if (A_status == A_wait_for_ACK_1)
{
printf("-----A looking forword ack 1,recive ack %d-----\n", mypkt.acknum);
if(notCorrupt(mypkt) && mypkt.acknum == 1) //正确回应
{
stoptimer(A);
A_status = A_wait_for_call_0_from_above;
}
else
printf("-----Wrong pkt-----\n");
}
//其他情况为等待应用层传输,不做处置
}
/* called when A's timer goes off */
void A_timerinterrupt()
{
tolayer3(A, buffer_pkt);
starttimer(A, MAXTIME);
}
/* the following routine will be called once (only) before any other */
/* entity A routines are called. You can use it to do any initialization */
void A_init()
{
A_status = A_wait_for_call_0_from_above;
}
/* Note that with simplex transfer from a-to-B, there is no B_output() */
/* called from layer 3, when a packet arrives for layer 4 at B*/
void B_input(struct pkt mypkt)
{
struct msg message;
struct pkt* sndpkt;
extract(mypkt, &message);
if(B_status == B_wait_for_0_from_below) //期望收到0号包
{
printf("-----B looking forword pkt 0,recive seq %d-----\n", mypkt.seqnum);
if(notCorrupt(mypkt) && mypkt.seqnum == 0)
{ //收到正确0号包
tolayer5(B, message);
sndpkt = make_pkt(0, 0, message); //这里的seqnum不影响,可随意赋值
B_status = B_wait_for_1_from_below;
}
else if(!(notCorrupt(mypkt)) || mypkt.seqnum == 1)
{ //收到错误包
sndpkt = make_pkt(0, 1, message); //这里的seqnum不影响,可随意赋值
printf("-----Wrong pkt-----\n");
}
else
{ //其他错误
sndpkt = make_pkt(0, 1, message); //这里的seqnum不影响,可随意赋值
}
tolayer3(B, *sndpkt);
free (sndpkt);
}
else if(B_status == B_wait_for_1_from_below) //期望收到1号包
{
printf("-----B looking forword pkt 1,recive seq %d-----\n", mypkt.seqnum);
if(notCorrupt(mypkt) && mypkt.seqnum == 1)
{ //收到正确1号包
tolayer5(B, message);
sndpkt = make_pkt(0, 1, message); //这里的seqnum不影响,可随意赋值
B_status = B_wait_for_0_from_below;
}
else if(!(notCorrupt(mypkt)) || mypkt.seqnum == 0)
{ //收到错误包
sndpkt = make_pkt(0, 0, message); //这里的seqnum不影响,可随意赋值
printf("-----Wrong pkt-----\n");
}
else
{ //其他错误
sndpkt = make_pkt(0, 0, message); //这里的seqnum不影响,�