Skip to content

Commit

Permalink
Merge pull request #26 from lil-skelly:crc-check
Browse files Browse the repository at this point in the history
Implemented fraction verification via CRC-32
  • Loading branch information
lil-skelly authored Sep 19, 2024
2 parents d4c7a41 + 8dd9698 commit 7fa97aa
Show file tree
Hide file tree
Showing 9 changed files with 244 additions and 146 deletions.
Binary file added client/client
Binary file not shown.
3 changes: 1 addition & 2 deletions client/include/crc32.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#include <stdint.h>
#include <stdlib.h>

#include "fraction.h"
extern const uint32_t crc32_tab[];
/*
* A function that calculates the CRC-32 based on the table above is
Expand All @@ -12,5 +12,4 @@ extern const uint32_t crc32_tab[];
* in sys/libkern.h, where it can be inlined.
*/
uint32_t crc32(const void *buf, size_t size);

#endif // CRC32_H
7 changes: 5 additions & 2 deletions client/include/fraction.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,18 @@ typedef struct {
uint32_t magic;
uint32_t index;
char iv[16];
uint32_t crc;

uint32_t crc;

size_t data_size;
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 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);
int compare_fractions(const void* a, const void* b);
int check_fractions(fraction_t *fraction, size_t size);
#endif
2 changes: 2 additions & 0 deletions client/src/crc32.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "../include/crc32.h"
#include "../include/fraction.h"

const uint32_t crc32_tab[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
Expand Down Expand Up @@ -54,3 +55,4 @@ uint32_t crc32(const void *buf, size_t size) {
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
return crc ^ ~0U;
}

112 changes: 74 additions & 38 deletions client/src/fraction.c
Original file line number Diff line number Diff line change
@@ -1,54 +1,54 @@
#include "../include/fraction.h"
#include <stdint.h>
#include "../include/crc32.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
fraction_t downloaded_fraction = {};

// 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
return 1;
}

// 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
return 1;
}

// Parse the downloaded data into a fraction
if (fraction_parse(res.data, res.size, &downloaded_fraction) != 0) {
http_free(&res); // Free HTTP response
return 1; // Return failure
http_free(&res);
return 1;
}

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


// Cleanup
http_free(&res);

return 0; // Return success
return 0;
}

int fraction_parse(char *data, size_t size, fraction_t *fraction) {
const size_t UINT32_SIZE = sizeof(uint32_t);
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 MAGIC_SIZE = UINT32_SIZE;
const size_t INDEX_SIZE = UINT32_SIZE;
const size_t CRC_SIZE = UINT32_SIZE;
const size_t HEADER_SIZE = MAGIC_SIZE + INDEX_SIZE + IV_SIZE + CRC_SIZE;
size_t data_size;

// Ensure the data size is sufficient
if (size < HEADER_SIZE) {
return 1; // Failure: data size is too small
}
fprintf(stderr, "Insufficient size: %lu\n", size);
return 1;

}

// Extract fields from data buffer with endianess handling
uint32_t magic, index, crc;
Expand All @@ -57,33 +57,27 @@ int fraction_parse(char *data, size_t size, fraction_t *fraction) {
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
if (!check_magic(magic)) {
fprintf(stderr, "Wrong magic number: %02x\n", magic);
return 1;
}

// Allocate memory for fraction data
size_t data_size = size - HEADER_SIZE;
data_size = size - HEADER_SIZE;
fraction->data = malloc(data_size);
if (!fraction->data) {
return 1; // Failure: memory allocation error
fprintf(stderr, "Failed to allocate data for fraction\n");
return 1;
}

// Copy the remaining data
// Set the extracted values in the fraction structure
fraction->magic = magic;
fraction->index = index;
fraction->crc = crc;
fraction->data_size = data_size;
memcpy(fraction->data, data + HEADER_SIZE, data_size);

return 0; // Success
return 0;
}

