Browse Source

Init commit in new repo

Joachim M. Giæver 7 years ago
parent
commit
a8db4ddf1f
6 changed files with 697 additions and 2 deletions
  1. 16 0
      Makefile
  2. 10 2
      README.md
  3. 484 0
      prog2.c
  4. 91 0
      prog2.h
  5. 48 0
      rtp_abp.c
  6. 48 0
      rtp_gbn.c

+ 16 - 0
Makefile

@@ -0,0 +1,16 @@
+RTPABP_SRC=rtp_abp.c prog2.c
+RTPGBN_SRC=rtp_gbn.c prog2.c
+HEADERS=prog2.h
+
+all: abp gbn
+
+main: abp
+
+abp: $(RTPABP_SRC) $(HEADERS) Makefile
+	gcc -o $@ $(RTPABP_SRC) -Wall -I -g -lm -DBIDIRECTIONAL=0
+
+gbn: $(RTPGBN_SRC) $(HEADERS) Makefile
+	gcc -o $@ $(RTPGBN_SRC) -Wall -g -lm -DBIDIRECTIONAL=1
+
+clean:
+	rm -f *~ *.o *.exe *.stackdump abp gbn

+ 10 - 2
README.md

@@ -1,3 +1,11 @@
-# RTP
 
-Reliable Transport Protocol cleared up code for Pearson student resources for the Kurose/Ross book.
+RTP: Reliable Transport Protocol
+=========
+
+The programming assignment of interest is “Implementing a Reliable Transport Protocol” (programming assignment 5) from Pearson student resources for the Kurose/Ross book.
+
+## About
+This is a makeable project of the file, where the the student only need to implement rtp_abp.c (part a) and/or rtp_gbn.c (part b/extra credit).
+
+## What?
+This is just a cleared up code, to make life easier.

+ 484 - 0
prog2.c

