-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
1,250 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#ifndef SIMULATOR_H_ | ||
#define SIMULATOR_H_ | ||
|
||
#define BIDIRECTIONAL 0 | ||
|
||
/* 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]; | ||
}; | ||
|
||
/* Implementation framework interface */ | ||
void A_output(struct msg message); | ||
void B_output(struct msg message); | ||
void A_input(struct pkt packet); | ||
void A_timerinterrupt(); | ||
void A_init(); | ||
|
||
void B_input(struct pkt packet); | ||
void B_init(); | ||
|
||
/* Simulator API */ | ||
void starttimer(int AorB, float increment); | ||
void stoptimer(int AorB); | ||
void tolayer3(int AorB, struct pkt packet); | ||
void tolayer5(int AorB, char datasent[]); | ||
int getwinsize(); | ||
float get_sim_time(); | ||
|
||
#endif |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
#include "../include/simulator.h" | ||
|
||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <iostream> | ||
#include <cstring> | ||
#include <queue> | ||
|
||
using namespace std; | ||
|
||
|
||
/* ****************************************************************** | ||
ALTERNATING BIT AND GO-BACK-N NETWORK EMULATOR: VERSION 1.1 J.F.Kurose | ||
unidirectional data transfer | ||
protocols (from A to B). 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). | ||
**********************************************************************/ | ||
|
||
/********* STUDENTS WRITE THE NEXT SEVEN ROUTINES *********/ | ||
|
||
/* called from layer 5, passed the data to be sent to other side */ | ||
|
||
bool A_transmission_ready; | ||
float TIMEOUT = 11.0; | ||
|
||
int sequence_number_A; // Sequence number being sent | ||
int acknowlegde_number_A; | ||
|
||
int sequence_number_B; // Sequence number expected | ||
int acknowledge_number_B; // next sequence nnumber from A | ||
|
||
struct pkt packet_in_act; | ||
|
||
int checksum_generator(pkt packet); | ||
bool PacketCorrupted(pkt packet); | ||
|
||
queue<msg> message_queue; | ||
|
||
void A_output(struct msg message) | ||
{ | ||
if(A_transmission_ready){ | ||
//checking if A is ready to take a new message as an acknowledgement | ||
|
||
A_transmission_ready = false; | ||
// changing check to hold till acknowledgement is received | ||
|
||
packet_in_act = {}; | ||
// Reset the current packet | ||
|
||
strncpy(packet_in_act.payload,message.data,sizeof(packet_in_act.payload)); | ||
// Copying message to current packet payload | ||
packet_in_act.seqnum = sequence_number_A; | ||
packet_in_act.acknum = acknowlegde_number_A; | ||
packet_in_act.checksum = 0; | ||
|
||
packet_in_act.checksum = checksum_generator(packet_in_act); | ||
|
||
tolayer3(0, packet_in_act); | ||
|
||
starttimer(0, TIMEOUT); | ||
} | ||
else{ | ||
message_queue.push(message); | ||
} | ||
} | ||
|
||
/* called from layer 3, when a packet arrives for layer 4 */ | ||
void A_input(struct pkt packet) | ||
{ | ||
if(!PacketCorrupted(packet) && packet.acknum == sequence_number_A ){ | ||
//checking if packet is not corrupt | ||
stoptimer(0); | ||
sequence_number_A = !sequence_number_A; | ||
|
||
if(!message_queue.empty()){ | ||
msg next_msg = message_queue.front(); | ||
message_queue.pop(); | ||
A_transmission_ready = true; | ||
A_output(next_msg); | ||
} | ||
else | ||
A_transmission_ready = true; | ||
} | ||
} | ||
|
||
/* called when A's timer goes off */ | ||
void A_timerinterrupt() | ||
{ | ||
A_transmission_ready = false; | ||
tolayer3(0, packet_in_act); | ||
starttimer(0, TIMEOUT); | ||
} | ||
|
||
/* 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_transmission_ready = true; | ||
sequence_number_A = 0; | ||
acknowlegde_number_A = 0; | ||
} | ||
|
||
/* 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 packet) | ||
{ | ||
|
||
pkt ack_packet = {}; | ||
|
||
if(!PacketCorrupted(packet) && packet.seqnum == sequence_number_B){ | ||
tolayer5(1, packet.payload); | ||
ack_packet.acknum = sequence_number_B; | ||
ack_packet.checksum = 0; | ||
ack_packet.checksum = checksum_generator(ack_packet); | ||
tolayer3(1, ack_packet); | ||
sequence_number_B = !sequence_number_B; | ||
} | ||
else if(!PacketCorrupted(packet) && packet.seqnum != sequence_number_B){ | ||
ack_packet.acknum = !sequence_number_B; | ||
ack_packet.checksum = 0; | ||
ack_packet.checksum = checksum_generator(ack_packet); | ||
tolayer3(1, ack_packet); | ||
} | ||
|
||
} | ||
|
||
/* the following rouytine will be called once (only) before any other */ | ||
/* entity B routines are called. You can use it to do any initialization */ | ||
void B_init() | ||
{ | ||
sequence_number_B = 0; | ||
} | ||
|
||
int checksum_generator(pkt packet){ | ||
int checksum = 0; | ||
|
||
int seq_number = packet.seqnum; | ||
int ack_number = packet.acknum; | ||
|
||
checksum += seq_number; | ||
checksum += ack_number; | ||
|
||
for(int i=0; i<sizeof(packet.payload); i++) | ||
checksum += packet.payload[i]; | ||
|
||
return ~checksum; | ||
} | ||
|
||
bool PacketCorrupted(pkt packet){ | ||
|
||
if(packet.checksum == checksum_generator(packet)) | ||
return false; | ||
else | ||
return true; | ||
|
||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
#include "../include/simulator.h" | ||
|
||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <iostream> | ||
#include <cstring> | ||
#include <vector> | ||
|
||
using namespace std; | ||
|
||
/* ****************************************************************** | ||
ALTERNATING BIT AND GO-BACK-N NETWORK EMULATOR: VERSION 1.1 J.F.Kurose | ||
Unidirectional data transfer | ||
protocols (from A to B). 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). | ||
**********************************************************************/ | ||
|
||
float TIMEOUT = 25.0; | ||
|
||
int sequence_number_A; | ||
int acknowlegde_number_A; | ||
int window_size_A; | ||
int send_b; | ||
int next_sequence_number; | ||
|
||
int expected_sequence_B; | ||
|
||
vector <msg> msg_buffer; | ||
|
||
void send_data(); | ||
int checksum_generator(pkt packet); | ||
bool corrupt_pkt(pkt packet); | ||
|
||
/* called from layer 5, passed the data to be sent to other side */ | ||
void A_output(struct msg message) | ||
{ | ||
|
||
//Message is added to the queue | ||
msg_buffer.push_back(message); | ||
|
||
// The sending routine is started | ||
send_data(); | ||
} | ||
|
||
void send_data(){ | ||
|
||
while(next_sequence_number < send_b + window_size_A && next_sequence_number<msg_buffer.size()){ | ||
msg message = msg_buffer[next_sequence_number]; | ||
// Creation of Packets | ||
pkt packet; | ||
|
||
strncpy(packet.payload,message.data,sizeof(packet.payload)); | ||
// Copying message to current packet payload | ||
packet.seqnum = next_sequence_number; | ||
packet.acknum = acknowlegde_number_A; | ||
packet.checksum = 0; | ||
packet.checksum = checksum_generator(packet); | ||
tolayer3(0, packet); | ||
|
||
if(send_b == next_sequence_number){ | ||
starttimer(0, TIMEOUT); | ||
} | ||
next_sequence_number++; | ||
} | ||
} | ||
|
||
/* called from layer 3, when a packet arrives for layer 4 */ | ||
void A_input(struct pkt packet) | ||
{ | ||
|
||
if(!corrupt_pkt(packet)){ | ||
send_b = packet.acknum +1; | ||
if(send_b == next_sequence_number) | ||
stoptimer(0); | ||
else{ | ||
stoptimer(0); | ||
starttimer(0, TIMEOUT); | ||
} | ||
} | ||
} | ||
|
||
/* called when A's TIMEOUT goes off */ | ||
void A_timerinterrupt() | ||
{ | ||
next_sequence_number = send_b; | ||
send_data(); | ||
} | ||
|
||
/* 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() | ||
{ | ||
sequence_number_A = 0; | ||
acknowlegde_number_A = 0; | ||
window_size_A = getwinsize(); | ||
send_b = 0; | ||
next_sequence_number = 0; | ||
} | ||
|
||
/* 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 packet) | ||
{ | ||
if(!corrupt_pkt(packet) && expected_sequence_B == packet.seqnum){ | ||
// adding packet corruption check | ||
tolayer5(1, packet.payload); | ||
pkt received_acknowledgement; | ||
received_acknowledgement.acknum = expected_sequence_B; | ||
received_acknowledgement.checksum = 0; | ||
received_acknowledgement.checksum = checksum_generator(received_acknowledgement); | ||
tolayer3(1, received_acknowledgement); | ||
expected_sequence_B++; | ||
} | ||
} | ||
|
||
/* the following rouytine will be called once (only) before any other */ | ||
/* entity B routines are called. You can use it to do any initialization */ | ||
void B_init() | ||
{ | ||
expected_sequence_B = 0; | ||
} | ||
|
||
int checksum_generator(pkt packet){ | ||
int checksum = 0; | ||
int seq_number = packet.seqnum; | ||
int ack_number = packet.acknum; | ||
checksum += seq_number; | ||
checksum += ack_number; | ||
|
||
for(int i=0; i<sizeof(packet.payload); i++) | ||
checksum += packet.payload[i]; | ||
|
||
return ~checksum; | ||
} | ||
|
||
bool corrupt_pkt(pkt packet){ | ||
|
||
if(packet.checksum == checksum_generator(packet)) | ||
return false; | ||
else | ||
return true; | ||
|
||
} |
Oops, something went wrong.