int check_magic(uint32_t magic) {
Expand All @@ -101,12 +95,52 @@ int compare_fractions(const void *a, const void *b) {
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\n");
printf("\n");
printf("CRC-32: 0x%08x\n", fraction.crc);
printf("Data size: %lu\n\n", fraction.data_size);
}

int calc_crc(fraction_t *frac){
uint8_t buffer[sizeof(frac->magic) + sizeof(frac->index) + sizeof(frac->iv) + frac->data_size];
size_t offset = 0;

memcpy(buffer + offset, &frac->magic, sizeof(frac->magic));
offset += sizeof(frac->magic);

memcpy(buffer + offset, &frac->index, sizeof(frac->index));
offset += sizeof(frac->index);

memcpy(buffer + offset, frac->iv, sizeof(frac->iv));
offset += sizeof(frac->iv);

memcpy(buffer + offset, frac->data, frac->data_size);
offset += frac->data_size;

uint32_t calculated_crc = crc32(buffer, offset);

if (calculated_crc != frac->crc) {
printf("Checksum incorrect\n");
printf("Checksum generated: %08X\n", calculated_crc);
printf("Checksum from fraction: %08X\n\n", frac->crc);
}

return calculated_crc == frac->crc;
}

int check_fractions(fraction_t *fraction, size_t size){
int res = 0;
for(size_t i = 0; i < size; i++){
if (!calc_crc(&fraction[i])) {
fprintf(stderr, "Failed to validate integrity of fraction:\n");
print_fraction(fraction[i]);
res += 1;
}
}
return res;
}

void fraction_free(fraction_t *fraction) {
Expand All @@ -115,3 +149,5 @@ void fraction_free(fraction_t *fraction) {
fraction->index = 0;
fraction->crc = 0;
}


105 changes: 65 additions & 40 deletions client/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,103 +7,128 @@
#include "../include/sock.h"
#include "../include/utils.h"

/* Networking constants */
#define SERVER_IP "127.0.0.1"
#define SERVER_PORT "8000"

/* Helper functions to assist with cleanup, I hate cleanup */
static void cleanup_char_array(char **array, int n_elem) {
for (int i = 0; i < n_elem; i++) {
free(array[i]);
}
free(array);
}

static void cleanup_fraction_array(fraction_t *array, int n_elem) {
for (int i = 0; i < n_elem; i++) {
fraction_free(&array[i]);
}
free(array);
}

int main(void) {
struct addrinfo hints, *ainfo;
int sfd; // socket file descriptor
int sfd = -1; // to be extra professional
http_res_t http_fraction_res, http_post_res;
char **fraction_links = NULL;
fraction_t *fractions = NULL;

/* 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;
}


printf("Connecting to: %s:%s\n", SERVER_IP, SERVER_PORT);
sfd = create_sock_and_conn(ainfo);
freeaddrinfo(ainfo);
if (sfd == -1) {
fprintf(stderr, "Failed to create socket and connect\n");
return EXIT_FAILURE;
}
freeaddrinfo(ainfo); // ainfo no longer needed

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

// Count number of links
int num_links = count_lines(http_fraction_res.data) + 1;

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

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

// Storing the fractions in a array
fraction_t *fractions = malloc(lines_read * sizeof(fraction_t));
if (fractions == NULL) {
fprintf(stderr, "Failed to malloc memory for fractions\n");

fractions = malloc(lines_read * sizeof(fraction_t));
if (!fractions) {
fprintf(stderr, "Failed to allocate memory for fractions\n");
cleanup_char_array(fraction_links, num_links);
http_free(&http_fraction_res);
http_free(&http_post_res);
goto cleanup;
}

for (int i=0; i<lines_read; i++) {
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");
fprintf(stderr, "Failed to download fraction\n");
}
}

// Sort the fractions based on index
puts("Downloaded fractions");
qsort(fractions, lines_read, sizeof(fraction_t), compare_fractions);
for (int i = 0; i < lines_read; i++) {
print_fraction(fractions[i]);

if (check_fractions(fractions, lines_read)) { // if this works, s0s4 and skelly is to blame!
fprintf(stderr, "Fractions check failed\n");
cleanup_char_array(fraction_links, num_links);
cleanup_fraction_array(fractions, lines_read);
http_free(&http_fraction_res);
http_free(&http_post_res);
goto cleanup;
}
puts("Verified fractions");

/* 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);
cleanup_char_array(fraction_links, num_links);
http_free(&http_fraction_res);
http_free(&http_post_res);
goto cleanup_socket;
goto cleanup;
}

/* 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);
cleanup_char_array(fraction_links, num_links);
cleanup_fraction_array(fractions, lines_read);

close(sfd);
return EXIT_SUCCESS;

cleanup_socket:
close(sfd);
/* There's nothing to see here, move on*/
cleanup: // we accept NO comments on this. have a !nice day
if (sfd != -1) {
close(sfd);
}
if (fraction_links) {
cleanup_char_array(fraction_links, num_links);
}
if (fractions) {
cleanup_fraction_array(fractions, num_links);
}
if (http_fraction_res.data) {
http_free(&http_fraction_res);
}
if (http_post_res.data) {
http_free(&http_post_res);
}
return EXIT_FAILURE;
}
Loading

0 comments on commit 7fa97aa

Please sign in to comment.