@@ -0,0 +1,484 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "prog2.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).
+**********************************************************************/
+
+/*****************************************************************
+***************** NETWORK EMULATION CODE STARTS BELOW ***********
+The code below emulates the layer 3 and below network environment:
+- emulates the tranmission and delivery (possibly with bit-level corruption
+and packet loss) of packets across the layer 3/4 interface
+- handles the starting/stopping of a timer, and generates timer
+interrupts (resulting in calling students timer handler).
+- generates message to be sent (passed from later 5 to 4)
+
+THERE IS NOT REASON THAT ANY STUDENT SHOULD HAVE TO READ OR UNDERSTAND
+THE CODE BELOW.  YOU SHOLD NOT TOUCH, OR REFERENCE (in your code) ANY
+OF THE DATA STRUCTURES BELOW.  If you're interested in how I designed
+the emulator, you're welcome to look at the code - but again, you should have
+to, and you defeinitely should not have to modify
+******************************************************************/
+
+event_t *evlist = NULL;   /* the event list */
+
+int TRACE = 1;             /* for my debugging */
+int nsim = 0;              /* number of messages from 5 to 4 so far */ 
+int nsimmax = 0;           /* number of msgs to generate, then stop */
+float time = 0.000;
+float lossprob;            /* probability that a packet is dropped  */
+float corruptprob;         /* probability that one bit is packet is flipped */
+float lambda;              /* arrival rate of messages from layer 5 */   
+int ntolayer3;             /* number sent into layer 3 */
+int nlost;                 /* number lost in media */
+int ncorrupt;              /* number corrupted by media*/
+
+int main() {
+    
+    event_t *eventptr;
+    msg_t  msg2give;
+    pkt_t  pkt2give;
+
+    int i,j;
+
+    init();
+
+    A_init();
+    B_init();
+
+    while (1) {
+
+        /* get next event to simulate */
+        eventptr = evlist;
+        
+        if ( eventptr == NULL )
+            goto terminate;
+        
+        /* remove this event from event list */
+        evlist = evlist->next;
+        
+        if (evlist != NULL)
+            evlist->prev=NULL;
+
+        if ( TRACE >= 2 ) {
+            printf("\nEVENT time: %f,",eventptr->evtime);
+            printf("  type: %d",eventptr->evtype);
+            
+            if ( eventptr->evtype == 0 )
+                printf(", timerinterrupt  ");
+            else if ( eventptr->evtype == 1 )
+                printf(", fromlayer5 ");
+            else
+                printf(", fromlayer3 ");
+        
+            printf(" entity: %d\n",eventptr->eventity);
+        }
+
+        /* update time to next event time */
+        time = eventptr->evtime;
+        
+        if ( nsim == nsimmax )
+            break; /* all done with simulation */
+        
+        if ( eventptr->evtype == FROM_LAYER5 ) {
+            
+            /* set up future arrival */
+            generate_next_arrival();
+            
+            /* fill in msg to give with string of same letter */    
+            j = nsim % 26; 
+            
+            for ( i = 0; i < 20; i++ )  
+                msg2give.data[i] = 97 + j;
+            
+            if ( TRACE > 2 ) {
+                
+                printf("          MAINLOOP: data given to student: ");
+                
+                for ( i = 0; i < 20; i++ ) 
+                    printf("%c", msg2give.data[i]);
+                
+                printf("\n");
+            }
+            
+            nsim++;
+    
+            if ( eventptr->eventity == A ) 
+                A_output(msg2give);  
+            else
+                B_output(msg2give);  
+
+        } else if ( eventptr->evtype ==  FROM_LAYER3 ) {
+            
+            pkt2give.seqnum = eventptr->pktptr->seqnum;
+            pkt2give.acknum = eventptr->pktptr->acknum;
+            pkt2give.checksum = eventptr->pktptr->checksum;
+    
+            for (i=0; i<20; i++)  
+                pkt2give.payload[i] = eventptr->pktptr->payload[i];
+    
+            if ( eventptr->eventity == A )      /* deliver packet by calling */
+                A_input(pkt2give);            /* appropriate entity */
+            else
+                B_input(pkt2give);
+            
+            free( eventptr->pktptr );          /* free the memory for packet */
+    
+        } else if ( eventptr->evtype ==  TIMER_INTERRUPT ) {
+            
+            if ( eventptr->eventity == A ) 
+                A_timerinterrupt();
+            else
+                B_timerinterrupt();
+        
+        } else
+            printf("INTERNAL PANIC: unknown event type \n");
+
+        free(eventptr);
+
+    }
+
+    terminate:
+        printf(" Simulator terminated at time %f\n after sending %d msgs from layer5\n",time,nsim);
+        return EXIT_SUCCESS;
+}
+
+
+/* initialize the simulator */
+void init() {
+    
+    int i;
+    float sum, avg;
+    float jimsrand();
+
+    printf("-----  Stop and Wait Network Simulator Version 1.1 -------- \n\n");
+    printf("Enter the number of messages to simulate: ");
+    scanf("%d",&nsimmax);
+    printf("Enter  packet loss probability [enter 0.0 for no loss]:");
+    scanf("%f",&lossprob);
+    printf("Enter packet corruption probability [0.0 for no corruption]:");
+    scanf("%f",&corruptprob);
+    printf("Enter average time between messages from sender's layer5 [ > 0.0]:");
+    scanf("%f",&lambda);
+    printf("Enter TRACE:");
+    scanf("%d",&TRACE);
+
+    /* init random number generator */
+    srand(9999);
+    /* test random number generator for students */
+    sum = 0.0;
+    
+    /* jimsrand() should be uniform in [0,1] */
+    for ( i = 0; i < 1000; i++ )
+        sum = sum + jimsrand();
+    
+    avg = sum / 1000.0;
+    
+    if ( avg < 0.25 || avg > 0.75 ) {
+        printf("It is likely that random number generation on your machine\n" ); 
+        printf("is different from what this emulator expects.  Please take\n");
+        printf("a look at the routine jimsrand() in the emulator code. Sorry. \n");
+        exit(1);
+    }
+
+    ntolayer3 = 0;
+    nlost = 0;
+    ncorrupt = 0;
+
+    /* initialize time to 0.0 */
+    time=0.0;
+
+    /* initialize event list */
+    generate_next_arrival();
+
+}
+
+/****************************************************************************/
+/* jimsrand(): return a float in range [0,1].  The routine below is used to */
+/* isolate all random number generation in one location.  We assume that the*/
+/* system-supplied rand() function return an int in therange [0,mmm]        */
+/****************************************************************************/
+float jimsrand() {
+
+    /* largest int  - MACHINE DEPENDENT!!!!!!!!   */
+    double mmm = 2147483647;
+
+    /* individual students may need to change mmm */ 
+    float x;
+
+    /* x should be uniform in [0,1] */
+    x = rand() / mmm;
+    
+    return(x);
+
+}  
+
+/********************* EVENT HANDLINE ROUTINES *******/
+/*  The next set of routines handle the event list   */
+/*****************************************************/
+
+void generate_next_arrival()
+{
+    double x, log(), ceil();
+    event_t *evptr;
+
+    if ( TRACE > 2 )
+        printf("          GENERATE NEXT ARRIVAL: creating new arrival\n");
+
+    /* x is uniform on [0,2*lambda] */
+    x = lambda * jimsrand()*2;
+    /* having mean of lambda        */
+
+    evptr = (event_t *)malloc(sizeof(event_t));
+
+    evptr->evtime =  time + x;
+    evptr->evtype =  FROM_LAYER5;
+    
+    if (BIDIRECTIONAL && (jimsrand()>0.5) )
+        evptr->eventity = B;
+    else
+        evptr->eventity = A;
+
+    insertevent(evptr);
+
+} 
+
+void insertevent( event_t *p ) {
+    event_t *q,*qold;
+
+    if ( TRACE > 2 ) {
+        printf("            INSERTEVENT: time is %f\n",time);
+        printf("            INSERTEVENT: future time will be %f\n",p->evtime); 
+    }
+
+    /* q points to header of list in which p struct inserted */
+    q = evlist;  
+    
+    if ( q == NULL ) {
+
+        /* list is empty */
+        evlist=p;
+        p->next=NULL;
+        p->prev=NULL;
+
+    } else {
+    
+        for ( qold = q; q != NULL && p->evtime > q->evtime; q = q->next )
+            qold=q; 
+        
+        if ( q == NULL ) {
+
+            /* end of list */
+            qold->next = p;
+            p->prev = qold;
+            p->next = NULL;
+
+        } else if ( q == evlist ) {
+
+            /* front of list */
+            p->next=evlist;
+            p->prev=NULL;
+            p->next->prev=p;
+            evlist = p;
+
+        } else {
+
+            /* middle of list */
+            p->next=q;
+            p->prev=q->prev;
+            q->prev->next=p;
+            q->prev=p;
+
+        }
+    }
+}
+
+void printevlist()
+{
+    event_t *q;
+    
+    printf("--------------\nEvent List Follows:\n");
+    
+    for(q = evlist; q!=NULL; q=q->next)
+        printf("Event time: %f, type: %d entity: %d\n",q->evtime,q->evtype,q->eventity);
+    
+    printf("--------------\n");
+
+}
+
+
+
+/********************** Student-callable ROUTINES ***********************/
+
+/* called by students routine to cancel a previously-started timer */
+void stoptimer(int AorB) {
+    
+    event_t *q;
+
+    if ( TRACE > 2 )
+        printf("          STOP TIMER: stopping timer at %f\n",time);
+    
+    /* for (q=evlist; q!=NULL && q->next!=NULL; q = q->next)  */
+    for ( q = evlist; q != NULL; q = q->next ) 
+        if ( ( q->evtype == TIMER_INTERRUPT && q->eventity == AorB ) ) { 
+            
+            /* remove this event */
+            if (q->next==NULL && q->prev==NULL) {
+                /* remove first and only event on list */
+                evlist = NULL;
+            } else if ( q->next == NULL ) {
+                /* end of list - there is one in front */
+                q->prev->next = NULL;
+            } else if ( q== evlist ) {
+                /* front of list - there must be event after */   
+                q->next->prev = NULL;
+                evlist = q->next;
+            } else {
+                /* middle of list */
+                q->next->prev = q->prev;
+                q->prev->next = q->next;
+            }
+
+            free(q);
+            return;
+        }
+
+    printf("Warning: unable to cancel your timer. It wasn't running.\n");
+}
+
+
+void starttimer( int AorB, float increment ) {
+
+    event_t *q;
+    event_t *evptr;
+
+    if ( TRACE > 2 )
+        printf("          START TIMER: starting timer at %f\n",time);
+    
+    /* be nice: check to see if timer is already started, if so, then  warn */
+    /* for (q=evlist; q!=NULL && q->next!=NULL; q = q->next)  */
+    
+    for ( q = evlist; q != NULL; q = q->next )
+        if ( ( q->evtype == TIMER_INTERRUPT && q->eventity == AorB ) ) { 
+            printf("Warning: attempt to start a timer that is already started\n");
+            return;
+        }
+
+    /* create future event for when timer goes off */
+    evptr = (event_t *) malloc( sizeof( event_t ) );
+    evptr->evtime =  time + increment;
+    evptr->evtype =  TIMER_INTERRUPT;
+    evptr->eventity = AorB;
+    
+    insertevent(evptr);
+
+} 
+
+
+/************************** TOLAYER3 ***************/
+/* A or B is trying to stop timer*/
+void tolayer3( int AorB, pkt_t packet ) {
+    pkt_t *mypktptr;
+    event_t *evptr,*q;
+    float lastime, x, jimsrand();
+    int i;
+
+    ntolayer3++;
+
+    /* simulate losses: */
+    if (jimsrand() < lossprob)  {
+        nlost++;
+
+        if ( TRACE > 0 )    
+            printf("          TOLAYER3: packet being lost\n");
+        
+        return;
+    }  
+
+    /* make a copy of the packet student just gave me since he/she may decide */
+    /* to do something with the packet after we return back to him/her */ 
+    mypktptr = (pkt_t *)malloc(sizeof(pkt_t));
+    mypktptr->seqnum = packet.seqnum;
+    mypktptr->acknum = packet.acknum;
+    mypktptr->checksum = packet.checksum;
+    
+    for ( i = 0; i < 20; i++ )
+        mypktptr->payload[i] = packet.payload[i];
+    
+    if ( TRACE > 2 )  {
+        printf("          TOLAYER3: seq: %d, ack %d, check: %d ", mypktptr->seqnum,
+        
+        mypktptr->acknum,  mypktptr->checksum);
+        
+        for ( i = 0; i < 20; i++ )
+            printf( "%c", mypktptr->payload[i] );
+
+        printf("\n");
+    }
+
+    /* create future event for arrival of packet at the other side */
+    evptr = (event_t *)malloc(sizeof(event_t));
+    evptr->evtype =  FROM_LAYER3;   /* packet will pop out from layer3 */
+    evptr->eventity = (AorB+1) % 2; /* event occurs at other entity */
+    evptr->pktptr = mypktptr;       /* save ptr to my copy of packet */
+    
+    /* finally, compute the arrival time of packet at the other end.
+    medium can not reorder, so make sure packet arrives between 1 and 10
+    time units after the latest arrival time of packets
+    currently in the medium on their way to the destination */
+    lastime = time;
+    
+    /* for (q=evlist; q!=NULL && q->next!=NULL; q = q->next) */
+    for ( q = evlist; q != NULL; q = q->next ) 
+        if ( ( q->evtype == FROM_LAYER3 && q->eventity == evptr->eventity ) ) 
+            lastime = q->evtime;
+    
+    evptr->evtime = lastime + 1 + 9*jimsrand();
+
+    /* simulate corruption: */
+    if (jimsrand() < corruptprob) {
+
+        ncorrupt++;
+
+        if ( (x = jimsrand()) < .75) /* corrupt payload */
+            mypktptr->payload[0]='Z';
+        else if (x < .875)
+            mypktptr->seqnum = 999999;
+        else
+            mypktptr->acknum = 999999;
+        
+        if ( TRACE > 0 )    
+            printf("          TOLAYER3: packet being corrupted\n");
+    }  
+
+    if ( TRACE > 2 )  
+        printf("          TOLAYER3: scheduling arrival on other side\n");
+    
+    insertevent(evptr);
+} 
+
+void tolayer5(int AorB, char datasent[20]) {
+    int i;  
+    
+    if (TRACE>2) {
+        printf("          TOLAYER5: data received: ");
+    
+        for ( i = 0; i < 20; i++ )  
+            printf("%c",datasent[i]);
+
+        printf("\n");
+    }
+
+}

