aboutsummaryrefslogtreecommitdiff
path: root/pa1_file_transfer/uftp_server.c
diff options
context:
space:
mode:
authorJack Sangdahl <jack@pngu.org>2024-10-02 12:58:44 -0600
committerJack Sangdahl <jack@pngu.org>2024-10-02 12:58:44 -0600
commitbba288a79171b2f3cf7efb72e56c0c6fb5cf6116 (patch)
treef3c8f96894097394685dd228b57c8b25a2ae54b5 /pa1_file_transfer/uftp_server.c
parentfa8c37bb3ecd3cc6caba9b6bf465c360301432ea (diff)
downloadecen5273-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.c176
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;
+}