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

How to write FTP Application

To Write FTP application, you will need to write the ftp server and the ftp client. The following illustrates the concepts for writing an FTP Server. In the following post, I will include the ftp client code.


Here’s a simple code for an ftp server that uses UDP socket:

Step 1:  Define connection port number and create socket to listen on port number

int main()
{
   extern connection connS;
   char buffer[MAX_SRTP_PACKET+10]="";
   extern incoming_buff server_buff[25];
  
   int process_id, recSome, sz, cls, counter=0;
   srtp_header srtp;
  
   connS.currentState = CLOSED;
   printf("Enter Port Number: ");
   scanf("%d",&connS.portNumber);

Step 2: Initialize buffer for incoming client messages

initializeBuff();
     
   while (connS.currentState != LISTEN)  
     connS.connection_number = SRTP_Listen(connS.portNumber);
  
   if (connS.currentState == LISTEN)
      sz = sizeof(connS.host_addr);    

Step 3: Set up handlers for signals and interrupts

struct sigaction act;
   act.sa_handler = sig_chld;
   sigemptyset(&act.sa_mask);
   act.sa_flags = SA_NOCLDSTOP;
  
   if (sigaction(SIGCHLD,&act,NULL)<0)
   {
     printf("CHILD SIGNAL ERROR\n");
     return 1;
   }     

Step 4: Implement server state machine inside infinite loop – server maintains state based on client response and messages to follow TCP state change behavior (ie – this in turn makes UDP “behave” like TCP with SRTP layer api)

    for (;;)
      {  
         recSome = recvfrom(connS.socketDesc, buffer, MAX_SRTP_PACKET+10,0,(struct sockaddr *)&connS.host_addr, &sz);
                 
                     if (recSome == -1)
                                 {
                                 }            
                     else if (buffer != NULL)
                                 {                
                       srtp = parser(buffer);
                       if (connS.currentState == LISTEN)
                                   {
                         if ( strcmp(srtp.contrl_field, SYN) == 0)
                                                 {
                           connS.currentState = SYN_RECVD;
                           printf("*****SYN RECEIVED!!!!!!!!\n");
                           synR = synTO= 0;          
                           int temp = SRTP_Listen(connS.portNumber);
                                                 }
                                   }
                       else if (connS.currentState == SYN_RECVD)
                                   {
                         if (strcmp(srtp.contrl_field, ACK) == 0)
                                                 {
                           printf("SYN ACK RECD!!\n");
                           connS.currentState=ESTABLISHED;
                           printf("CONNECTION ESTBLISHED!\n");                    
                                                 }                   
                                   }
                       else if (connS.currentState == ESTABLISHED)
                                   {
                         printf("currentState ESTABLISHED!!\n");
                         if (((strcmp(srtp.contrl_field, DAT)) == 0) || (strcmp(srtp.contrl_field, DATL) == 0))
                                                 {  
                                                   printf("RECEIVING DATA PACKETS!!\n");
                                       if (checksum(srtp)==srtp.cksum)
                                                   {
                                         int inBuff=bufferPacket(srtp);
                                         printf("In buff: %d\n", inBuff);
                                         if (inBuff==-1)
                                                                 {
                                           writeFile();
                                                                   printf("FILE PUT DONE!\n");
                                                                 }
                                                   }
                                                 }
                         else if ((strcmp(srtp.contrl_field,FIN))==0)
                                                 {   printf("FIN RECEIVED!");
                                         synTimer(5);
                             connS.currentState = CLOSE_WAIT;
                                         cls = SRTP_Close(connS.connection_number);
                                         if (cls)
                                            connS.currentState = LAST_ACK;
                                                 }
                         else if ((strcmp(srtp.contrl_field,PUT))==0)
                             initializeBuff();
                                   }
                       else if ((connS.currentState == LAST_ACK)||(finTO))
                                   {
                         if (strcmp(srtp.contrl_field,ACK)==0)
                                                 {   finR=1;
                             printf("RECEIVED ACK ON FIN\n");
                                         printf("GOODBYE!\n");
                                         connS.currentState = CLOSED;
                                                 }
                  
                                   }
                       else if (connS.currentState == CLOSED)
                          exit(1);
                       for (int f=0;f< (MAX_SRTP_PACKET+10);f++)
                          buffer[f] = NULL; 

                 }  
                 if ((connS.currentState==LAST_ACK)&&(finTO))
                    connS.currentState=CLOSED;
         if (connS.currentState == CLOSED)
                 {
                   printf("SO FAR: \n");
                   printf("%s\n",server_buff[0].pkt.data);
                   printf("%s\n",server_buff[1].pkt.data);  
                   exit(1);
                 }
      }
 return 0;
}

