0
votes

I'm coding simple FTP server for a school project and I have a problem with file transfer.

In fact, when the command PASV is sent, I create a socket with the specified port and listen but then later when the command RETR is sent and I try to write the file on the socket file descriptor, the write block the excecution of the program and the ftp client keep waiting.

Why is this write blocking ?

This function create my socket

int     create_s_socket(struct sockaddr_in *sock, int port)                                    
{                                                                                              
  int           socket_fd;                                                                     
  int           enable;                                                                        

  if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)                                     
    return (-1);                                                                               
  enable = 1;                                                                                  
  if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0)               
    return (-1);                                                                               
  sock->sin_family = AF_INET;                                                                  
  sock->sin_addr.s_addr = htonl(INADDR_LOOPBACK);                                              
  sock->sin_port = htons(port);                                                                
  if (bind(socket_fd, (struct sockaddr *)sock, sizeof(*sock)) < 0)                             
    return (-1);                                                                               
  return (socket_fd);                                                                          
}

This function open open the data connection (passive mode)

void                    cmd_pasv(t_handle *hdl)                                                
{                                                                                              
  struct sockaddr_in    data_sock;                                                             
  uint16_t              port;                                                                  
  socklen_t             len;                                                                   

  len = sizeof(data_sock);                                                                     
  if ((hdl->data_fd = create_s_socket(&data_sock, 0)) != -1)                                   
    {                                                                                          
      listen(hdl->data_fd, 5);                                                                 
      getsockname(hdl->data_fd, (struct sockaddr *)&data_sock, &len);                          
      port = ntohs(data_sock.sin_port);                                                        
      printf("port = %d\n", port);                                                             
      set_rep(hdl, 227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d).",                          
              (int)(data_sock.sin_addr.s_addr & 0xFF),                                         
              (int)((data_sock.sin_addr.s_addr & 0xFF00) >> 8),                                
              (int)((data_sock.sin_addr.s_addr & 0xFF0000) >> 16),                             
              (int)((data_sock.sin_addr.s_addr & 0xFF000000) >> 24),                           
              (int)(port / 256), (int)(port % 256));                                           
      printf("data fd %d\n", hdl->data_fd);                                                    
    }                                                                                          
  else                                                                                         
    set_rep(hdl, 500, "Canno open data connection");                                           
}

This function open ad send the file throught the data line

void            cmd_retr(t_handle *hdl)                                                        
{                                                                                              
  char          *fullpath;                                                                     
  FILE          *file;                                                                         
  size_t        nread;                                                                         
  char          buf[BLOCK_SIZE];                                                               

  log_msg(INFO, "data fd is %d", hdl->data_fd);                                                
  if (hdl->data_fd > 0)                                                                        
    {                                                                                          
      log_msg(INFO, "data fd is %d", hdl->data_fd);                                            
      if (hdl->cmd_arg)                                                                        
        {                                                                                      
          log_msg(INFO, "file to uploadis %s", hdl->cmd_arg);                                  
          fullpath = malloc(sizeof(char) *                                                     
                            strlen(hdl->path) + strlen(hdl->cmd_arg) + 2);                     
          sprintf(fullpath, "%s/%s", hdl->path, hdl->cmd_arg);                                 
          log_msg(INFO, "full path is %s", fullpath);                                          
          if ((file = fopen(fullpath, "r")) != NULL)                                           
            {                                                                                  
              log_msg(INFO, "file opened correctly");                                          
              while ((nread = fread(buf, sizeof(char), BLOCK_SIZE, file)) > 0)                 
                {                                                                              
                  log_msg(INFO, "read %d bytes \"%s\"", nread, buf);                           
                  if (write(hdl->data_fd, buf, nread) == -1)                                   
                    log_msg(ERROR, "write: %s", strerror(errno));                              
                }                                                                              
              if (nread < 0)                                                                   
                log_msg(ERROR, "read: %s", strerror(errno));                                   
            }                                                                                  
          else                                                                                 
            set_rep(hdl, 000, "File \"%s\" not found", fullpath);                              
          free(fullpath);                                                                      
        }                                                                                      
      else                                                                                     
        set_rep(hdl, 000, "Missing arg");                                                      
    }                                                                                          
  else                                                                                         
    set_rep(hdl, 000, "Data connection not open fd %d", hdl->data_fd);                         
}            

Thanks ;)

1

1 Answers

1
votes

In fact, when the command PASV is sent, I create a socket with the specified port and listen but then later when the command RETR is sent and I try to write the file on the socket file descriptor, the write block the excecution of the program and the ftp client keep waiting.

Why is this write blocking ?

It's unclear whether you've presented all the relevant code. If you have, then the problem is certainly that you are trying to write to the server socket. You should instead accept() a connection to that socket, verify that it is from the expected client, and use the resulting connected socket (which will have a different file descriptor) to communicate.