diff options
author | Jack Sangdahl <jack@pngu.org> | 2024-10-02 12:58:44 -0600 |
---|---|---|
committer | Jack Sangdahl <jack@pngu.org> | 2024-10-02 12:58:44 -0600 |
commit | bba288a79171b2f3cf7efb72e56c0c6fb5cf6116 (patch) | |
tree | f3c8f96894097394685dd228b57c8b25a2ae54b5 /pa1_file_transfer/uftp_server.c | |
parent | fa8c37bb3ecd3cc6caba9b6bf465c360301432ea (diff) | |
download | ecen5273-bba288a79171b2f3cf7efb72e56c0c6fb5cf6116.tar.gz ecen5273-bba288a79171b2f3cf7efb72e56c0c6fb5cf6116.zip |
Programming Assignment 1: File Transfer
Signed-off-by: Jack Sangdahl <jack@pngu.org>
Diffstat (limited to 'pa1_file_transfer/uftp_server.c')
-rw-r--r-- | pa1_file_transfer/uftp_server.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/pa1_file_transfer/uftp_server.c b/pa1_file_transfer/uftp_server.c new file mode 100644 index 0000000..e170b3f --- /dev/null +++ b/pa1_file_transfer/uftp_server.c @@ -0,0 +1,176 @@ +// File Transfer (Server) +// Jack Sangdahl +// 07 September 2024 +#include <arpa/inet.h> +#include <dirent.h> +#include <fcntl.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <unistd.h> + +#define DATA_SIZE 1024 + +int main(int argc, char **argv) { + if (argc != 2) { + fprintf(stderr, "usage: %s <port_num>\n", argv[0]); + exit(EXIT_FAILURE); + } + int port = atoi(argv[1]), sock; + if (port > 65535 || port < 5000) { + fprintf(stderr, "%s: port must be in range 5000-65535\n", argv[0]); + exit(EXIT_FAILURE); + } + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + fprintf(stderr, "%s: error opening socket\n", argv[0]); + exit(EXIT_FAILURE); + } + struct sockaddr_in server_addr, client_addr; + memset(&server_addr, 0, sizeof(server_addr)); + memset(&client_addr, 0, sizeof(client_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons((short)port); + if (bind(sock, (const struct sockaddr *)&server_addr, sizeof(server_addr)) < + 0) { + fprintf(stderr, "%s: error binding socket to port\n", argv[0]); + exit(EXIT_FAILURE); + } + printf("ready to receive client connections\n"); + socklen_t client_size = sizeof(client_addr); + char data[DATA_SIZE], command[DATA_SIZE], filename[DATA_SIZE]; + while (1) { + memset(data, 0, strlen(data)); + ssize_t n = recvfrom(sock, data, DATA_SIZE, 0, + (struct sockaddr *)&client_addr, &client_size); + if (n < 0) + fprintf(stderr, "%s: error receiving datagram from client\n", argv[0]); + struct hostent *host_info = + gethostbyaddr((const char *)&client_addr.sin_addr.s_addr, + sizeof(client_addr.sin_addr.s_addr), AF_INET); + if (!host_info) + fprintf(stderr, "%s: error determining host info\n", argv[0]); + char *host_addr = inet_ntoa(client_addr.sin_addr); + printf("%s: received datagram from %s (%s)\n", argv[0], host_info->h_name, + host_addr); + printf("received %d/%d bytes: %s\n", (int)strlen(data), (int)n, data); + sscanf(data, "%s %s", command, filename); + if (!strncmp(command, "get", 3)) { + printf("sending file %s to client...\n", filename); + int send_data, f = open(filename, O_RDONLY); + if (f < 0) { + send_data = -1; + fprintf(stderr, "error: file %s does not exist in directory\n", + filename); + } else + send_data = 1; + if (sendto(sock, &send_data, sizeof(send_data), 0, + (struct sockaddr *)&client_addr, client_size) < 0) { + fprintf(stderr, "%s: error sending status to client\n", argv[0]); + if (f >= 0) + close(f); + continue; + } + if (f < 0) + continue; + off_t file_size = lseek(f, 0, SEEK_END); + if (file_size < 0) { + fprintf(stderr, "error: determine file size of file %s\n", filename); + close(f); + continue; + } + lseek(f, 0, SEEK_SET); + sprintf(data, "%ld", file_size); + if (sendto(sock, data, strlen(data), 0, (struct sockaddr *)&client_addr, + client_size) < 0) { + fprintf(stderr, "%s: error sending file size to client\n", argv[0]); + close(f); + continue; + } + memset(data, 0, sizeof(data)); + ssize_t bytes_read; + while ((bytes_read = read(f, data, sizeof(data)))) { + if (sendto(sock, data, bytes_read, 0, (struct sockaddr *)&client_addr, + client_size) < 0) { + fprintf(stderr, "%s: error sending data to client\n", argv[0]); + break; + } + memset(data, 0, sizeof(data)); + } + if (bytes_read < 0) + fprintf(stderr, "%s: error reading from file %s\n", argv[0], filename); + close(f); + } else if (!strncmp(command, "put", 3)) { + printf("receiving file %s from client...\n", filename); + if (recvfrom(sock, data, DATA_SIZE, 0, (struct sockaddr *)&client_addr, + &client_size) < 0) + fprintf(stderr, "%s: error receiving data from client\n", argv[0]); + int file_size = atoi(data), + f = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (f < 0) + fprintf(stderr, "%s: error opening file %s\n", argv[0], filename); + int bytes_transferred = 0; + ssize_t bytes_received; + while (bytes_transferred < file_size) { + memset(data, 0, sizeof(data)); + int transfer_size = (file_size - bytes_transferred < DATA_SIZE) + ? (file_size - bytes_transferred) + : DATA_SIZE; + bytes_received = + recvfrom(sock, data, transfer_size, 0, + (struct sockaddr *)&client_addr, &client_size); + if (bytes_received < 0) { + fprintf(stderr, "%s: error receiving data from client\n", argv[0]); + close(f); + } + if (write(f, data, bytes_received) != bytes_received) { + fprintf(stderr, "%s: error writing data to file %s\n", argv[0], + filename); + close(f); + } + bytes_transferred += bytes_received; + printf("received %d/%d bytes\n", bytes_transferred, file_size); + } + close(f); + printf("file %s transferred successfully\n", filename); + } else if (!strncmp(command, "delete", 6)) { + int send_data, f = open(filename, O_RDWR); + if (f < 0) { + send_data = 1; + if (sendto(sock, &send_data, sizeof(int), 0, + (struct sockaddr *)&client_addr, client_size) < 0) + fprintf(stderr, "%s: error sending data to client\n", argv[0]); + } + close(f); + if (remove(filename) < 0) { + send_data = 2; + fprintf(stderr, "%s: error removing file %s\n", argv[0], filename); + } else + send_data = 0; + if (sendto(sock, &send_data, sizeof(int), 0, + (struct sockaddr *)&client_addr, client_size) < 0) + fprintf(stderr, "%s: error sending data to client\n", argv[0]); + } else if (!strncmp(command, "ls", 2)) { + char send_data[DATA_SIZE] = {0}; + DIR *d = opendir("."); + int data_len = 0; + struct dirent *curr; + while ((curr = readdir(d))) { + int name_len = strlen(curr->d_name); + memcpy(send_data + data_len, curr->d_name, name_len); + data_len += name_len; + send_data[data_len] = '\n'; + data_len++; + } + closedir(d); + if (data_len) + if (sendto(sock, send_data, strlen(send_data), 0, + (struct sockaddr *)&client_addr, client_size) < 0) + fprintf(stderr, "%s: error sending data to client\n", argv[0]); + } else if (!strncmp(command, "exit", 4)) + printf("received exit signal from client\n"); + } + return EXIT_SUCCESS; +} |