Final Code: Here are all the includes and function definitions prior to beginning main



void sig_chld(int);

static int Stimer, synR, synTO,finR,finTO, maxPacket;

void synTimer(int amount)
{
   synTO=finTO=0;
  
   int processId;
  
   processId = fork();
  
   switch(processId)
   {
     case 0:
        printf("FIN timer started!\n");
        //usleep(amount);
                sleep(amount);
                printf("FIN timer expired!\n");
        _exit(0);
    
     default:
       Stimer = processId;
       //return processId;
   }
  
}

void sig_chld(int signo)
{
   int status;
   extern connection connS;
  
   waitpid(Stimer,&status,WNOHANG);
   if(WIFEXITED(status))
   { synTO=1; finTO=1;
     //if (!synR)
     if (!finR)
     {
        connS.currentState = CLOSED;
                printf("NO FIN ACK RECEIVED!\n");
     } 
     else printf("YOU WERE ACKED!\n");
   }
return;
}

int bufferPacket(srtp_header srtp)
{  extern incoming_buff server_buff[25];
   int index = (srtp.seq_num/80)-1;

   if (strcmp(srtp.contrl_field,DATL)==0)
   { 
                  maxPacket=index;
   }

   int tmp;
   
   if (!server_buff[index].received)
   {  server_buff[index].pkt= srtp;
      server_buff[index].received = 1;
      printf("Storing packet # %d\n",index);
   }
  
   int i=0, ackNum;
   while ((server_buff[i].received)&&(server_buff[i].ack_sent)&&(i<25))
      i++;
   if (strcmp(server_buff[i-1].pkt.contrl_field,DATL)==0)
   {  printf("ALL ACKS SENT!\n");
                  return -1;
   }
   else if ((server_buff[i].received) &&(!server_buff[i].ack_sent))
   {
      ackNum = (i*80)+1;
                  tmp = s_sendAckPkt(ackNum);
                  server_buff[i].ack_sent = 1;
                  if (tmp)
                                  printf("ACK SENT %d\n",ackNum);
                  return i;
   }
}

void writeFile()
{  char tempBuff[2000];
   int fileDesc;
  
   printf("INSIDE WRITE FILE\n");
  
   fileDesc = creat("testPut",448);
  
   if (fileDesc<0)
      printf("File Exists!\n");

   for (int t=0;t<25;t++)
   {
     write(fileDesc,server_buff[t].pkt.data,strlen(server_buff[t].pkt.data));

     if (strcmp(server_buff[t].pkt.contrl_field,DATL)==0)
     { 
                close(fileDesc);break;
     }
   }
return;
}

void initializeBuff()
{
  for(int i=0;i<25;i++)
  {  server_buff[i].received=0;
     server_buff[i].ack_sent=0;
  }
  return; 
}

Friday, March 9, 2012

Into the Mind of a Cold-Blooded Killer

I just finished John Grisham's The Chamber, about a young lawyer named Adam Hall who is climbing the corporate ladder at Chicago's presigious Kravitz & Bane law firm when he decides to take a pro bono case as defense attorny to a convict on death row. Sam Cayhall is headed for Mississippi's Parchman, the infamous gas chamber but is he really as guilty as they believe? Grisham leads the reader closer to his execution the way Dante leads readers through The Inferno.  As Adam tries to uncover the truth about who Sam Cayhall really is, he takes the reader inside the mind of a cold-blooded killer. Grisham makes a poignant statement about why the death penalty is denounced as a cruel form of punishment by many countries, and why it is still enforced in the United States. This is a very compelling read, and hard-to-put-down book!

Saturday, January 28, 2012

New Screenplay and More!

1. Check out a free promotion of a great screenplay now: http://www.amazon.com/dp/B0071MMYCW

2. Check out a collection of free verse: http://www.amazon.com/dp/B0070IJA8I