Skip to content

Commit

Permalink
Added functionality to download and parse fractions. Also added CRC-3…
Browse files Browse the repository at this point in the history
…2 functionality in utils.h for future use
  • Loading branch information
skelly committed Sep 13, 2024
1 parent e12a322 commit 1ee9932
Show file tree
Hide file tree
Showing 8 changed files with 270 additions and 89 deletions.
2 changes: 1 addition & 1 deletion src/client/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
CC = gcc
FLAGS = -Wall -Wextra -Wshadow
SRC = main.c sock.c http.c utils.c
SRC = main.c sock.c http.c utils.c fraction.c
OUT = client

all:
Expand Down
110 changes: 110 additions & 0 deletions src/client/fraction.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#include "fraction.h"
#include <stdint.h>


// Change the return type to int to indicate success or failure
int download_fraction(int sfd, char *url, fraction_t *fraction) {
char *path = NULL;
http_res_t res;
fraction_t downloaded_fraction = {}; // Initialize to zero in case of failure

// Parse the URL to get the path
path = get_path_from_url(url);
if (!path) {
fprintf(stderr, "Invalid URL: %s\n", url);
return 1; // Return failure
}

// Perform the HTTP GET request
if (http_get(sfd, path, &res) != HTTP_SUCCESS) {
fprintf(stderr, "Failed to download: %s\n", url);
return 1; // Return failure
}

// Parse the downloaded data into a fraction
if (fraction_parse(res.data, res.size, &downloaded_fraction) != 0) {
fprintf(stderr, "Failed to parse fraction from downloaded data\n");
http_free(&res); // Free HTTP response
return 1; // Return failure
}

// If the user provided a fraction pointer, copy the result
if (fraction) {
*fraction = downloaded_fraction;
}

// Cleanup
http_free(&res);

return 0; // Return success
}

int fraction_parse(char *data, size_t size, fraction_t *fraction) {
const size_t IV_SIZE = 16; // 16 bytes for the IV
const size_t MAGIC_SIZE = sizeof(uint32_t);
const size_t INDEX_SIZE = sizeof(uint32_t);
const size_t CRC_SIZE = sizeof(uint32_t);
const size_t HEADER_SIZE = MAGIC_SIZE + INDEX_SIZE + IV_SIZE + CRC_SIZE;

// Ensure the data size is sufficient
if (size < HEADER_SIZE) {
return 1; // Failure: data size is too small
}

// Extract fields from data buffer with endianess handling
uint32_t magic, index, crc;
memcpy(&magic, data, MAGIC_SIZE);
memcpy(&index, data + MAGIC_SIZE, INDEX_SIZE);
memcpy(fraction->iv, data + MAGIC_SIZE + INDEX_SIZE, IV_SIZE);
memcpy(&crc, data + MAGIC_SIZE + INDEX_SIZE + IV_SIZE, CRC_SIZE);

// Convert from little-endian to host byte order if needed (for
// little-endian systems, this is usually not required)
magic = __bswap_32(magic);
index = __bswap_32(index);
crc = __bswap_32(crc);

// Set the extracted values in the fraction structure
fraction->magic = magic;
fraction->index = index;
fraction->crc = crc;

// Check the magic number
if (!check_magic(fraction->magic)) {
return 1; // Failure: magic number does not match
}

// Allocate memory for fraction data
size_t data_size = size - HEADER_SIZE;
fraction->data = malloc(data_size);
if (!fraction->data) {
return 1; // Failure: memory allocation error
}

// Copy the remaining data
memcpy(fraction->data, data + HEADER_SIZE, data_size);

return 0; // Success
}

int check_magic(uint32_t magic) {
return magic == MAGIC;
}

void print_fraction(fraction_t fraction) {
printf("Magic: 0x%08x\n", fraction.magic);
printf("Index: %u\n", fraction.index);
printf("CRC: 0x%08x\n", fraction.crc);
printf("IV: ");
for (size_t i = 0; i < sizeof(fraction.iv); i++) {
printf("%02x ", (unsigned char)fraction.iv[i]);
}
printf("\n");
}

void fraction_free(fraction_t *fraction) {
free(fraction->data);
fraction->magic = 0;
fraction->index = 0;
fraction->crc = 0;
}
29 changes: 29 additions & 0 deletions src/client/fraction.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#ifndef fractions_h
#define fractions_h

#include <stdint.h>
#include "http.h"
#include "utils.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <endian.h>

#define MAGIC 0xdeadbeef

typedef struct {
uint32_t magic;
uint32_t index;
char iv[16];
uint32_t crc;

char *data;
} fraction_t;

int download_fraction(int sfd, char *url, fraction_t *fraction);
int fraction_parse(char *data, size_t size, fraction_t *fraction);
int check_magic(uint32_t data);
void print_fraction(fraction_t fraction);
void fraction_free(fraction_t *fraction);
#endif
36 changes: 0 additions & 36 deletions src/client/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,42 +291,6 @@ int http_get(int sfd, const char *path, http_res_t *res) {
return err;
}

/* Perform a GET request to path and write the body to the file specified in
* f_path */
int http_download_data_to_file(int sfd, const char *path, const char *f_path) {
http_res_t res;
FILE *file;
int error;

error = http_get(sfd, path, &res);
if (error != HTTP_SUCCESS) {
return error;
}

file = fopen(f_path, "w");
if (file == NULL) {
perror("Error: Failed to open file");
http_free(&res);
return -1;
}

if (fwrite(res.data, sizeof(char), res.size, file) != res.size) {
perror("Error: Failed to write data to file");
fclose(file);
http_free(&res);
return -2;
}

if (fclose(file) != 0) {
perror("Error: Failed to close file");
http_free(&res);
return -3;
}

http_free(&res);
return 0;
}