+ 91 - 0
prog2.h

@@ -0,0 +1,91 @@
+
+#ifndef PROG2_H
+#define PROG2_H
+
+/* change to 1 if you're doing extra credit */
+/* and write a routine called B_output */
+//#define BIDIRECTIONAL 1
+
+typedef struct msg msg_t;
+typedef struct pkt pkt_t;
+typedef struct event event_t;
+
+/* 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 */
+    pkt_t *pktptr;          /* ptr to packet (if any) assoc w/ this event */
+    event_t *prev;
+    event_t *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
+
+void insertevent(struct event *p);
+void init();
+void generate_next_arrival();
+
+/********* STUDENTS WRITE THE NEXT SEVEN ROUTINES *********/
+
+/* 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();
+
+/* called from layer 3, when a packet arrives for layer 4 */
+void A_input( pkt_t packet );
+
+/* called from layer 5, passed the data to be sent to other side */
+void A_output( msg_t message );
+
+/* called when A's timer goes off */
+void A_timerinterrupt();
+
+/* 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();
+
+/* called from layer 3, when a packet arrives for layer 4 at B*/
+void B_input( pkt_t packet );
+
+/* Note that with simplex transfer from a-to-B, there is no B_output() */
+void B_output( msg_t message ); /* need be completed only for extra credit */
+
+/* called when B's timer goes off */
+void B_timerinterrupt();
+
+/** 
+ * STUDENT CALLABLE FUNCTIONS: Dont implement (they allready are, int prog2.c)
+ **/
+void starttimer( int AorB, float increment );
+/* called by students routine to cancel a previously-started timer */
+void stoptimer(int AorB);
+/* TOLAYER3 */
+void tolayer3( int AorB, pkt_t packet );
+/* TOLAYER5 */
+void tolayer5(int AorB, char datasent[20]);
+#endif

