Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <string.h>
- /* Statistics
- * Do NOT change the name/declaration of these variables
- * You need to set the value of these variables appropriately within your code.
- * */
- int A_application = 0;
- int A_transport = 0;
- int B_application = 0;
- int B_transport = 0;
- /* Globals
- * Do NOT change the name/declaration of these variables
- * They are set to zero here. You will need to set them (except WINSIZE) to some proper values.
- * */
- /* @ref Slide 3-63
- * TimeoutInterval = EstimatedRTT + 4*DevRTT
- * Since I don't have specific SampleRTTs I assume DevRTT = EstimatedRTT
- * 5 time units there and back = 10 time units = EstimatedRTT
- * Therefore TIMEOUT = 10 + 4*10 = 50 */
- float TIMEOUT = 50.0;
- int WINSIZE; //This is supplied as cmd-line parameter; You will need to read this value but do NOT modify it;
- int SND_BUFSIZE = 1000; //Sender's Buffer size
- int RCV_BUFSIZE = 1000; //Receiver's Buffer size
- /* Needed variables */
- struct pkt* A_buf;
- int A_bufindex;
- int A_nextavailseqnum;
- int A_base;
- float *A_timers;
- int *A_acks;
- float A_timestep;
- int *B_acks;
- struct msg* B_msgs;
- int B_base;
- /* Need to declare these interface functions to avoid conflicting type warnings */
- void tolayer3(int AorB, struct pkt packet);
- void starttimer(int AorB, float increment);
- void tolayer5(int AorB, char datasent[20]);
- /* An additional function to evaluate the checksum
- * @ref http://www.tutorialspoint.com/cprogramming/c_bitwise_operators.htm */
- int evalchecksum(packet)
- struct pkt packet;
- {
- int csum = packet.seqnum;
- csum += packet.acknum;
- int i, j;
- for (i=0; i<20; i+=4) {
- for (j=0; j<4; j++) {
- csum += ((int)packet.payload[i+j]) << 8*j;
- }
- }
- return (csum ^ 0xFFFFFFFF); //returns the one's complement
- }
- /* @ref Text on pages 223-229 and Figures 3.24 and 3.25 on page 226 */
- /* Called from layer 5, passed the data to be sent to other side */
- void A_output(message)
- struct msg message;
- {
- A_application++;
- //Buffer the packet
- A_buf[A_bufindex].seqnum = A_bufindex;
- A_buf[A_bufindex].checksum = evalchecksum(A_buf[A_bufindex]);
- memcpy(A_buf[A_bufindex].payload, message.data, 20);
- if (A_nextavailseqnum < (A_base + WINSIZE)) {
- printf("Packet %d is being sent.\n", A_bufindex);
- tolayer3(0, A_buf[A_bufindex]);
- A_timers[A_bufindex] = TIMEOUT;
- A_nextavailseqnum++;
- A_transport++;
- }
- A_bufindex++;
- }
- /* Called from layer 3, when a packet arrives for layer 4 */
- void A_input(packet)
- struct pkt packet;
- {
- if (evalchecksum(packet) == packet.checksum) {
- printf("Packet %d is ACKed.\n", packet.acknum);
- A_acks[packet.acknum] = 1;
- while (A_acks[A_base]) {
- A_base++;
- }
- A_timers[packet.acknum] = -1.0;
- //Send all the packets in the window
- int i;
- for (i=A_nextavailseqnum; (i<A_bufindex && i<(A_base + WINSIZE)); i++) {
- printf("Packet %d is being sent.\n", i);
- tolayer3(0, A_buf[i]);
- A_timers[i] = TIMEOUT;
- A_transport++;
- }
- A_nextavailseqnum = i;
- }
- }
- /* Called when A's timer goes off */
- void A_timerinterrupt()
- {
- starttimer(0, A_timestep);
- int i;
- for (i=0; i<SND_BUFSIZE; i++) {
- if (A_timers[i] >= 0) {
- A_timers[i] -= A_timestep;
- if (A_timers[i] < 0) {
- printf("Packet %d timed out! The packet is being resent.\n", i);
- tolayer3(0, A_buf[i]);
- A_timers[i] = TIMEOUT;
- A_transport++;
- }
- }
- }
- }
- /* 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_buf = malloc(SND_BUFSIZE * sizeof(struct pkt));
- A_bufindex = 1;
- A_nextavailseqnum = 1;
- A_base = 1;
- A_timers = malloc(SND_BUFSIZE);
- A_acks = malloc(SND_BUFSIZE);
- int i;
- for (i=0; i<SND_BUFSIZE; i++) {
- A_timers[i] = -1.0;
- A_acks[i] = 0;
- }
- A_timestep = 5.0; //1 timestep is the average time it takes a packet to go from one side to the other
- starttimer(0, A_timestep);
- }
- /* Note that with simplex transfer from A-to-B, there is no B_output() */
- void B_output(message) /* Needs to be completed only for extra credit */
- struct msg message;
- {
- }
- /* Called from layer 3, when a packet arrives for layer 4 at B*/
- void B_input(packet)
- struct pkt packet;
- {
- B_transport++;
- if (evalchecksum(packet) == packet.checksum) {
- printf("Packet %d has been received and it's uncorrupted.\n", packet.seqnum);
- //Set up the ACK and send it
- struct pkt ack;
- ack.acknum = packet.seqnum;
- ack.checksum = evalchecksum(ack);
- printf("ACKing packet %d.\n", ack.acknum);
- tolayer3(1, ack);
- B_acks[packet.seqnum] = 1;
- //Store message
- memcpy(B_msgs[B_base].data, packet.payload, 20);
- while (B_acks[B_base]) {
- printf("Sending message %d.\n", B_base);
- tolayer5(1, B_msgs[B_base].data);
- B_application++;
- B_base++;
- }
- }
- else {
- printf("A corrupted packet from layer 3 has been received!\n");
- }
- }
- /* Called when B's timer goes off */
- void B_timerinterrupt()
- {
- }
- /* The following routine will be called once (only) before any other */
- /* entity B routines are called. You can use it to do any initialization */
- void B_init()
- {
- B_acks = malloc(RCV_BUFSIZE);
- B_msgs = malloc(RCV_BUFSIZE * sizeof(struct msg));
- B_base = 1;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement