Friday, March 23, 2012

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;  
}

No comments: