void B_input(struct pkt packet) { //struct pkt new_packet_b; int my_checksum=0; B_transport++; my_checksum=packet.seqnum+packet.acknum; for(int i=0;i<20;i++) my_checksum+=packet.payload[i]; memset(new_packet_b.payload,'\0',20); if(expectedseqno==0) { new_packet_b.seqnum=-1; new_packet_b.acknum=1; new_packet_b.checksum=new_packet_b.acknum+new_packet_b.seqnum; for(int i=0;i<20;i++) new_packet_b.checksum+=new_packet_b.payload[i]; } if((my_checksum==packet.checksum )&& (packet.seqnum ==expectedseqno))//reject out of order packets { tolayer5(1,packet.payload); B_application++; new_packet_b.acknum=1; new_packet_b.seqnum=expectedseqno; new_packet_b.checksum=new_packet_b.acknum+new_packet_b.seqnum; for(int i=0;i<20;i++) new_packet_b.checksum+=new_packet_b.payload[i]; tolayer3(1,new_packet_b); expectedseqno++; } else { tolayer3(1,new_packet_b);//to tell sender which packet is needed } }
/*Sender State that handles acknowledgment*/ void A_Receiver_State(struct pkt packet) { bool corrupt = isPacketCorrupt(packet.checksum,packet.seqnum,packet.acknum,packet.payload); int acknum = packet.acknum; if(!corrupt) { base = acknum+1; int endOfWindow = base +windowSize; //send all packets from nextseq to end of new windowsize which are in buffer while(nextSequenceNum<endOfWindow && nextSequenceNum<senderPacketCounter) { tolayer3(A,senderBuffer[nextSequenceNum]); nextSequenceNum++; } if(base==nextSequenceNum) //All acknowledgements have been have been received { stoptimer(A); } //one ack have been received, thus send one packet from new window else { stoptimer(A); starttimer(A,timeout); } } }
/* * B_input(packet),where packet is a structure of type pkt. This routine * will be called whenever a packet sent from the A-side (i.e., as a result * of a tolayer3() being done by a A-side procedure) arrives at the B-side. * packet is the (possibly corrupted) packet sent from the A-side. */ void B_input(struct pkt packet) { struct pkt ack; if (iscorrupt(packet)) { return; } if (packet.acknum == DATAACK) { if (!iscorrupt(packet) && packet.seqnum != Bexpectedseqnum) { //wrong seq num ack = Bpastack; tolayer3(BEntity,ack); return; } if (!iscorrupt(packet) && packet.seqnum == Bexpectedseqnum) { //right seqnum ack.checksum = 0; ack.seqnum = packet.seqnum; ack.acknum = ACK; memcpy(ack.payload,packet.payload,MESSAGE_LENGTH); ack.checksum = genchecksum(ack); Bpastack = ack; tolayer3(BEntity,ack); struct msg message; memcpy(message.data,packet.payload,MESSAGE_LENGTH); tolayer5(BEntity,message); Bexpectedseqnum++; return; } } ////new stuff if (packet.acknum == ACK) { if (Bbase >= (packet.seqnum + 1)) { if (packet.seqnum + 1 == Bnextseqnum) { stopTimer(BEntity); } return; } Bbase = packet.seqnum + 1; if (Bbase == Bnextseqnum) { stopTimer(BEntity); } else { stopTimer(BEntity); startTimer(BEntity,TIMERAMT); } } ////old stuff }
/*Initial state of receiver side*/ void B_Initial_State(struct pkt packet) { struct msg message; createMessageforLayer5(&packet,&message); bool corrupt = isPacketCorrupt(packet.checksum,packet.seqnum,packet.acknum,message.data); int seqnum = packet.seqnum; struct pkt datapacket; //creating packet containing acknowledgment int checksum=0; if(!corrupt && seqnum==expectedSeqNum) { int ack=expectedSeqNum; //send ack for received packet createDataPacket(&datapacket,0,ack,checksum,""); createCheckSum(&datapacket); //set checksum datapacket.acknum = expectedSeqNum; //re assigning value for correctness tolayer3(B,datapacket); tolayer5(B,message.data); int i; for(i=0;i<20;i++) { printf("%c",message.data[i]); } printf("\n"); //printf("\nB SIDE : Printing Packet payload Sent Above %s\n",message.data); //printf("\nB SIDE : Printing Acknum %d sent from B to A \n",datapacket.acknum); //incrementing the expected sequence number expectedSeqNum++; } else //send previous acknowledgment { int ack =expectedSeqNum-1; createDataPacket(&datapacket,0,ack,checksum,""); createCheckSum(&datapacket); //set checksum datapacket.acknum = expectedSeqNum-1; //reassign for correctness tolayer3(B,datapacket); } }
void send_nack(int caller, struct pkt *pkt_to_nack) { int seqnum = pkt_to_nack->seqnum; char msg[MSGSIZE] = {'N','A','C','K',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; struct pkt *nack_pkt = make_pkt(seqnum, msg); nack_pkt->acknum = 0; tolayer3(caller, *nack_pkt); }
struct pkt send_packet(int target, int seq, int ack, char* payload) { struct pkt packet_out; packet_out = make_packet(seq, ack, payload); printf("%c: Sending packet (%d, %d, %d ,'%s')\n",(target == 0) ? 'A' : 'B' ,packet_out.seqnum, packet_out.acknum, packet_out.checksum, packet_out.payload); stats.packets_sent++; tolayer3(target, packet_out); //send out the built packet from A return packet_out; }
/* * A_timerinterrupt() This routine will be called when A's timer expires * (thus generating a timer interrupt). You'll probably want to use this * routine to control the retransmission of packets. See starttimer() * and stoptimer() in the writeup for how the timer is started and stopped. */ void A_timerinterrupt() { int i; for (i = Abase; i < (Anextseqnum - Abase - 1), i < (Abase + WINDOW_SIZE); i++) { if (Aglobalarray[i] == NULL) { //removed timer here return; } tolayer3(AEntity, *Aglobalarray[i]); } startTimer(AEntity, TIMERAMT); return; }
/*Initial Sender State*/ void A_Initial_State() { //printf("before if loop nextseq %d, base+window %d\n",nextSequenceNum,(base+windowSize)); if(nextSequenceNum<(base+windowSize)) { //printf("Entered if loop\n"); tolayer3(A,senderBuffer[nextSequenceNum]); if(base==nextSequenceNum) starttimer(A,timeout); nextSequenceNum++; } }
/*Function sends packets in between the window base and (nextSeqNum-1) * It is called during timeout of oldest unAcknowledged packet*/ void reSendAllIntermediatePackets() { int i; int tempBase =base; int msgCount = nextSequenceNum-base-1; //number of packets to be sent //printf("msgcount value %d\n",msgCount); for(i=0;i<msgCount;i++) { //printf("tempBase value %d\n",tempBase); tolayer3(A,senderBuffer[tempBase]); //printf("^^^^^^^^^^^^^^^^^^^^^ RESENT MESSAGES %s\n",senderBuffer[tempBase].payload); tempBase++; } }
/* * B_timerinterrupt() This routine will be called when B's timer expires * (thus generating a timer interrupt). You'll probably want to use this * routine to control the retransmission of packets. See starttimer() * and stoptimer() in the writeup for how the timer is started and stopped. */ void B_timerinterrupt() { ////new stuff int i; for (i = Bbase; i < (Bnextseqnum - Bbase - 1), i < (Bbase + WINDOW_SIZE); i++) { if (Bglobalarray[i] == NULL) { //removed timer here return; } tolayer3(BEntity, *Bglobalarray[i]); } startTimer(BEntity, TIMERAMT); return; ////old stuff }
/* called when A's timer goes off */ void A_timerinterrupt() //ram's comment - changed the return type to void. { //printf("\n in A_timerinterrupt.. Calling startimer"); starttimer(0,TIMEOUT); timer_A_started=1; int i; for(i=base;i<nextseqnum;i++)// send packets in window { tolayer3(0,my_packet[i]); A_transport++; } }
/*Initial state of receiver side*/ void B_Initial_State(struct pkt packet) { struct msg message; createMessageforLayer5(&packet, &message); bool corrupt = isPacketCorrupt(packet.checksum, packet.seqnum, packet.acknum, message.data); int seqnum = packet.seqnum; struct pkt datapacket; //creating packet containing acknowledgment int checksum = 0; if (!corrupt) { //send ack for all packets lying under below range if (seqnum >= (receiverBase - receiverWindowSize) && seqnum <= (receiverBase + receiverWindowSize - 1)) { int ack = seqnum; //send ack for received packet createDataPacket(&datapacket, 0, ack, checksum, ""); createCheckSum(&datapacket); //set checksum datapacket.acknum = seqnum; //re assigning value for correctness tolayer3(B, datapacket); //this is done irrespective of any action //printf("\nB SIDE : Printing Acknum %d sent from B to A \n", // datapacket.acknum); B_StoreMessageInReceiverBuffer(seqnum, &message); //marks AckSent as true } //for values lying under current window if (seqnum >= receiverBase && seqnum <= (receiverBase + receiverWindowSize - 1)) { /* Handling data sent to layer5*/ int returnVal = returnNextMaximumContiguousSequenceAcknowledged(B); if (returnVal != -1) { sendMessagestoLayer5(returnVal); } } } //Un_corrupt packet Loop Ends }
/*Function sends packet with "Id" nextSeqNumber, Also add event to timer List*/ void A_sendPacket(int sequence) { insertLinkedList(sequence, get_sim_time()); tolayer3(A, senderBuffer[sequence]); //printf("Packet sent from A to B Sequence Number : %d \n",sequence); if (nextSequenceNum == base) //whenever it starts fresh after receiving all Acks, start the timer { //printf("TIMER HAS BEEN STARTED at %f\n",get_sim_time()); //stoptimer(A); starttimer(A, timeout); } }
/* called when A's timer goes off */ void A_timerinterrupt(void) { int i; if (TRACE > 0) printf("----A: time out,resend packets!\n"); for(i=0; i<windowcount; i++) { if (TRACE > 0) printf ("---A: resending packet %d\n", (buffer[(windowfirst+i) % WINDOWSIZE]).seqnum); tolayer3(A,buffer[(windowfirst+i) % WINDOWSIZE]); packets_resent++; if (i==0) starttimer(A,RTT); } }
void A_output(struct msg message) { Atemp = (struct pkt*) malloc(sizeof(struct pkt)); memcpy(Atemp->payload,message.data,MESSAGE_LENGTH); Atemp->seqnum = Anextseqnum; Atemp->acknum = DATAACK; Atemp->checksum = 0; Atemp->checksum = genchecksum(*Atemp); Aglobalarray[Anextseqnum] = Atemp; if (Anextseqnum < (Abase + WINDOW_SIZE)) { //(!getTimerStatus( AEntity )) { //will succeed if timer is off tolayer3(AEntity,*Atemp); if (Abase == Anextseqnum) { startTimer(AEntity,TIMERAMT); } } Anextseqnum++; return; }
/* called from layer 3, when a packet arrives for layer 4 at B*/ void B_input(struct pkt packet) { struct pkt sendpkt; int i; /* if not corrupted and received packet is in order */ if ( (!IsCorrupted(packet)) && (packet.seqnum == expectedseqnum) ) { if (TRACE > 0) printf("----B: packet %d is correctly received, send ACK!\n",packet.seqnum); packets_received++; /* deliver to receiving application */ tolayer5(B, packet.payload); /* send an ACK for the received packet */ sendpkt.acknum = expectedseqnum; /* update state variables */ expectedseqnum = (expectedseqnum + 1) % SEQSPACE; } else { /* packet is corrupted or out of order resend last ACK */ if (TRACE > 0) printf("----B: packet corrupted or not expected sequence number, resend ACK!\n"); if (expectedseqnum == 0) sendpkt.acknum = SEQSPACE - 1; else sendpkt.acknum = expectedseqnum - 1; } /* create packet */ sendpkt.seqnum = B_nextseqnum; B_nextseqnum = (B_nextseqnum + 1) % 2; /* we don't have any data to send. fill payload with 0's */ for ( i=0; i<20 ; i++ ) sendpkt.payload[i] = '0'; /* computer checksum */ sendpkt.checksum = ComputeChecksum(sendpkt); /* send out packet */ tolayer3 (B, sendpkt); }
/* called from layer 5 (application layer), passed the message to be sent to other side */ void A_output(struct msg message) { struct pkt sendpkt; int i; /* if not blocked waiting on ACK */ if ( windowcount < WINDOWSIZE) { if (TRACE > 1) printf("----A: New message arrives, send window is not full, send new messge to layer3!\n"); /* create packet */ sendpkt.seqnum = A_nextseqnum; sendpkt.acknum = NOTINUSE; for ( i=0; i<20 ; i++ ) sendpkt.payload[i] = message.data[i]; sendpkt.checksum = ComputeChecksum(sendpkt); /* put packet in window buffer */ /* windowlast will always be 0 for alternating bit; but not for GoBackN */ windowlast = (windowlast + 1) % WINDOWSIZE; buffer[windowlast] = sendpkt; windowcount++; /* send out packet */ if (TRACE > 0) printf("Sending packet %d to layer 3\n", sendpkt.seqnum); tolayer3 (A, sendpkt); /* start timer if first packet in window */ if (windowcount == 1) starttimer(A,RTT); /* get next sequence number, wrap back to 0 */ A_nextseqnum = (A_nextseqnum + 1) % SEQSPACE; } /* if blocked, window is full */ else { if (TRACE > 0) printf("----A: New message arrives, send window is full\n"); window_full++; } }
/* called from layer 5, passed the data to be sent to other side */ void A_output(struct msg message) //ram's comment - students can change the return type of the function from struct to pointers if necessary { //Buffer 1000 packets, used it to send when window moves ahead if(SND_BUFSIZE<1000) { A_application++; strncpy(buffer[SND_BUFSIZE].data, message.data,20); SND_BUFSIZE++; } if(nextseqnum<(base+WINSIZE)){ struct pkt packet_a; strncpy(packet_a.payload,buffer[nextseqnum].data,20); packet_a.seqnum=nextseqnum; packet_a.acknum=-1;//it is not acknowledgment packet_a.checksum=packet_a.seqnum+packet_a.acknum; for(int i=0;i<20;i++) packet_a.checksum+=packet_a.payload[i]; my_packet[my_packet_no++]=packet_a; tolayer3(0,packet_a); A_transport++; if(base==nextseqnum) { starttimer(0,TIMEOUT); timer_A_started=1; } nextseqnum++; } }
/* * Just like A_output, but residing on the B side. USED only when the * implementation is bi-directional. */ void B_output(struct msg message) { //////new stuff Btemp = (struct pkt*) malloc(sizeof(struct pkt)); memcpy(Btemp->payload,message.data,MESSAGE_LENGTH); Btemp->seqnum = Bnextseqnum; Btemp->acknum = DATAACK; Btemp->checksum = 0; Btemp->checksum = genchecksum(*Btemp); Bglobalarray[Bnextseqnum] = Btemp; if (Bnextseqnum < (Bbase + WINDOW_SIZE)) { //(!getTimerStatus( AEntity )) { //will succeed if timer is off tolayer3(BEntity,*Btemp); if (Bbase == Bnextseqnum) { startTimer(BEntity,TIMERAMT); } } Bnextseqnum++; return; /////old stuff }
/* * B_input(packet),where packet is a structure of type pkt. This routine * will be called whenever a packet sent from the A-side (i.e., as a result * of a tolayer3() being done by a A-side procedure) arrives at the B-side. * packet is the (possibly corrupted) packet sent from the A-side. */ void B_input(struct pkt packet) { struct msg message; // Store message retrived from network struct pkt ack; // Store ack packet // Pass message to layer 5 when it not corrupted and when it has expected seqnum if (not_corrupted(packet) && (packet.seqnum == rev_seqnum)) { strncpy(message.data, packet.payload, MESSAGE_LENGTH); tolayer5(BEntity, message); // Make ack message ack = prepare_pkt(1, rev_seqnum, NULL); // flip expected sequence number of packet rev_seqnum = !rev_seqnum; } else { // Make ack message ack = prepare_pkt(1, !rev_seqnum, NULL); } // Send ack message tolayer3(BEntity, ack); }
void send_pkt(int caller, struct pkt *pkt_to_send) { tolayer3(caller, *pkt_to_send); starttimer(caller, TIMEOUT); }
/* called from layer 3, when a packet arrives for layer 4 */ void A_input(struct pkt packet) { /*printf("\nIn a_input"); printf("\n Packet details- seqnum %d acknum %d checksum %d payload %s \n", packet.seqnum, packet.acknum, packet.checksum, packet.payload);*/ int my_checksum=packet.seqnum+packet.acknum; for(int i=0;i<20;i++) my_checksum+=packet.payload[i]; //if ((my_checksum==packet.checksum)) if ((my_checksum==packet.checksum) ) { if(base != (packet.seqnum+1)) { base=packet.seqnum+1;//move window ahead if(base==nextseqnum) { if(timer_A_started==1) { stoptimer(0); timer_A_started=0; } } else { if(timer_A_started==1) { stoptimer(0); timer_A_started=0; } starttimer(0,TIMEOUT); timer_A_started=1; } } //transmit all buffered packets if are in window int buf_index=base; while((nextseqnum<(base+WINSIZE)) && (nextseqnum< SND_BUFSIZE)){ printf("\n**********Sending packet in A_input"); struct pkt packet_a; strncpy(packet_a.payload,buffer[nextseqnum].data,20); packet_a.seqnum=nextseqnum; packet_a.acknum=-1;//it is not acknowledgment packet_a.checksum=packet_a.seqnum+packet_a.acknum; for(int i=0;i<20;i++) packet_a.checksum+=packet_a.payload[i]; my_packet[my_packet_no++]=packet_a; tolayer3(0,packet_a); A_transport++; if(base==nextseqnum) { //printf("\nCalling startimer"); starttimer(0,TIMEOUT); timer_A_started=1; } nextseqnum++; } } }