/* Properly free a http_res_t structure */
void http_free(http_res_t *res) {
free(res->data);
Expand Down
5 changes: 2 additions & 3 deletions src/client/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <stdlib.h>
#include <string.h>
#include "sock.h"
#include "utils.h"

// error codes
#define HTTP_SUCCESS 0
Expand All @@ -13,7 +14,7 @@
#define HTTP_OOM -3
#define HTTP_HEADERS_TOO_LONG -4

#define HTTP_VERBOSE 1
#define HTTP_VERBOSE 0

typedef struct {
int status_code;
Expand All @@ -27,8 +28,6 @@ void http_free(http_res_t *res);
int http_get(int sfd, const char *path, http_res_t *res);
int http_post(int sfd,const char* path,const char *content_type, const char* parameters, http_res_t *res);

int download_to_memory(int sfd,char **links,int n_links,char **bytes_array);

long parse_http_status_code(const char *buf);
long parse_http_content_length(const char *buf);

Expand Down
70 changes: 40 additions & 30 deletions src/client/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <sys/types.h>
#include <unistd.h>

#include "fraction.h"
#include "http.h"
#include "sock.h"
#include "utils.h"
Expand All @@ -14,83 +15,92 @@ int main() {
struct addrinfo hints, *ainfo;
int sfd; // socket file descriptor
char hostname[NI_MAXHOST];
char **byte_arrays;
http_res_t http_fraction_res;
http_res_t http_post_res;
http_res_t http_fraction_res, http_post_res;

/* Setup socket and initiate connection with the server */
setup_hints(&hints);

if (h_getaddrinfo(SERVER_IP, SERVER_PORT, &hints, &ainfo) != 0) {
fprintf(stderr, "Failed to resolve server address\n");
return EXIT_FAILURE;
}

if (h_getnameinfo(ainfo, hostname, sizeof(hostname)) != 0) {
freeaddrinfo(ainfo);
fprintf(stderr, "Failed to get server hostname\n");
return EXIT_FAILURE;
}

printf("Connecting to: %s\n", hostname);
sfd = create_sock_and_conn(ainfo);
if (sfd == -1) {
fprintf(stderr, "Failed to create socket and connect\n");
return EXIT_FAILURE;
}

freeaddrinfo(ainfo); // we don't need these anymore
freeaddrinfo(ainfo); // ainfo no longer needed

/* Get the fraction links */
if (http_get(sfd, "/", &http_fraction_res) != HTTP_SUCCESS) {
goto err;
fprintf(stderr, "Failed to retrieve fraction links\n");
goto cleanup_socket;
}

// Count number of links
int num_links = count_lines(http_fraction_res.data) + 1; // +1 for the last line if not ending with \n
int num_links = count_lines(http_fraction_res.data) + 1;

// Allocate memory for fraction links
char **fraction_links = malloc(num_links * sizeof(char *));
if (fraction_links == NULL) {
fprintf(stderr, "malloc failed to allocate memory for fraction links\n");
if (!fraction_links) {
fprintf(stderr, "Failed to allocate memory for fraction links\n");
http_free(&http_fraction_res);
goto err;
goto cleanup_socket;
}

// Split the response data into lines
int lines_read =
split_fraction_links(http_fraction_res.data, fraction_links, num_links);
if (lines_read < 0) {
http_free(&http_fraction_res);
fprintf(stderr, "Failed to split fraction links\n");
free(fraction_links);
goto err;
http_free(&http_fraction_res);
goto cleanup_socket;
}

// if(download_to_memory(sfd,fraction_links,lines_read ,byte_arrays)){
// puts("Error downloading chunks");
// return EXIT_FAILURE;
// };

// Print the fraction links
// TODO: Download each link to a file
for (int i = 0; i < lines_read; i++) {
// printf("%s\n", fraction_links[i]);
free(fraction_links[i]); // Free allocated memory for each line
fraction_t *fractions = malloc(lines_read * sizeof(fraction_t));
for (int i=0; i<lines_read; i++) {
if (download_fraction(sfd, fraction_links[i], &fractions[i]) != 0) {
fprintf(stderr, "Failed to parse fraction\n");
}
print_fraction(fractions[i]);
}

/* Tell the server that we successfully downloaded the fractions */
if (http_post(sfd, "/deadbeef", "plain/text", "{'downloaded':true}", &http_post_res) != HTTP_SUCCESS) {
/* Notify the server that we successfully downloaded the fractions */
if (http_post(sfd, "/deadbeef", "plain/text", "{'downloaded':true}",
&http_post_res) != HTTP_SUCCESS) {
fprintf(stderr, "Failed to send POST request\n");
free(fraction_links);
http_free(&http_fraction_res);
http_free(&http_post_res);

free(fraction_links);

goto err;
goto cleanup_socket;
}

/* Cleanup */
http_free(&http_fraction_res);
http_free(&http_post_res);

// Free fractions and links
for (int i = 0; i < lines_read; i++) {

free(fraction_links[i]);
fraction_free(&fractions[i]);
}
free(fraction_links);
free(fractions);

close(sfd);
return EXIT_SUCCESS;

err:
cleanup_socket:
close(sfd);
return EXIT_FAILURE;
}
26 changes: 8 additions & 18 deletions src/client/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,12 @@ int split_fraction_links(char *data, char *data_arr[], int maxlines) {
return lines_read;
}


char *get_path_from_url(const char *url) {
const char *path_start = strstr(url, "://");
if (!path_start) {
perror("There was a error with the URL");
return NULL;
}

path_start += 3; // Skip past "://"

// Find the first '/' after the host part
char *path = strchr(path_start, '/');
if (!path) {
perror("No string found!");
return "";
}

return path;
void print_hex(char *str) {
while (*str) {
printf(
"%02x ",
(unsigned char)*str);
str++;
}
printf("\n");
}
Loading

0 comments on commit 1ee9932

Please sign in to comment.