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