+ 48 - 0
rtp_abp.c

@@ -0,0 +1,48 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include "prog2.h"
+
+extern int nsimmax;
+extern float lambda;
+
+/* 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() {
+	
+}
+
+/* called from layer 3, when a packet arrives for layer 4 */
+void A_input( pkt_t packet ) {
+
+}
+
+/* called from layer 5, passed the data to be sent to other side */
+void A_output( msg_t message ) {
+
+}
+
+/* called when A's timer goes off */
+void A_timerinterrupt() {
+
+}
+
+/* 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() {
+
+}
+
+/* called from layer 3, when a packet arrives for layer 4 at B*/
+void B_input( pkt_t packet ) {
+
+}
+
+/* Note that with simplex transfer from a-to-B, there is no B_output() */
+void B_output( msg_t message ) {
+	/* need be completed only for extra credit */
+}
+
+/* called when B's timer goes off */
+void B_timerinterrupt() {
+
+}

+ 48 - 0
rtp_gbn.c

@@ -0,0 +1,48 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include "prog2.h"
+
+extern int nsimmax;
+extern float lambda;
+
+/* 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() {
+
+}
+
+/* called from layer 3, when a packet arrives for layer 4 */
+void A_input( pkt_t packet ) {
+
+}
+
+/* called from layer 5, passed the data to be sent to other side */
+void A_output( msg_t message ) {
+
+}
+
+/* called when A's timer goes off */
+void A_timerinterrupt() {
+
+}
+
+/* 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() {
+
+}
+
+/* called from layer 3, when a packet arrives for layer 4 at B*/
+void B_input( pkt_t packet ) {
+
+}
+
+/* Note that with simplex transfer from a-to-B, there is no B_output() */
+void B_output( msg_t message ) {
+	/* need be completed only for extra credit */
+}
+
+/* called when B's timer goes off */
+void B_timerinterrupt() {
+
+}