Friday, March 23, 2012

Comparison of Infininand vs Gigabit Ethernet (GigE)

The great debate between Infiniband vs GigE has been ongoing and accelerated by arrival of 10GigE.These are some studies that compare the two protocols. While one is sockets based and the other is qpairs based, these high performance computation-heavy benchmarks stress test for latency, and bandwidth analysis. The results are surprisingly indicative of the type of workload that is running using each interconnect technology.

http://www.deskeng.com/articles/aaammw.htm

Fluent Benchmark Configuration for Infiniband and GigE

LS-DYNA Benchmark comparison published for the LS-DYNA Conference
http://www.dynalook.com/international-conf-2008/

"Optimizing LS-DYNA® Productivity in Cluster Environments"
http://www.dynalook.com/international-conf-2008/ComputingTechnology-3.pdf

Client Code to Create ATM SVC

This is client code that creates Switched Virtual Connection with AAL5 UBR sockets using ATM on Linux distribution from sourceforge.net



#define MAX_SDU     20000
#define MAX_OFFSET  8

void usage(char *name)
{
  fprintf(stderr,"usage: %s [vpi] [vci]\n",name);
  exit(1);
}

int main(int argc, char *argv[])
{
  struct sockaddr_atmsvc to_addr;
  struct atm_blli        blli;
  struct atm_qos         qos, to_qos;
  struct atm_sap         to_sap;
  fd_set                 rd, wd, ed;
  int                    to_fd;
  char                   command[20] = "";
  int                    compare = 1;
  int                    num;

  char   *quit = "q";
  char   *dest = "47.0005.80.ffe100.0000f21a26d8.0020ea000ee0.00";

  /*char   *dest = "nestor-atm";
  */
 
  printf("client: creating new socket...\n");
  if ((to_fd = socket(PF_ATMSVC, SOCK_DGRAM, ATM_AAL5)) < 0)
  {
    perror("client:socket create error\n");
    return 1;
  }
  printf("socket id:");
  printf("%d",to_fd);
  printf("\n");

  printf("client: setting qos...\n");
  memset(&qos,0,sizeof(qos));
  qos.aal = ATM_AAL5;
  qos.txtp.traffic_class = qos.rxtp.traffic_class = ATM_UBR;
  qos.txtp.max_sdu = qos.rxtp.max_sdu = MAX_SDU;

  if (setsockopt(to_fd,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0)
  {
        perror("client: setsockopt SO_ATMQOS\n");
        return 1;
  }

  printf("client: setting sap parameters...\n");
  memset(&to_sap,0, sizeof(to_sap));
  if (setsockopt(to_fd, SOL_ATM, SO_ATMSAP,&to_sap, sizeof(to_sap)) <0)
  {
    perror("client: sap paremeter set failed\n");
    close(to_fd);
    return 1;
  }
 

  memset(&to_addr,0, sizeof(to_addr));
  to_addr.sas_family = AF_ATMSVC;
  text2atm(dest, (struct sockaddr *)&to_addr, sizeof(to_addr), T2A_SVC | T2A_LOCAL);

   printf("client: calling connect...\n");
    if (connect(to_fd,(struct sockaddr *) &to_addr,sizeof(to_addr)) < 0)
    {
        perror("client: bind failed\n");
        close(to_fd);
        return 1;
    }
 
    srandom(0); /* we want it to be deterministic */


    FD_ZERO(&rd);
    FD_ZERO(&wd);
    FD_ZERO(&ed);
    FD_SET(to_fd, &wd);
   
    printf("\n");
    printf("Enter message, q to quit: ");
    gets(command);
    compare = strcmp(command, quit);

    while (compare!=0)
    {
      printf("\n");
      printf("client sending message...\n");
     
      num = write(to_fd,command,sizeof(command));
      if (num < 0)
      {
        perror("client: write failed\n");
        close(to_fd);
        return 0;
      }

      printf("\n");
      memset(command,0,sizeof(command));
      printf("Enter message, q to quit: ");
      gets(command);
      compare= strcmp(command, quit);
    }
    printf("Shutting down...!\n");
    shutdown(to_fd, 2);
    printf("Goodbye!\n");
    close(to_fd);
  return 0;
}

Server Code to Create ATM SVC

This code creates ATM Switched Virtual Connection with AAL5 UBR socket using ATM on Linux distribution from sourceforge.net




#define MAX_SDU     20000
#define MAX_OFFSET  8

void usage(char *name)
{
  fprintf(stderr,"usage: %s [vpi] [vci]\n",name);
  exit(1);
}

int main(int argc, char *argv[])
{
  struct sockaddr_atmsvc frm_addr, lsn_addr;
  struct atm_blli        blli;
  struct atm_qos         qos, fm_qos;
  struct atm_sap         lstn_sap;
  socklen_t              fm_len, lsn_len;
  fd_set                 rd, wd, ed;
  int                    lsn_fd, fm_fd;
  int                    pid, lst;
  static unsigned char   buffer[20];
  int                    num;

  /*char   *lstn = "47.0005.80.ffe100.0000.f21a.26d8.0020ea000ee0.00";
  */
  char *lstn = "nestor-atm";
 
  printf("server: creating listen socket...\n");
  if ((lsn_fd = socket(PF_ATMSVC, SOCK_DGRAM, ATM_AAL5)) < 0)
  {
    perror("makeConn:socket error\n");
    return 1;
  }
  printf("socket id:");
  printf("%d",lsn_fd);
  printf("\n");

  printf("server: setting listen qos...\n");
  memset(&qos,0,sizeof(qos));
  qos.aal = ATM_AAL5;
  qos.txtp.traffic_class = qos.rxtp.traffic_class = ATM_UBR;
  qos.txtp.max_sdu = qos.rxtp.max_sdu = MAX_SDU;

  if (setsockopt(lsn_fd,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0)
  {
        perror("server: setsockopt SO_ATMQOS\n");
        return 1;
  }

  printf("server: setting listen sap...\n");
  memset(&lstn_sap,0, sizeof(lstn_sap));
  if (setsockopt(lsn_fd, SOL_ATM, SO_ATMSAP,&lstn_sap, sizeof(lstn_sap)) <0)
  {
    perror("server: sap paremeter set failed\n");
    close(lsn_fd);
    return 1;
  }

  memset(&lsn_addr,0, sizeof(lsn_addr));
  lsn_addr.sas_family = AF_ATMSVC;
  text2atm(lstn, (struct sockaddr *)&lsn_addr, sizeof(lsn_addr), T2A_SVC | T2A_LOCAL);

   printf("server: binding listen socket...\n");
    if (bind(lsn_fd,(struct sockaddr *) &lsn_addr,sizeof(lsn_addr)) < 0)
    {
        perror("server: bind failed\n");
        return 1;
    }
 
   fm_len = sizeof(frm_addr);
   memset(&frm_addr,0,fm_len);

    printf("server: listening...\n");
    if (listen(lsn_fd, 3) < 0)
    {
       perror("server: listen failed\n");
       close(lsn_fd);
       return 1;
    }
    srandom(0); /* we want it to be deterministic */
 
  while(1)
  {

    FD_ZERO(&rd);
    FD_ZERO(&wd);
    FD_ZERO(&ed);
    FD_SET(lsn_fd, &rd);
    select(lsn_fd+1, &rd, &wd, &ed, NULL);
   
    printf("server: accepting on new socket...\n");
    fm_fd = accept(lsn_fd, (struct sockaddr *)&frm_addr,&fm_len);
    if (fm_fd < 0)
    {
      perror("server: did not accept\n");
      close(fm_fd);
      close(lsn_fd);
      exit(1);
    }

    while(1)
    {
      FD_SET(fm_fd, &rd);
      select(fm_fd+1, &rd, &wd, &ed, NULL);
      memset(buffer,0,sizeof(buffer));
      printf("server: waiting...\n");
      lst = read(fm_fd,buffer,sizeof(buffer));
      if (lst < 0)
      {
        perror("server: listen error\n");
        close(lsn_fd);
        close(fm_fd);
        exit(0);
      }
      if (lst > 0)
      {
        printf("server: received bytes %d\n", lst);
        printf("server: message = %s\n", buffer);
      }
      if (lst == 0)
      {
       printf("server: closing connection...\n");
       close(lsn_fd);
       close(fm_fd);
       exit(0);
      }
    }
  }
  return 0;
}

Client Code to Create ATM PVC Connection and Data Transfer

 An ATM client here opens a connection for PVC over VPI/VCI = 0/64 defining qos using AAL5 UBR Traffic descriptors using ATM on Linux distribution from sourceforge.net




#define MAX_SDU     20000
#define MAX_OFFSET  8

void usage(char *name)
{
  fprintf(stderr,"usage: %s [vpi] [vci]\n",name);
  exit(1);
}

int main(int argc, char *argv[])
{
  struct sockaddr_atmpvc addr;
  struct atm_qos         qos;
  int    fd;
  int    pid, lst;
  static unsigned char buffer[20];
  int    num;
  char * test = "Sending test";
  char *quit = "q";
  char command[30]="";
  int  compare = 1;
 
  /*if (argc != 3) {usage(argv[0]);}
  */
  printf("Creating a pvc with vpi/vci 0/64... \n");

  if ((fd = socket(PF_ATMPVC, SOCK_DGRAM, 0)) < 0)
  {
    perror("socket error");
    return 1;
  }
  printf("created socket with id: ");
  printf("%d",fd);
  printf("\n");

  memset(&addr,0,sizeof(addr));
  addr.sap_family = AF_ATMPVC;
  addr.sap_addr.itf = 0;
  addr.sap_addr.vpi = 0;
  addr.sap_addr.vci = 64;

  memset(&qos,0,sizeof(qos));
  qos.aal = ATM_AAL5;
  qos.txtp.traffic_class = qos.rxtp.traffic_class = ATM_UBR;
  qos.txtp.max_sdu = qos.rxtp.max_sdu = MAX_SDU;
  if (setsockopt(fd,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0)
  {
        perror("setsockopt SO_ATMQOS");
        return 1;
  }
  printf("Set socket options to AAL5, UBR traffic...\n");
  if (bind(fd,(struct sockaddr *) &addr, sizeof(addr)) < 0)
  {
       perror("bind error");
       return 1;
  }
  srandom(0); /* we want it to be deterministic */

    printf("Enter message, q to quit: ");
    gets(command);
  
    compare = strcmp(command, quit);

    while (compare != 0)
    {
      printf("\n");
      printf("client sending message... \n");
      num = write(fd,command, strlen(command));
      printf("client: Bytes sent= %d\n",num);
      if (num<0)
      {
       printf("error no ");
       printf(" %s", strerror(errno));
       return 0;
      }
  
    printf("\n");
    printf("Enter message, q to quit: ");
    gets(command);
    compare = strcmp(command, quit);

    }
   
  return 0;
}

Server Code to Create ATM PVC

This code opens connection on ATM socket defined for PVC on VPI/VCI = 0/64. QOS is defined over AAL5 UBR Traffic using ATM on Linux distribution from sourceforge.net



#define MAX_SDU     20000
#define MAX_OFFSET  8

void usage(char *name)
{
  fprintf(stderr,"usage: %s [vpi] [vci]\n",name);
  exit(1);
}

int main(int argc, char *argv[])
{
  struct sockaddr_atmpvc addr;
  struct atm_qos         qos;
  int    fd;
  int    pid, lst;
  static unsigned char buffer[30];
  int    num;
  char * test = "Sending test";
 
  /*if (argc != 3) {usage(argv[0]);}
  */
  printf("Creating a pvc with vpi/vci 0/64... \n");

  if ((fd = socket(PF_ATMPVC, SOCK_DGRAM, 0)) < 0)
  {
    perror("socket error");
    return 1;
  }
  printf("created socket with id: ");
  printf("%d",fd);
  printf("\n");

  memset(&addr,0,sizeof(addr));
  addr.sap_family = AF_ATMPVC;
  addr.sap_addr.itf = 0;
  addr.sap_addr.vpi = 0;
  addr.sap_addr.vci = 64;

  memset(&qos,0,sizeof(qos));
  qos.aal = ATM_AAL5;
  qos.txtp.traffic_class = qos.rxtp.traffic_class = ATM_UBR;
  qos.txtp.max_sdu = qos.rxtp.max_sdu = MAX_SDU;
  if (setsockopt(fd,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0)
  {
        perror("setsockopt SO_ATMQOS");
        return 1;
  }
  printf("Set socket options to AAL5, UBR traffic...\n");
  if (bind(fd,(struct sockaddr *) &addr, sizeof(addr)) < 0)
  {
       perror("bind error");
       return 1;
  }
  srandom(0); /* we want it to be deterministic */

  printf("Server: listening on vc 0,64...\n");
  while (1)
  {
    memset(buffer,0, sizeof(buffer));
    lst = read(fd, buffer, sizeof(buffer));
    if (lst<0)
      perror("server: listen error\n");
    if (lst > 0)
    {
      printf("Server: received bytes %d\n", lst);
      printf("server: message received = %s\n", buffer);
    }
  }

  return 0;
}

My Implementation of Simple Reliable Transport Protocol (SRTP)

 This protocol runs above UDP and provides : reliability, retransmissions, acknowledgements, timeouts, and congestion control


#define NUM_DELIMETERS   10
#define MAX_SRTP_HEADER  22
#define MAX_SRTP_PAYLOAD 81
#define MAX_SRTP_PACKET  MAX_SRTP_PAYLOAD + MAX_SRTP_HEADER
#define MAX_NUM_PACKETS  2000
#define MAX_SRTP_STRING  MAX_SRTP_PACKET + NUM_DELIMETERS
  
#define CLOSED        0
#define LISTEN        1
#define SYN_SENT      2
#define SYN_RECVD     3
#define ESTABLISHED   4
#define FIN_WAIT1     5
#define FIN_WAIT2     6
#define CLOSE_WAIT    7
#define LAST_ACK      8
#define TIMER_EXP     9

/*Error Codes */
#define CHKSUM_FAILED  -2

/*Code for Control Field in UDP packet*/

#define ACK   "A"
#define RST   "R"
#define SYN   "S"
#define FIN   "F"
#define DAT   "D"
#define SYN_ACK "Z"
#define RXM   "R"
#define ERR   "E"
#define FIN_ACK "X"
#define DATL  "L"   /* indentifies last segment */
#define PUT   "put"

int conflag;
/*typedef definitions*/
typedef unsigned long  uint32;
typedef unsigned short uint16;
typedef unsigned char  uint8;

typedef struct
{      
       uint16  src_port_num;
       uint16  dest_port_num;
       uint32  seq_num;
       uint32  ack_num;     
       uint16  window_size;
       u_short  cksum;
       char    *contrl_field;
       uint32  reserved;
       char    data[MAX_SRTP_PAYLOAD];
      
}srtp_header;

typedef struct
{
     srtp_header   pkt;
     bool          received;
     bool          ack_sent;
}incoming_buff;

incoming_buff server_buff[2000];

typedef struct

      srtp_header     pkt;
      int             num_rxmt;
      bool            ack_recd;
      bool            sent_pkt;
      bool            timed_out;
      bool            no_pkt;
      int             pID;
     
}timer;

timer t1[MAX_NUM_PACKETS];

typedef struct
{
       int                start_index;
       int                current_index;
       int                window_size;          
}sWindow;
 
sWindow window; 
   
typedef struct
{
       int                connection_number;
       int                portNumber;
       int                socketDesc;
       int                currentState;
       struct sockaddr_in host_addr;
      
}connection;

connection connS, connC; 

//---------------------------------------------------------------------

void sendPackets(int , int);
srtp_header initialize(void);


void initWindow(int size)

   extern sWindow window;

   window.start_index = 0;
   window.current_index = size-1;
   window.window_size = size;
   //printf("INITIALIZED WINDOW!\n");
return;
}

void initTimer()
{
  extern timer t1[MAX_NUM_PACKETS];
 
  for (int i=0;i
  {  srtp_header srt;
     srt = initialize();
     t1[i].pkt = srt;
     t1[i].ack_recd = 0;
     t1[i].timed_out = 0;
     t1[i].pID = 0;
     t1[i].no_pkt=1;
  }

}

void initializeBuff()
{  extern incoming_buff server_buff[2000];

  for(int i=0;i<2000;i++)
  {  srtp_header srp;
     srp = initialize();
 
     server_buff[i].received=0;
     server_buff[i].pkt = srp;
     server_buff[i].ack_sent=0;
  }
  return; 
}



void insertTimer(srtp_header hdr, int sent)
{
   extern timer t1[MAX_NUM_PACKETS];
   extern sWindow window;
   extern connection connC;

   if (sent
   {
     t1[sent].pkt = hdr;
     printf("INSERTED PACKET! %d %s \n",sent, hdr.contrl_field);
     t1[sent].num_rxmt = 0;
     t1[sent].ack_recd = 0;
     t1[sent].sent_pkt = 0;
     t1[sent].timed_out = 1;
     t1[sent].no_pkt=0;
     t1[sent].pID = 0;
   }
   return;
}

//---------------------------------------------------------------------
u_short checksum(srtp_header srtp)
{
    int sum, i = 0;
    u_short answer;
   
    sum = 0;
    i = 0;
    sum  = sum + srtp.src_port_num;
    //printf("SUM1 = %d\n\n", sum);
    sum  = sum + srtp.dest_port_num;
    //printf("SUM2 = %d\n\n", sum);
    sum  = sum + srtp.seq_num;
    //printf("SUM3 = %d\n\n", sum);
    sum  = sum + srtp.ack_num;
    //printf("SUM4 = %d\n\n", sum);
    sum  = sum + srtp.window_size;
    //printf("SUM5 = %d\n\n", sum);
    sum  = sum + atoi(srtp.contrl_field);
    //printf("SUM6 = %d\n\n", sum);
    sum  = sum + srtp.reserved;
    //printf("SUM7 = %d\n\n", sum);
   
    for(i=0; i
    {
        sum  = sum + (srtp.data[i]);
        //cout<<"SUM "<<<" = "<<<" : "<<<
    }
   
    //printf("SUM8 = %d\n\n", sum);
   
   
    answer = ~sum;  /*takes the ones complement */
    //printf("ANSWER = %d\n\n", answer);
    return answer;
   
}

  /* reverse string s in place*/
  void reverse (char s[])
  {
      int c, i, j;

      for (i=0, j = strlen(s)-1; i
          c = s[i];
          s[i] = s[j];
          s[j] = c;
      }
  }  /* end of reverse*/


  /* converts n to characters in s */
  void itoa(int n, char s[])
  {
      int i, sign;

      if ((sign = n) < 0) {
          n = -n;
      }
      i=0;
      do {
          s[i++] = n % 10 + '0';
      } while ((n /= 10) > 0  );
      if (sign < 0) {
          s[i++] = '-';
      }
      s[i] = '\0';
      reverse(s);
  }   /* end of itoa */

  /* create packet  and place into circular buffer*/
char* getPacket(srtp_header srtp)
  {
     /*declarations*/
    char tmp_str[MAX_SRTP_PACKET + 10]; /*0416*/

    int i,j, k;
   
    static char *out;
    out = (char *)calloc(532, sizeof(char));
    const char *delimiter = "&";
    const char *delnull = "\0"; /*0416*/

    memset(tmp_str, NULL, sizeof(tmp_str) );
   
  
  
    printf("reading the input ...\n\n");

    /**************create header string**********************/
    strcat(out, delimiter);
    itoa(srtp.src_port_num, tmp_str);
    strcat(out, tmp_str);
    strcat(out, delimiter);

    itoa(srtp.dest_port_num, tmp_str);
    strcat(out, tmp_str);
    strcat(out, delimiter);
   
    itoa(srtp.seq_num, tmp_str);
    strcat(out, tmp_str);
    strcat(out, delimiter);

    itoa(srtp.ack_num, tmp_str);
    strcat(out, tmp_str);
    strcat(out, delimiter);

    itoa(srtp.window_size, tmp_str);
    strcat(out, tmp_str);
    strcat(out, delimiter);
   
    itoa(srtp.cksum, tmp_str);
    strcat(out, tmp_str);
    strcat(out, delimiter);
  
    strcat(out, srtp.contrl_field);
    strcat(out, delimiter);
   
    itoa(srtp.reserved, tmp_str);
    strcat(out, tmp_str);
    strcat(out, delimiter);

   
    strncpy(tmp_str, srtp.data, MAX_SRTP_PAYLOAD);
    strcat(out, tmp_str);
    strcat(out, delnull); /*0416*/
    //strcat(out, delimiter);
 
   

    printf("packet string  = %s\n\n", out);
   
    return out;
 
   

  } /* end of getPacket()*/


  /* parse packet into tokens */
srtp_header parser(char s[])
  {
    /*declarations */
    srtp_header srtp;
    const char *delimiter = "&";
    int i;
    char *data;
    data = (char *)calloc(MAX_SRTP_PAYLOAD, sizeof(char)); /*0416*/
    memset(data, NULL, MAX_SRTP_PAYLOAD); /*0416*/
    const char *delnull = "\0"; /*0416*/

   
   
   
    printf("You are inside Parser\n\n");

    /**************parse string********/
   
    srtp.src_port_num = (short)atoi(strtok(s, delimiter)); 
    srtp.dest_port_num = (short)atoi(strtok(NULL, delimiter));
    srtp.seq_num = (short)atoi(strtok(NULL, delimiter));
    srtp.ack_num = (short)atoi(strtok(NULL, delimiter));
    srtp.window_size = (short)atoi(strtok(NULL, delimiter));
    srtp.cksum = (u_short)atoi(strtok(NULL, delimiter));
    srtp.contrl_field = (strtok(NULL, delimiter) );
    srtp.reserved = (short)atoi(strtok(NULL, delimiter));
 
    //data = strtok(NULL, delimiter);
    data = strtok(NULL, delnull); /*0416*/

    
    if(data != NULL)
    {
      strncpy(srtp.data, data, MAX_SRTP_PAYLOAD); /*0416*/
    }
    

  

    /*printf("src_port_num = %d\n", srtp.src_port_num);
    printf("dest_port_num = %d\n", srtp.dest_port_num);
    printf("cksum_num = %d\n", srtp.cksum);
    printf("seq_num = %d\n", srtp.seq_num);
    printf("ack_num = %d\n", srtp.ack_num);
    printf("contrl_field = %s\n", srtp.contrl_field);*/
    if(data != NULL)
    {
      printf("data = %s\n", data);
    }
   
    printf("Leaving Parser\n\n");
   
    return srtp;

    /*************parse string**********/


  }  /* end of parser */
 
 
 
/* initializes srtp struct to its default values */
srtp_header initialize(void)
{
   
    srtp_header packet;
  
    packet.src_port_num = 0;
    packet.dest_port_num = 0;
    packet.seq_num = 0;
    packet.ack_num = 0;
    packet.cksum = 0;
    packet.contrl_field = "0";
    packet.window_size = 0; 
    packet.reserved = 0;
    memset(packet.data, 0, MAX_SRTP_PAYLOAD );
   
    //printf("You have initialized the packet\n\n");
   
    return packet;

} /* end of initialize */

int cTimer(int index,int amount)
{
   extern timer t1[MAX_NUM_PACKETS];
   int procId;
  
   procId = fork();
  
   switch(procId)
   {
     case 0:
        printf("Timer %d started!\n", index);
        //usleep(amount);/*0418*/
    sleep(amount);
    printf("Timer %d timer expired!\n", index);
   
    _exit(0);
    
     default:
       t1[index].pID = procId;
       //printf("TIMER PID = %d\n", procId);
       return procId;
   }
  
}


void sendPackets(int startIx, int numberOfPkts)
{  extern timer t1[MAX_NUM_PACKETS];
   extern int conflag;
   int r,i, slp, numTrmt;

   if ((startIx+numberOfPkts-1)>MAX_NUM_PACKETS)
        numTrmt = MAX_NUM_PACKETS;
   else numTrmt = startIx+numberOfPkts-1;

     
   //if ((t1[startIx].num_rxmt < 3)&&(t1[startIx].timed_out))
   //{  
  
      for (i=startIx;i<=(numTrmt);i++)
      {
        if((!t1[i].no_pkt)&&(t1[i].num_rxmt<3)&&(t1[i].timed_out))
        { t1[i].ack_recd = 0;
          t1[i].timed_out=0;  

      slp = cTimer(i,10);/*0418*/

          r = sendto(connC.socketDesc,getPacket(t1[i].pkt),MAX_SRTP_STRING,0,(struct sockaddr*)&connC.host_addr, sizeof(struct sockaddr));
     
          if (r==-1)
          {
           //printf("sendto fails\n");
       return;
          }
          else if (t1[i].sent_pkt)
          {
           t1[i].num_rxmt++;
       printf("REXMT PACKET %d FOR %d TIME!!\n", i, t1[i].num_rxmt);
          }
          else 
      {
       t1[i].num_rxmt = 0;
           t1[i].sent_pkt = 1;
           printf("=====PACKET %d SENT====\n", i);      
      }
     }
     else if((!t1[i].no_pkt)&&(t1[i].num_rxmt==3)&&(t1[i].timed_out))
     {
        printf("pkt %d experienced congestion\n",i);
            conflag = 1;
     }

      }  
   //}
   //else if (t1[startIx].num_rxmt==3)
   //{
   //   printf("**************CONGESTION EXPERIENCED*********\n");
     
   //}
return;  
}


//======================================BEGIN API FOR SRTP=============================================
int sendSynAckPkt()
  {
           int sendsynack;
           srtp_header synackPkt;
       extern connection connS;
       
       synackPkt = initialize();
           synackPkt.contrl_field = SYN_ACK;
           synackPkt.seq_num = rand();
      
           sendsynack = sendto(connS.socketDesc,getPacket(synackPkt),MAX_SRTP_PACKET,0,(struct sockaddr *)&connS.host_addr, sizeof(struct sockaddr));
      
           if (sendsynack == -1)
           {
              return -1;
           }
       else
       {
           return 1;
       }

      
  } /*end of sendSynAckPkt*/
 
 
int sendFinAckPkt()
  {
          int sendfinack;
          extern connection connS;
          srtp_header finackPkt;
      
          finackPkt = initialize();
          finackPkt.contrl_field = FIN_ACK;
          finackPkt.seq_num = rand();
         
          sendfinack = sendto(connS.socketDesc,getPacket(finackPkt),MAX_SRTP_PACKET,0,(struct sockaddr *)&connS.host_addr, sizeof(struct sockaddr));
      
              if (sendfinack == -1)
              {
                 return -1;
              }
              else
          {   
               return 1;
          }
          
    
  } /* end of sendFinAckPkt */
      
 
int s_sendAckPkt(int seq_num)
 {

          int sendAck;
      srtp_header ackPacket;
      extern connection connS;
      ackPacket = initialize();
      ackPacket.contrl_field = ACK;     
      ackPacket.ack_num = seq_num;
     
     
      sendAck = sendto(connS.socketDesc, getPacket(ackPacket), MAX_SRTP_PACKET,0,(struct sockaddr *)&connS.host_addr, sizeof(struct sockaddr));
     
      if (sendAck == -1)
      {
        return -1;
      }
      else
      {
         return 1;

      }
   
 } /* end of s_sendAckPkt */

int sendFinPkt()
 {
         int sendFin;
         extern connection connC;
         srtp_header finPacket;
             finPacket = initialize();
      
             finPacket.seq_num = rand();     
             finPacket.contrl_field = FIN;   
   
         sendFin = sendto(connC.socketDesc, getPacket(finPacket), MAX_SRTP_PACKET, 0, (struct sockaddr *)&connC.host_addr, sizeof(struct sockaddr));
        
         if (sendFin == -1)
             {
               return -1;
             }      
             else
             { 
             return 1;

         }
 } /*end of sendFinPkt */   
   
          
   
  
 int sendSynPkt()
 {

        int  sendSyn;
        extern connection connC;
        srtp_header synPacket;
        synPacket = initialize();
      
        synPacket.seq_num = rand();
        //printf("SYN SEQ NUM = %d\n\n", synPacket.seq_num );
        synPacket.contrl_field = SYN;
        sendSyn = sendto(connC.socketDesc, getPacket(synPacket), MAX_SRTP_PACKET, 0, (struct sockaddr *)&connC.host_addr, sizeof(struct sockaddr));
       
   
    if (sendSyn == -1)
        {
          return -1;
        }
    else
    {
      return 1;
    }
      
 }  /* end of sendsynpkt */

int c_sendAckPkt(int ackNum)
 {

          int sendAck;
      extern connection connC;
      srtp_header ackPacket;
      ackPacket = initialize();
      ackPacket.contrl_field = ACK;     
      ackPacket.ack_num = ackNum;
     
      sendAck = sendto(connC.socketDesc, getPacket(ackPacket), MAX_SRTP_PACKET,0,(struct sockaddr *)&connC.host_addr, sizeof(struct sockaddr));
     
      if (sendAck == -1)
      {
        return -1;
      }
      else
      {
         return 1;

      }
   
 } /* end of c_sendAckPkt */
     

/*** generate one packet that contains command, filename, filesize***/
int sendSetupPkt(char *filename, char *command, int namelength)
{  
        
        int sendPkt;
        srtp_header setupPkt;
        extern connection connC;
       
        setupPkt = initialize();
        setupPkt.contrl_field = command;
        memset(setupPkt.data,0,80);
        strncpy(setupPkt.data, filename, namelength);
        sendPkt = sendto(connC.socketDesc, getPacket(setupPkt), MAX_SRTP_PACKET+10, 0, (struct sockaddr*)&connC.host_addr, sizeof(struct sockaddr));
        if(sendPkt ==-1)
        {
            return -1;  /* error sending packet */
        }
        else
        {
            return 1;  /* packet sent ok */
        }
       
} /* end of sendSetupPkt */



//THIS FUNCTION PERFORMS 3-WAY HANDSHAKE, ESTABLISHES   
//CONNECTION AND RETURNS A CONNECTION NUMBER
    
    int SRTP_Open(struct sockaddr *udp_host_addr, int port_number)
    {  int connection_number = 1;
       struct sockaddr_in client_addr;
       extern connection connC;
      
       //*************STEP 1: CREATE SOCKET***********************

    if (connC.currentState ==  CLOSED)
    {
      //printf("Current State = %d\n",connC.currentState);
   
          connC.socketDesc = socket(AF_INET, SOCK_DGRAM, 0);
      connC.connection_number = connection_number = 1;

          client_addr.sin_family      = AF_INET;
          client_addr.sin_port        = htons(port_number);
          client_addr.sin_addr.s_addr = INADDR_ANY;      
             
          if (connC.socketDesc == -1)
          {
           printf("Socket failed to create!\n");
       exit(1);
          }
      
          else
          {  
       //************STEP 2: BIND SOCKET TO LOCAL ADDRESS**********
      
           if (bind(connC.socketDesc, (struct sockaddr *)&client_addr, sizeof(struct sockaddr)) == -1)
       {
          printf("Bind Failed in SRTP_Open!\n");
          close(connC.socketDesc);
          exit(1);
       }
       else
       {
       // printf("Bind successful!\n");
        fcntl(connC.socketDesc,F_SETFL,O_NONBLOCK);
           }
      }
         return connection_number;
     } 
}
   
//********************END SRTP_Open Function***************************
   
//***********STEP 1: GO TO STATE LISTEN************** 
    
int SRTP_Listen(int port_number)       

       //********** LISTEN FOR A SYN*************
       extern connection connS;
       int sockfd;
       struct sockaddr_in host_addr;
      
       connS.connection_number = 2;
      
    if (connS.currentState == CLOSED)
    { 
       //*********CREATE SOCKET**************
      
       sockfd = socket(AF_INET, SOCK_DGRAM, 0);
       connS.socketDesc = sockfd;
      
       host_addr.sin_family = AF_INET;
       host_addr.sin_port   = htons(port_number);
       host_addr.sin_addr.s_addr = INADDR_ANY;
      
       if(sockfd==-1)
       {
          printf("CREATE SOCKET FAILED!\n");
      exit(1);
       }
      
       //************ELSE BIND THE SOCKET*******
       else
       {
          connS.socketDesc = sockfd;
      if(bind(sockfd,(struct sockaddr *)&host_addr, sizeof(struct sockaddr)) == -1)
      {
         printf("Bind failed in SRTP_Listen!\n");
         close(sockfd);
         exit(1);
      }
      else
      {printf("Bind Successful!\n");
       fcntl(sockfd,F_SETFL,O_NONBLOCK);
      }
       }
           
       connS.currentState = LISTEN;
       //printf("Current State: %d\n",connS.currentState);

       return connS.connection_number;
     }
    
     if (connS.currentState == SYN_RECVD)
     { 
       //*************SEND A SYNACK********************
      
        int sendSyn = sendSynAckPkt();
      
      
       if (sendSyn == -1)
       {
          printf("SYNACK SEND ERROR!\n");
      connS.currentState = CLOSED;
      close(connS.socketDesc);
      exit(1);
       }
       else if (sendSyn != -1)
       {
         printf("SYNACK SENT!\n");   
       }
       return connS.connection_number;
      }     
    }

int SRTP_Close(int connection_number)
{
    extern connection connS,connC;
    //printf("INSIDE CLOSE!\n");
   
    if ((connS.connection_number==connection_number)&&(connS.currentState==CLOSE_WAIT))
    {
      //printf("SENDING A FINACK!\n");
      connS.currentState = LAST_ACK;
      int temp = sendFinAckPkt();
      return temp;
    }
    else if((connC.connection_number==connection_number)&&(connC.currentState==ESTABLISHED))
    {
      //printf("TERMINATING-SENDING A FIN\n");
      connC.currentState = FIN_WAIT1;
      int temp = sendFinPkt();
      return temp;
    }
    else if((connC.connection_number==connection_number)&&(connC.currentState==FIN_WAIT2))
    {
       connC.currentState = CLOSED;
       //printf("Sending Ack on FIN\n");
       int temp = c_sendAckPkt(0);
       return temp;
    }
}

int SRTP_Send(int conn_number, char*buffer_ptr, int buffer_size)

    int num, r, sent;
    static char *string;
    string = (char *)calloc(81, sizeof(char));
    srtp_header srtp;
    static char *result;
    char value[81];
    extern connection conn1;
   
   sent = num = 0;
   memset(string, NULL, MAX_SRTP_PAYLOAD + 1);
   memset(value, NULL, 81);
     
   while(*buffer_ptr != 0)
   {
     value[num++] = *buffer_ptr++;
             
     if( ((num / 80) == 1) )
     {
       //printf("String greater than 80\n\n\n\n");

      srtp = initialize();
      srtp.src_port_num = 3490;
      srtp.dest_port_num = connC.portNumber;
      srtp.window_size = 10;
      //srtp.contrl_field = DAT; /*0416*/
      srtp.ack_num = 0;
     
      if(*buffer_ptr == NULL)  /*0416*/
      {
         srtp.contrl_field = DATL;
      }
      else
      {
         srtp.contrl_field = DAT;   
      }

           
       
       srtp.seq_num = (sent+1)*80;
       memset(srtp.data,NULL,80);  
              
       strcat(string, value);
       strncpy(srtp.data, string, strlen(string));
        srtp.cksum = checksum(srtp);
        //printf("~~~~~~CHECKSUM ON THIS PACKET:  %d\n", srtp.cksum);     
         
       insertTimer(srtp,sent);    
       sent++;

       num = 0;
       memset(string, NULL, MAX_SRTP_PAYLOAD + 1);
       memset(value, NULL, 81);
     }   
   } /*end of whileloop */
    
   //printf("strlen = %d\n\n", strlen(value) ) ;
   if (strlen(value)>0)
   {
      //printf("String less than 80\n\n");

     srtp = initialize();
     srtp.src_port_num = 3490;
     srtp.dest_port_num = connC.portNumber;
     srtp.window_size = 10;
     srtp.ack_num = 0;
           
      
      srtp.contrl_field=DATL;
      srtp.seq_num = (sent+1)*80;
      memset(srtp.data,NULL,80);
                   
      strcat(string, value);
      strncpy(srtp.data, string, strlen(string));
      srtp.cksum = checksum(srtp);
      //printf("~~~~~~CHECKSUM ON THIS PACKET: %d\n", srtp.cksum);     
     

      insertTimer(srtp,sent);
      sent++;
      num = 0;
      memset(string, NULL, MAX_SRTP_PAYLOAD + 1);

     } /*end of if*/
         
     return sent;

}


int SRTP_Receive(int conn_num, char *buffer_ptr, int buffer_size)
{
    
     srtp_header srtp;
   
    /*  1) reads data from udp buffer
      2) parse packet string
      3) create data packet (structs)
      4) return # of bytes received or an error code = -1 */
     
      srtp = parser(buffer_ptr);
     
      /*** pass srtp to global buffer if space is avail if not return error **/
      

       return buffer_size;
}

How to write an FTP client


Here’s a simple code for ftp client:

Step 1: Begin by defining socket for opening a connection (ie for resolving host ip address and port number)

struct hostent     *he;
   struct sockaddr_in clientaddr;
   extern connection  connC;
   extern timer       t1[MAX_NUM_PACKETS];
   extern sWindow     window;
   int                sz, recAck, req=0, temp, connid=0, ackNum, jj;

   char               buffer[MAX_SRTP_STRING]="";
   char               host_address[60]="";
   char *quitCom = "quit";
   char *put="put";
   char *action;
   char command[30]="";
   char *filename;

   srtp_header        pkt;
   char TONumber[10]="";
   int compare=1, putcompare,namelength, pID, stimulus,ackIndex, rFlag, m, i;
   bool rtxflag, found, problem;

   int pp=pipe(pfd);
 
   fcntl(pfd[0],F_SETFL,O_NONBLOCK);
 
   done = 0;
   initWindow(7); /*0418*/
  
   struct sigaction act;
   act.sa_handler = sig_chld;
   sigemptyset(&act.sa_mask);
   act.sa_flags = SA_NOCLDSTOP;
               
   if(sigaction(SIGCHLD,&act,NULL)<0)
      printf("Chld sig error\n");
                 
   connC.currentState =  CLOSED; 
   printf("Current State = %d\n",connC.currentState);
   connC.host_addr.sin_family = AF_INET;
               
   printf("HostName: ");
   scanf("%s",host_address);
   he = gethostbyname(host_address);
   if (he==NULL)
   {
     printf("HOSTNAME ERROR!\n");
     exit(1);
   }
   else
   {
     memcpy(&connC.host_addr.sin_addr, he->h_addr, he->h_length);
   }

   printf("PortNumber: ");
   scanf("%d",&connC.portNumber);
   connC.host_addr.sin_port = htons(connC.portNumber);
   connC.connection_number = SRTP_Open((struct sockaddr *)&connC.host_addr, connC.portNumber);

Step 2: Begin state machine and establish 3-way handshake

if (connC.currentState != ESTABLISHED)
   {               
      connC.connection_number = sendSynPkt();
      startsyntimer();
      if (connC.connection_number == 1)
      {
        connC.currentState = SYN_SENT;
                printf("SYN SENT!\n");
                printf("Current State: %d\n",connC.currentState);
                printf(" Waiting for ACK and SYN from server\n");
      }
      else
      {
                printf("SYN SEND ERROR!\n");
                close(connC.socketDesc);
                exit(1);
      }
                    
      while (syntimer != 1)
      {
                recAck = recvfrom(connC.socketDesc,buffer,MAX_SRTP_PACKET,0,(struct sockaddr*)&connC.host_addr, &sz);
                if ((recAck > 0) && (connC.currentState == SYN_SENT))
                {
                  pkt = parser(buffer);
                  if (strcmp(pkt.contrl_field, SYN_ACK) == 0)
                  {
           printf("RECEIVED A SYNACK!!!!!\n");
           printf("Sending ACK for SYN_ACK from server\n");
                   req=1;
                   break;                      
                  }                             
                }
       }
     }        
               
   if (req != 1)
   {
     printf("Connection Timed out ! Retry later\n");
     exit(1);
   }
     
   if (c_sendAckPkt(100) == -1)
   {
     printf("Send ACK ERROR!");
     connC.currentState = CLOSED;
     close(connC.socketDesc);
     exit(1);
   }
   else
   {  
     printf("ACK SENT!\n\n");
     connC.currentState = ESTABLISHED;
     printf("Connection Established!\n");    
   }

Step 3: Connection is established at this point to perform data transfer
do
   {
     if (syntimer==1) break;
   }while(syntimer != 1); 
   
   gets(command);
     
   while(compare != 0)
   {
      printf("\n");
      printf("my_ftp> ");
      gets(command);
     
      while(int(command[0])==0)
      {
                printf("my_ftp> ");
                gets(command);
      }
                                    
      action = strtok(command," ");
      compare = strcmp(action,quitCom);
      putcompare = strcmp(action,put);
                                    
      while((putcompare!=0)&&(compare!=0))
      {
       printf("Command not found!\n");
       printf("my_ftp> ");
       for(int i=0;i<30;i++)
                command[i]=0;
       gets(command);
                                      
       while(int(command[0])==0)
       {  
                 printf("my_ftp> ");
                 gets(command);
        }
                                    
       action = strtok(command," ");
       compare = strcmp(action,quitCom);
       putcompare = strcmp(action,put);
     }
                                    
     if(putcompare==0)
     {
                filename = strtok(NULL,"\n");
        namelength = strlen(filename);                                  
                printf("%s",filename);
                                    
                int fD, buff_size;
                char fileBuff[30000]="";
                                    
                fD=open(filename,O_RDWR,0);
                if (fD==-1)
                {
                  printf("check filename!\n");        
                  close(fD);                           
                }             
                else
        { 
                  strncpy(fileBuff," ",30000);
          read(fD,fileBuff,30000);
          close(fD);
                  buff_size = strlen(fileBuff);
                  printf("file read successfully\n");

          if( (sendSetupPkt(filename, action, namelength) == -1) )
                  {
                     printf("Error in sending setupPkt\n\n");
                  }
                  else
                  {
                     printf("Hoorray!!  SetupPkt sent!!\n\n");
                  }
                 

          garb = 0;
          conflag = 0;
          timeout = 0;
          rtxflag = false;
          problem = false;
                  totalacks = 0;
                  initWindow(10);
                  initTimer();
                  char parentack[15]="", childack[15]="";

                  // ======================================================================
                  // forking a listener process
                  // ========================================================================                                 
                                                 
                  switch(pID = fork())
          {
            case 0 :
               printf("CHILD Listening for ACKS\n");
                      
                       
                       for(;;)
                       {
                         int r = recvfrom(connC.socketDesc,buffer,MAX_SRTP_STRING,0,(struct sockaddr*)&connC.host_addr, &sz);

                         if ((r > 0)&&(int(buffer[0])!=0))
                                 {
                                    pkt = parser(buffer);
                                   
                                    

                            if ((strcmp(pkt.contrl_field, ACK) == 0))
                                    {
                                       printf("CHILD RECEIVED DATA ACK : %d\n", pkt.ack_num);
                                       itoa(pkt.ack_num,childack);
                                       write(pfd[1],childack,15);
                                      
                                       for (int p=0;p<15;p++)
                                           childack[p]=0;
                                    }
                    for(int p=0;p<(MAX_SRTP_STRING);p++)          
                                    {   buffer[p]=0;
                                        if (p<15) childack[p]=0;
                                    }
                         }
                 for(int p=0;p<(MAX_SRTP_STRING);p++)             
                                 {    buffer[p]=0; if (p<15) childack[p]=0;}                                                    
                       }                          

             default:
               listenerprocessId = pID;                      
           }                                                                                   

                //=========================================================================
                                               
                                                 
                  numPkts = SRTP_Send(connC.connection_number,fileBuff,buff_size);
                  printf("numPkts: %d\n",numPkts);             

                  if (numPkts
                  {    initWindow(numPkts);
                       window.start_index =0;
               sendPackets(0,numPkts);
                       stimulus = numPkts;
                       rFlag = 0;
                  }
         else
          {   window.start_index =0;
              sendPackets(0,window.window_size);  
                      stimulus = window.window_size;
                      rFlag = 1;                            
                  }
                               
                  while(totalacks != -1)
          {
                     read(pfd[0],parentack,15);
                     jj = window.start_index;found = false;
                     while ((jj<(window.start_index + window.window_size)) &&(!found))
                     {
                        if ((t1[jj].timed_out)&&(!t1[jj].ack_recd))
                 {
                 printf("Ack not received and timeout on %d\n",jj);
                                 found = true;
                 }
                                else jj++;
                     }
             if(found)
             {
                 printf("ACK not received so timeout\n");
                 for(int y=jj+1; y<(window.start_index + window.window_size);y++)
                 {      kill(t1[y].pID,SIGSTOP); t1[y].timed_out = 1;
                                             printf("killed timer for pkt %d\n",y);
                 }
                 window.start_index = jj;
                 stimulus = window.start_index + window.window_size;
                 printf("Resending %d to %d\n", window.start_index, stimulus);
                                 timeout =0;
                 if (conflag == 0)
                  {sendPackets(window.start_index,window.window_size);
                  }
                 else
                  {
                  conflag = 0;
                  problem = true;
                  totalacks = -1;
                  }
                 garb = 1;
                                 rtxflag = 1;
             }
                 
                     if (int(parentack[0]) != 0)
                     {  ackNum = atoi(parentack);
                        ackIndex = ((ackNum-1)/80)-1;
                                printf("PARENT RECEIVED ACK FOR: %d\n",ackIndex);
                garb = 0;              
                                if (ackIndex >= 0)
                                {             
                                 if(t1[ackIndex].timed_out == 0)
                                 {
                                  kill(t1[ackIndex].pID, SIGSTOP);
                                  t1[ackIndex].ack_recd = 1;
                                  printf("Stoping Timer: %d\n", t1[ackIndex].pID);
                                  t1[ackIndex].pID = 0;
                                  rtxflag = false;
                                  totalacks++;                                         
                                 }
                                 else if (t1[ackIndex].timed_out == 1)
                                   printf("Packet %d TIMED OUT\n", ackIndex);
                                }
                                                                                               
                        if ((totalacks == numPkts) ||( ackNum == 0))
                        { 
                                  rFlag = 0;
                          printf("ALL ACKS RECD\n");
                                  totalacks = -1;
                                  break;
                        }

                        for (int p=0;p<15;p++)             
                   parentack[p]=0;                                                                                 
                     }             
             if ((ackIndex != (numPkts-1)) && (garb ==0))
                     {
                      rtxflag = false;             
             
                      for(int i=window.start_index;i
                        {
                         if((!rtxflag) && (ackIndex == (stimulus -1)) && (garb == 0))                      
                         {
                                  printf("Present Window2 from %d  to %d \n", window.start_index, stimulus);
                                  window.start_index = window.start_index + window.window_size;
                          stimulus = window.start_index + window.window_size;
                                  timeout =0;
                          printf("Window2 slides to %d and %d \n", window.start_index, stimulus);
                          sendPackets(window.start_index,window.window_size);
                                 }
                                }
                      }
           } 


       printf ("Out of while loop\n");
       kill(listenerprocessId, SIGKILL);
      
       /*0418*/
       for (int r=0; r
        if (t1[r].pID != 0)
         kill(t1[r].pID, SIGSTOP);
 
       initTimer();
       printf("Done = %d\n", done);
       while (done != 1) {}
       if (problem == false)
          printf("File Put Done! %d\n",numPkts);
       else
            printf("traffic problems ! You may want to try again\n");
       for(i=0;i<30000;i++)
                   fileBuff[i] = 0;
       done = 0;
         }                           
      }
     }     
  
Step 4: Connection teardown with graceful disconnect

if((compare==0)&&(connC.currentState==ESTABLISHED))
   {
     printf("Goodbye!\n");
     int d = SRTP_Close(connC.connection_number);

     if(d)
       connC.currentState = FIN_WAIT1;
   }  
   if (connC.currentState == FIN_WAIT1)
   { 
      printf("WAITING FOR FINACK!\n");
      for(;;)
      {
                int r = recvfrom(connC.socketDesc,buffer,MAX_SRTP_PACKET,0,(struct sockaddr*)&connC.host_addr, &sz);
        if ((r>0)&&(int(buffer[0])!=0))
        {
                  pkt = parser(buffer);
                  if (strcmp(pkt.contrl_field,FIN_ACK)==0)
                  {
                    printf("Received FINACK!\n");
            connC.currentState = FIN_WAIT2;
                    int last = SRTP_Close(connC.connection_number);
                    if (last)
                       connC.currentState = CLOSED;
                  }
         }
                 if (connC.currentState == CLOSED)
                     exit(1);
       }
    } 
return 0;  
}