From c5fcf7179a83ef65c86c6a4a390029149e518649 Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Tue, 5 Oct 2021 21:49:54 +0200 Subject: Duzy commit ze smieciami --- semestr-4/sieci/pracownia3/4pkt/config.h | 7 + semestr-4/sieci/pracownia3/4pkt/transport.c | 152 +++++++++++++++++++++ semestr-4/sieci/pracownia3/config.h | 10 ++ .../sieci/pracownia3/franciszek_malinka.tar.xz | Bin 0 -> 2744 bytes .../sieci/pracownia3/franciszek_malinka/config.h | 10 ++ .../pracownia3/franciszek_malinka/transport.c | 149 ++++++++++++++++++++ .../sieci/pracownia3/franciszek_malinka/utils.c | 58 ++++++++ .../sieci/pracownia3/franciszek_malinka/utils.h | 18 +++ .../sieci/pracownia3/franciszek_malinka/window.c | 42 ++++++ .../sieci/pracownia3/franciszek_malinka/window.h | 24 ++++ semestr-4/sieci/pracownia3/p3.pdf | Bin 0 -> 95110 bytes semestr-4/sieci/pracownia3/transport.c | 149 ++++++++++++++++++++ semestr-4/sieci/pracownia3/utils.c | 58 ++++++++ semestr-4/sieci/pracownia3/utils.h | 18 +++ semestr-4/sieci/pracownia3/window.c | 42 ++++++ semestr-4/sieci/pracownia3/window.h | 24 ++++ 16 files changed, 761 insertions(+) create mode 100644 semestr-4/sieci/pracownia3/4pkt/config.h create mode 100644 semestr-4/sieci/pracownia3/4pkt/transport.c create mode 100644 semestr-4/sieci/pracownia3/config.h create mode 100644 semestr-4/sieci/pracownia3/franciszek_malinka.tar.xz create mode 100644 semestr-4/sieci/pracownia3/franciszek_malinka/config.h create mode 100644 semestr-4/sieci/pracownia3/franciszek_malinka/transport.c create mode 100644 semestr-4/sieci/pracownia3/franciszek_malinka/utils.c create mode 100644 semestr-4/sieci/pracownia3/franciszek_malinka/utils.h create mode 100644 semestr-4/sieci/pracownia3/franciszek_malinka/window.c create mode 100644 semestr-4/sieci/pracownia3/franciszek_malinka/window.h create mode 100644 semestr-4/sieci/pracownia3/p3.pdf create mode 100644 semestr-4/sieci/pracownia3/transport.c create mode 100644 semestr-4/sieci/pracownia3/utils.c create mode 100644 semestr-4/sieci/pracownia3/utils.h create mode 100644 semestr-4/sieci/pracownia3/window.c create mode 100644 semestr-4/sieci/pracownia3/window.h (limited to 'semestr-4/sieci/pracownia3') diff --git a/semestr-4/sieci/pracownia3/4pkt/config.h b/semestr-4/sieci/pracownia3/4pkt/config.h new file mode 100644 index 0000000..42ccd89 --- /dev/null +++ b/semestr-4/sieci/pracownia3/4pkt/config.h @@ -0,0 +1,7 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#define DATAGRAM_LEN 1000 +#define HEADER_LEN 40 + +#endif diff --git a/semestr-4/sieci/pracownia3/4pkt/transport.c b/semestr-4/sieci/pracownia3/4pkt/transport.c new file mode 100644 index 0000000..806eb4e --- /dev/null +++ b/semestr-4/sieci/pracownia3/4pkt/transport.c @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "config.h" + +#define NS_TO_MS(X) ((long)(X) / (long)1000000) +#define S_TO_MS(X) ((long)(X) * (long)1000) + +int get_socket() { + int sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) { + fprintf(stderr, "socket error: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + return sockfd; +} + +size_t send_datagram(int sockfd, struct sockaddr_in server_address, char *buffer, size_t buffer_len) { + return sendto(sockfd, buffer, buffer_len, 0, (struct sockaddr*) &server_address, sizeof(server_address)); +} + +void send_data_request(int sockfd, struct sockaddr_in server_address, size_t pos, size_t bytes) { + char buffer[40]; + sprintf(buffer, "GET %ld %ld\n", pos, bytes); + size_t buffer_len = strlen(buffer); + if (send_datagram(sockfd, server_address, buffer, buffer_len) != buffer_len) { + fprintf(stderr, "sendto error: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } +} + +long get_time_interval(struct timespec start, struct timespec finish) { + return S_TO_MS(finish.tv_sec - start.tv_sec) + NS_TO_MS(finish.tv_nsec - start.tv_nsec); +} + +int poll_socket_modify_timeout(int sockfd, int *timeout) { + if (*timeout < 0) { + *timeout = 0; + return 0; + } + + struct pollfd fds; + struct timespec start; + struct timespec finish; + + fds.fd = sockfd; + fds.events = POLLIN; + fds.revents = 0; + + clock_gettime(CLOCK_REALTIME, &start); + int result = poll(&fds, 1, *timeout); + clock_gettime(CLOCK_REALTIME, &finish); + + if (result == -1) { + fprintf(stderr, "poll error: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + if (result == 0) { + *timeout = 0; + return 0; + } + + *timeout -= get_time_interval(start, finish); + return result; +} + +size_t recv_message(int sockfd, char *buffer, struct sockaddr_in *sender) { + socklen_t sender_len = sizeof(*sender); + bzero(buffer, HEADER_LEN + DATAGRAM_LEN); + bzero(sender, sizeof(*sender)); + size_t datagram_len = recvfrom(sockfd, buffer, IP_MAXPACKET, 0, + (struct sockaddr*)sender, &sender_len); + + if (datagram_len < 0) { + fprintf(stderr, "recvfrom error: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + return datagram_len; +} + +inline size_t min(size_t x, size_t y) { return (x +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "window.h" +#include "utils.h" + +size_t send_datagram(int sockfd, struct sockaddr_in server_address, char *buffer, size_t buffer_len) { + return sendto(sockfd, buffer, buffer_len, 0, (struct sockaddr*) &server_address, sizeof(server_address)); +} + +void send_data_request(int sockfd, struct sockaddr_in server_address, size_t pos, size_t bytes) { + char buffer[40]; + sprintf(buffer, "GET %ld %ld\n", pos, bytes); + size_t buffer_len = strlen(buffer); + if (send_datagram(sockfd, server_address, buffer, buffer_len) != buffer_len) { + fprintf(stderr, "sendto error: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } +} + +size_t recv_message(int sockfd, char *buffer, struct sockaddr_in *sender) { + socklen_t sender_len = sizeof(*sender); + bzero(buffer, HEADER_LEN + DATAGRAM_LEN); + bzero(sender, sizeof(*sender)); + size_t datagram_len = recvfrom(sockfd, buffer, IP_MAXPACKET, 0, + (struct sockaddr*)sender, &sender_len); + + if (datagram_len < 0) { + fprintf(stderr, "recvfrom error: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + return datagram_len; +} + +void request_data(int sockfd, struct sockaddr_in server_address, window_t *w, size_t bytes_writen, size_t remaining_bytes) { + int pos = w->first_pos; + for (int i = 0; i < w->size && i*DATAGRAM_LEN < remaining_bytes; i++) { + if (w->uptodate[pos] == false) { + size_t bytes_to_request = min(DATAGRAM_LEN, remaining_bytes - i*DATAGRAM_LEN); + send_data_request(sockfd, server_address, bytes_writen + i*DATAGRAM_LEN, bytes_to_request); + } + pos = (pos + 1) % w->size; + } +} + +void update_file(FILE *fd, window_t *w, size_t *bytes_writen, size_t *remaining_bytes) { + while (w->uptodate[w->first_pos] && *remaining_bytes > 0) { + // printf("Writing %ld\n", *bytes_writen); + size_t bytes_to_write = min(DATAGRAM_LEN, *remaining_bytes); + fwrite(w->ar[w->first_pos], sizeof(char), bytes_to_write, fd); + *bytes_writen += bytes_to_write; + *remaining_bytes -= bytes_to_write; + shift(w); + } +} + +size_t recv_datagram(int sockfd, char *buffer, struct sockaddr_in server_address) { + struct sockaddr_in sender; + + size_t received_bytes = recv_message(sockfd, buffer, &sender); + if (sender.sin_addr.s_addr != server_address.sin_addr.s_addr || sender.sin_port != server_address.sin_port) { + printf("Smieci!\n"); + return 0; + } + return received_bytes; +} + + +void receive_file(int sockfd, struct sockaddr_in server_address, const char *file_name, size_t remaining_bytes) { + FILE *fd = fopen(file_name, "w"); + if (!fd) { + fprintf(stderr, "fopen error: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + size_t bytes_writen = 0; + + size_t recv_pos, recv_len; + char buffer[DATAGRAM_LEN + HEADER_LEN]; + int prev_len = 0; + window_t w; + init_window(&w, WINDOW_SIZE, DATAGRAM_LEN); + + while (remaining_bytes) { + request_data(sockfd, server_address, &w, bytes_writen, remaining_bytes); + int timeout = TIMEOUT; + while (poll_socket_modify_timeout(sockfd, &timeout)) { + size_t received_bytes = recv_datagram(sockfd, buffer, server_address); + if (received_bytes == 0) continue; + sscanf(buffer, "DATA %ld %ld\n", &recv_pos, &recv_len); + if (recv_pos < bytes_writen) continue; + + int pos = (recv_pos - bytes_writen) / DATAGRAM_LEN; + pos = (pos + w.first_pos) % w.size; + if (!w.uptodate[pos]) { + for (int i = 0; i < recv_len; i++) { + w.ar[pos][i] = buffer[i + received_bytes - recv_len]; + } + w.uptodate[pos] = true; + } + update_file(fd, &w, &bytes_writen, &remaining_bytes); + } + + if (prev_len != bytes_writen) { + prev_len = bytes_writen; + printf("%.3f%%\n", 100.0 * (float)(bytes_writen) / (float)(remaining_bytes+bytes_writen)); + } + } + destroy_window(&w); + fclose(fd); +} + +int main(int argc, char *argv[]) { + if (argc != 5) { + printf("Usage:\n\t%s [server ip] [server port] [output file name] [file size]\n", argv[0]); + return -1; + } + + int sockfd = get_socket(); + struct sockaddr_in server_address; + bzero(&server_address, sizeof(server_address)); + server_address.sin_family = AF_INET; + if (!inet_pton(AF_INET, argv[1], &server_address.sin_addr)) { + fprintf(stderr, "Invalid ip address: %s\n", argv[1]); + return -1; + } + server_address.sin_port = htons(atoi(argv[2])); + if (server_address.sin_port == 0) { + fprintf(stderr, "Invalid port: %s\n", argv[2]); + return -1; + } + + size_t file_len = atoi(argv[4]); + if (file_len == 0) { + printf("File len is 0, nothing to do here.\n"); + return 0; + } + + receive_file(sockfd, server_address, argv[3], file_len); +} \ No newline at end of file diff --git a/semestr-4/sieci/pracownia3/franciszek_malinka/utils.c b/semestr-4/sieci/pracownia3/franciszek_malinka/utils.c new file mode 100644 index 0000000..4c2f449 --- /dev/null +++ b/semestr-4/sieci/pracownia3/franciszek_malinka/utils.c @@ -0,0 +1,58 @@ +/* Projekt: Transport + * Autor: Franciszek Malinka 316093 + */ + +#include "utils.h" +#include +#include +#include +#include +#include +#include +#include + +size_t min(size_t x, size_t y) { return (x +#include + +#define NS_TO_MS(X) ((long)(X) / (long)1000000) +#define S_TO_MS(X) ((long)(X) * (long)1000) + +size_t min(size_t x, size_t y); + +int get_socket(); + +long get_time_interval(struct timespec start, struct timespec finish); + +int poll_socket_modify_timeout(int sockfd, int *timeout); + +#endif \ No newline at end of file diff --git a/semestr-4/sieci/pracownia3/franciszek_malinka/window.c b/semestr-4/sieci/pracownia3/franciszek_malinka/window.c new file mode 100644 index 0000000..c8bffad --- /dev/null +++ b/semestr-4/sieci/pracownia3/franciszek_malinka/window.c @@ -0,0 +1,42 @@ +/* Projekt: Transport + * Autor: Franciszek Malinka 316093 + */ + +#include "window.h" +#include +#include + +void init_window(window_t *w, int window_size, int window_width) { + w->ar = malloc(window_size * sizeof(char *)); + for (int i = 0; i < window_size; i++) + w->ar[i] = malloc(window_width * sizeof(char)); + w->uptodate = malloc(window_size); + bzero (w->uptodate, window_size); + w->first_pos = 0; + w->size = window_size; +} + +void destroy_window(window_t *w) { + for (int i = 0; i < w->size; i++) + free(w->ar[i]); + free(w->ar); + free(w->uptodate); +} + +void shift_while_uptodate(window_t *w) { + while (w->uptodate[w->first_pos]) { + w->uptodate[w->first_pos] = false; + w->first_pos = (w->first_pos + 1) % w->size; + } +} + +void shift(window_t *w) { + w->uptodate[w->first_pos] = false; + w->first_pos = (w->first_pos + 1) % w->size; +} + +void update(window_t *w, int pos, char *buffer, size_t buf_size) { + pos = (w->first_pos + pos) % w->size; + for (int i = 0; i < buf_size; i++) w->ar[pos][i] = buffer[i]; + w->uptodate[pos] = true; +} \ No newline at end of file diff --git a/semestr-4/sieci/pracownia3/franciszek_malinka/window.h b/semestr-4/sieci/pracownia3/franciszek_malinka/window.h new file mode 100644 index 0000000..63e89cc --- /dev/null +++ b/semestr-4/sieci/pracownia3/franciszek_malinka/window.h @@ -0,0 +1,24 @@ +#ifndef WINDOW_H +#define WINDOW_H + +#include +#include + +typedef struct { + char **ar; + bool *uptodate; + int size; + int first_pos; +} window_t; + +void init_window(window_t *w, int window_size, int window_width); + +void destroy_window(window_t *w); + +void shift_while_uptodate(window_t *w); + +void shift(window_t *w); + +void update(window_t *w, int pos, char *buffer, size_t buf_size); + +#endif \ No newline at end of file diff --git a/semestr-4/sieci/pracownia3/p3.pdf b/semestr-4/sieci/pracownia3/p3.pdf new file mode 100644 index 0000000..14f1261 Binary files /dev/null and b/semestr-4/sieci/pracownia3/p3.pdf differ diff --git a/semestr-4/sieci/pracownia3/transport.c b/semestr-4/sieci/pracownia3/transport.c new file mode 100644 index 0000000..9226d69 --- /dev/null +++ b/semestr-4/sieci/pracownia3/transport.c @@ -0,0 +1,149 @@ +/* Projekt: Transport + * Autor: Franciszek Malinka 316093 + */ + +#include +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "window.h" +#include "utils.h" + +size_t send_datagram(int sockfd, struct sockaddr_in server_address, char *buffer, size_t buffer_len) { + return sendto(sockfd, buffer, buffer_len, 0, (struct sockaddr*) &server_address, sizeof(server_address)); +} + +void send_data_request(int sockfd, struct sockaddr_in server_address, size_t pos, size_t bytes) { + char buffer[40]; + sprintf(buffer, "GET %ld %ld\n", pos, bytes); + size_t buffer_len = strlen(buffer); + if (send_datagram(sockfd, server_address, buffer, buffer_len) != buffer_len) { + fprintf(stderr, "sendto error: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } +} + +size_t recv_message(int sockfd, char *buffer, struct sockaddr_in *sender) { + socklen_t sender_len = sizeof(*sender); + bzero(buffer, HEADER_LEN + DATAGRAM_LEN); + bzero(sender, sizeof(*sender)); + size_t datagram_len = recvfrom(sockfd, buffer, IP_MAXPACKET, 0, + (struct sockaddr*)sender, &sender_len); + + if (datagram_len < 0) { + fprintf(stderr, "recvfrom error: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + return datagram_len; +} + +void request_data(int sockfd, struct sockaddr_in server_address, window_t *w, size_t bytes_writen, size_t remaining_bytes) { + int pos = w->first_pos; + for (int i = 0; i < w->size && i*DATAGRAM_LEN < remaining_bytes; i++) { + if (w->uptodate[pos] == false) { + size_t bytes_to_request = min(DATAGRAM_LEN, remaining_bytes - i*DATAGRAM_LEN); + send_data_request(sockfd, server_address, bytes_writen + i*DATAGRAM_LEN, bytes_to_request); + } + pos = (pos + 1) % w->size; + } +} + +void update_file(FILE *fd, window_t *w, size_t *bytes_writen, size_t *remaining_bytes) { + while (w->uptodate[w->first_pos] && *remaining_bytes > 0) { + // printf("Writing %ld\n", *bytes_writen); + size_t bytes_to_write = min(DATAGRAM_LEN, *remaining_bytes); + fwrite(w->ar[w->first_pos], sizeof(char), bytes_to_write, fd); + *bytes_writen += bytes_to_write; + *remaining_bytes -= bytes_to_write; + shift(w); + } +} + +size_t recv_datagram(int sockfd, char *buffer, struct sockaddr_in server_address) { + struct sockaddr_in sender; + + size_t received_bytes = recv_message(sockfd, buffer, &sender); + if (sender.sin_addr.s_addr != server_address.sin_addr.s_addr || sender.sin_port != server_address.sin_port) { + printf("Smieci!\n"); + return 0; + } + return received_bytes; +} + + +void receive_file(int sockfd, struct sockaddr_in server_address, const char *file_name, size_t remaining_bytes) { + FILE *fd = fopen(file_name, "w"); + if (!fd) { + fprintf(stderr, "fopen error: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + size_t bytes_writen = 0; + + size_t recv_pos, recv_len; + char buffer[DATAGRAM_LEN + HEADER_LEN]; + int prev_len = 0; + window_t w; + init_window(&w, WINDOW_SIZE, DATAGRAM_LEN); + + while (remaining_bytes) { + request_data(sockfd, server_address, &w, bytes_writen, remaining_bytes); + int timeout = TIMEOUT; + while (poll_socket_modify_timeout(sockfd, &timeout)) { + size_t received_bytes = recv_datagram(sockfd, buffer, server_address); + if (received_bytes == 0) continue; + sscanf(buffer, "DATA %ld %ld\n", &recv_pos, &recv_len); + if (recv_pos < bytes_writen) continue; + + int pos = (recv_pos - bytes_writen) / DATAGRAM_LEN; + pos = (pos + w.first_pos) % w.size; + if (!w.uptodate[pos]) { + for (int i = 0; i < recv_len; i++) { + w.ar[pos][i] = buffer[i + received_bytes - recv_len]; + } + w.uptodate[pos] = true; + } + update_file(fd, &w, &bytes_writen, &remaining_bytes); + } + + if (prev_len != bytes_writen) { + prev_len = bytes_writen; + printf("%.3f%%\n", 100.0 * (float)(bytes_writen) / (float)(remaining_bytes+bytes_writen)); + } + } + destroy_window(&w); + fclose(fd); +} + +int main(int argc, char *argv[]) { + if (argc != 5) { + printf("Usage:\n\t%s [server ip] [server port] [output file name] [file size]\n", argv[0]); + return -1; + } + + int sockfd = get_socket(); + struct sockaddr_in server_address; + bzero(&server_address, sizeof(server_address)); + server_address.sin_family = AF_INET; + if (!inet_pton(AF_INET, argv[1], &server_address.sin_addr)) { + fprintf(stderr, "Invalid ip address: %s\n", argv[1]); + return -1; + } + server_address.sin_port = htons(atoi(argv[2])); + if (server_address.sin_port == 0) { + fprintf(stderr, "Invalid port: %s\n", argv[2]); + return -1; + } + + size_t file_len = atoi(argv[4]); + if (file_len == 0) { + printf("File len is 0, nothing to do here.\n"); + return 0; + } + + receive_file(sockfd, server_address, argv[3], file_len); +} \ No newline at end of file diff --git a/semestr-4/sieci/pracownia3/utils.c b/semestr-4/sieci/pracownia3/utils.c new file mode 100644 index 0000000..4c2f449 --- /dev/null +++ b/semestr-4/sieci/pracownia3/utils.c @@ -0,0 +1,58 @@ +/* Projekt: Transport + * Autor: Franciszek Malinka 316093 + */ + +#include "utils.h" +#include +#include +#include +#include +#include +#include +#include + +size_t min(size_t x, size_t y) { return (x +#include + +#define NS_TO_MS(X) ((long)(X) / (long)1000000) +#define S_TO_MS(X) ((long)(X) * (long)1000) + +size_t min(size_t x, size_t y); + +int get_socket(); + +long get_time_interval(struct timespec start, struct timespec finish); + +int poll_socket_modify_timeout(int sockfd, int *timeout); + +#endif \ No newline at end of file diff --git a/semestr-4/sieci/pracownia3/window.c b/semestr-4/sieci/pracownia3/window.c new file mode 100644 index 0000000..c8bffad --- /dev/null +++ b/semestr-4/sieci/pracownia3/window.c @@ -0,0 +1,42 @@ +/* Projekt: Transport + * Autor: Franciszek Malinka 316093 + */ + +#include "window.h" +#include +#include + +void init_window(window_t *w, int window_size, int window_width) { + w->ar = malloc(window_size * sizeof(char *)); + for (int i = 0; i < window_size; i++) + w->ar[i] = malloc(window_width * sizeof(char)); + w->uptodate = malloc(window_size); + bzero (w->uptodate, window_size); + w->first_pos = 0; + w->size = window_size; +} + +void destroy_window(window_t *w) { + for (int i = 0; i < w->size; i++) + free(w->ar[i]); + free(w->ar); + free(w->uptodate); +} + +void shift_while_uptodate(window_t *w) { + while (w->uptodate[w->first_pos]) { + w->uptodate[w->first_pos] = false; + w->first_pos = (w->first_pos + 1) % w->size; + } +} + +void shift(window_t *w) { + w->uptodate[w->first_pos] = false; + w->first_pos = (w->first_pos + 1) % w->size; +} + +void update(window_t *w, int pos, char *buffer, size_t buf_size) { + pos = (w->first_pos + pos) % w->size; + for (int i = 0; i < buf_size; i++) w->ar[pos][i] = buffer[i]; + w->uptodate[pos] = true; +} \ No newline at end of file diff --git a/semestr-4/sieci/pracownia3/window.h b/semestr-4/sieci/pracownia3/window.h new file mode 100644 index 0000000..63e89cc --- /dev/null +++ b/semestr-4/sieci/pracownia3/window.h @@ -0,0 +1,24 @@ +#ifndef WINDOW_H +#define WINDOW_H + +#include +#include + +typedef struct { + char **ar; + bool *uptodate; + int size; + int first_pos; +} window_t; + +void init_window(window_t *w, int window_size, int window_width); + +void destroy_window(window_t *w); + +void shift_while_uptodate(window_t *w); + +void shift(window_t *w); + +void update(window_t *w, int pos, char *buffer, size_t buf_size); + +#endif \ No newline at end of file -- cgit v1.2.3