Heck yeah 😄
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
#GCC=gcc -O3 -g -Wall -Wextra -pedantic -std=gnu11
|
||||
GCC=gcc -O3
|
||||
GCC=gcc -O3 -g -Wall -Wextra -pedantic -std=gnu11
|
||||
#GCC=gcc -O3
|
||||
LD_FLAGS= -lpthread
|
||||
|
||||
all: cascade
|
||||
|
BIN
A3/src/cascade
BIN
A3/src/cascade
Binary file not shown.
167
A3/src/cascade.c
167
A3/src/cascade.c
@ -40,7 +40,7 @@ void free_resources()
|
||||
* a normal size for the hash would be given by the global variable
|
||||
* 'SHA256_HASH_SIZE', that has been defined in sha256.h
|
||||
*/
|
||||
unsigned char* get_file_sha(const char* sourcefile, uint8_t hash[32], int size)
|
||||
void get_file_sha(const char* sourcefile, uint8_t hash[32], int size)
|
||||
{
|
||||
int casc_file_size;
|
||||
|
||||
@ -48,7 +48,7 @@ unsigned char* get_file_sha(const char* sourcefile, uint8_t hash[32], int size)
|
||||
if (fp == 0)
|
||||
{
|
||||
printf("Failed to open source: %s\n", sourcefile);
|
||||
return NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
fseek(fp, 0L, SEEK_END);
|
||||
@ -62,19 +62,86 @@ unsigned char* get_file_sha(const char* sourcefile, uint8_t hash[32], int size)
|
||||
get_data_sha(buffer, hash, casc_file_size, size);
|
||||
}
|
||||
|
||||
|
||||
csc_file_t* check_blocks(const char* destination, csc_file_t* casc_file_data) {
|
||||
casc_file_data->completed = 1;
|
||||
|
||||
FILE* fp = fopen(destination, "a+w");
|
||||
if (fp == NULL)
|
||||
{
|
||||
printf("Failed to open destination file %s\n", destination);
|
||||
csc_free_file(casc_file_data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* buffer = malloc(casc_file_data->blocksize);
|
||||
if (buffer == NULL)
|
||||
{
|
||||
printf("No block buffer asigned: %ld\n", casc_file_data->blocksize);
|
||||
csc_free_file(casc_file_data);
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SHA256_CTX shactx;
|
||||
for(unsigned long long i = 0; i < casc_file_data->blockcount; i++)
|
||||
{
|
||||
uint8_t* shabuffer = malloc(sizeof(uint8_t) * SHA256_HASH_SIZE);
|
||||
unsigned long long size = casc_file_data->blocks[i].length;
|
||||
if (fread(buffer, size, 1, fp) != 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
sha256_init(&shactx);
|
||||
sha256_update(&shactx, buffer, size);
|
||||
sha256_final(&shactx, shabuffer);
|
||||
|
||||
if (memcmp((&(&casc_file_data->blocks[i])->hash)->x, shabuffer, 32) == 0) {
|
||||
(&casc_file_data->blocks[i])->completed = 1;
|
||||
} else {
|
||||
(&casc_file_data->blocks[i])->completed = 0;
|
||||
casc_file_data->completed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (casc_file_data->completed) {
|
||||
rewind(fp);
|
||||
buffer = malloc(casc_file_data->targetsize);
|
||||
uint8_t* shabuffer = malloc(sizeof(uint8_t) * SHA256_HASH_SIZE);
|
||||
fread(buffer, casc_file_data->targetsize, 1, fp);
|
||||
|
||||
sha256_init(&shactx);
|
||||
sha256_update(&shactx, buffer, casc_file_data->targetsize);
|
||||
sha256_final(&shactx, shabuffer);
|
||||
|
||||
if (!(memcmp((&casc_file_data->targethash)->x, shabuffer, 32) == 0)) {
|
||||
casc_file_data->completed = 0;
|
||||
for (unsigned long long i = 0;i < casc_file_data->blockcount;i++) {
|
||||
(&casc_file_data->blocks[i])->completed = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return casc_file_data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets a sha256 hash of specified data, sourcedata. The hash itself is
|
||||
* placed into the given variable 'hash'. Any size can be created, but a
|
||||
* a normal size for the hash would be given by the global variable
|
||||
* 'SHA256_HASH_SIZE', that has been defined in sha256.h
|
||||
*/
|
||||
void get_data_sha(const char* sourcedata, char* hash, uint32_t data_size, int hash_size)
|
||||
void get_data_sha(const char* sourcedata, unsigned char* hash, uint32_t data_size, int hash_size)
|
||||
{
|
||||
SHA256_CTX shactx;
|
||||
unsigned char shabuffer[hash_size];
|
||||
uint8_t* shabuffer = malloc(sizeof(uint8_t) * hash_size);
|
||||
sha256_init(&shactx);
|
||||
sha256_update(&shactx, sourcedata, data_size);
|
||||
sha256_final(&shactx, &shabuffer);
|
||||
sha256_final(&shactx, shabuffer);
|
||||
|
||||
for (int i=0; i<hash_size; i++)
|
||||
{
|
||||
@ -117,6 +184,7 @@ void download_only_peer(char *cascade_file)
|
||||
uint8_t hash_buf[32];
|
||||
get_file_sha(cascade_file, hash_buf, 32);
|
||||
|
||||
while (!casc_file->completed) {
|
||||
int peercount = 0;
|
||||
while (peercount == 0)
|
||||
{
|
||||
@ -147,10 +215,12 @@ void download_only_peer(char *cascade_file)
|
||||
{
|
||||
get_block(queue[i], peer, hash_buf, output_file);
|
||||
}
|
||||
// TODO test if everything is all right
|
||||
|
||||
printf("\n");
|
||||
casc_file = check_blocks(output_file,casc_file);
|
||||
}
|
||||
|
||||
printf("File fully downloaded\n");
|
||||
free_resources();
|
||||
}
|
||||
|
||||
@ -159,7 +229,7 @@ void download_only_peer(char *cascade_file)
|
||||
*/
|
||||
int count_occurences(char string[], char c)
|
||||
{
|
||||
int i=0;
|
||||
size_t i=0;
|
||||
int count=0;
|
||||
for(i=0; i<strlen(string); i++)
|
||||
{
|
||||
@ -205,7 +275,6 @@ uint8_t* hex_to_bytes(const char* string) {
|
||||
}
|
||||
|
||||
data[(index/2)] += value << (((index + 1) % 2) * 4);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
@ -251,12 +320,15 @@ csc_file_t* csc_parse_file(const char* sourcefile, const char* destination)
|
||||
x[i] = (uint8_t)(*((unsigned long long*)&header[32+i]));
|
||||
}
|
||||
|
||||
csc_hashdata_t* hash = {x};
|
||||
csc_hashdata_t* hash = malloc(sizeof(csc_hashdata_t));
|
||||
memcpy(hash->x,x,SHA256_HASH_SIZE);
|
||||
|
||||
casc_file_data->targethash = *hash;
|
||||
casc_file_data->blockcount = 1 + floor(
|
||||
(casc_file_data->targetsize - 1.0)/casc_file_data->blocksize
|
||||
);
|
||||
casc_file_data->trailblocksize = casc_file_data->targetsize - ((casc_file_data->blockcount - 1) * casc_file_data->blocksize);
|
||||
casc_file_data->completed = 0;
|
||||
|
||||
csc_block_t* block_list = malloc(
|
||||
sizeof(csc_block_t) * casc_file_data->blockcount
|
||||
@ -282,52 +354,14 @@ csc_file_t* csc_parse_file(const char* sourcefile, const char* destination)
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
csc_hashdata_t* hash = {block_x};
|
||||
csc_hashdata_t* hash = malloc(sizeof(csc_hashdata_t));
|
||||
memcpy(hash->x,block_x,SHA256_HASH_SIZE);
|
||||
block->hash = *hash;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
fp = fopen(destination, "a+w");
|
||||
if (fp == NULL)
|
||||
{
|
||||
printf("Failed to open destination file %s\n", destination);
|
||||
csc_free_file(casc_file_data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* buffer = malloc(casc_file_data->blocksize);
|
||||
if (buffer == NULL)
|
||||
{
|
||||
printf("No block buffer asigned: %d\n", casc_file_data->blocksize);
|
||||
csc_free_file(casc_file_data);
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SHA256_CTX shactx;
|
||||
for(unsigned long long i = 0; i < casc_file_data->blockcount; i++)
|
||||
{
|
||||
uint8_t shabuffer[SHA256_HASH_SIZE];
|
||||
unsigned long long size = casc_file_data->blocks[i].length;
|
||||
if (fread(buffer, size, 1, fp) != 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
sha256_init(&shactx);
|
||||
sha256_update(&shactx, buffer, size);
|
||||
sha256_final(&shactx, &shabuffer);
|
||||
|
||||
if (memcmp((&(&casc_file_data->blocks[i])->hash)->x, shabuffer, 32) == 0) {
|
||||
(&casc_file_data->blocks[i])->completed = 1;
|
||||
} else {
|
||||
(&casc_file_data->blocks[i])->completed = 0;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
return casc_file_data;
|
||||
return check_blocks(destination, casc_file_data);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -340,12 +374,12 @@ void csc_free_file(csc_file_t* file)
|
||||
free(file);
|
||||
}
|
||||
|
||||
size_t readbytes(int sock, void* buffer, size_t count)
|
||||
size_t readbytes(int sock, uint8_t* buffer, size_t count)
|
||||
{
|
||||
size_t remaining = count;
|
||||
while(remaining > 0)
|
||||
{
|
||||
size_t read = recv(sock, buffer, remaining, NULL);
|
||||
size_t read = recv(sock, buffer, remaining, 0);
|
||||
if (read == 0)
|
||||
return 0;
|
||||
buffer += read;
|
||||
@ -361,7 +395,7 @@ size_t readbytes(int sock, void* buffer, size_t count)
|
||||
*/
|
||||
void get_block(csc_block_t* block, csc_peer_t peer, unsigned char* hash, char* output_file)
|
||||
{
|
||||
printf("Attempting to get block %d from %s:%s for %s\n", block->index, peer.ip, peer.port, output_file);
|
||||
printf("Attempting to get block %ld from %s:%s for %s\n", block->index, peer.ip, peer.port, output_file);
|
||||
|
||||
int buffer_size;
|
||||
if (block->length + PEER_RESPONSE_HEADER_SIZE > MAX_LINE) {
|
||||
@ -396,7 +430,7 @@ void get_block(csc_block_t* block, csc_peer_t peer, unsigned char* hash, char* o
|
||||
if (msglen == 0)
|
||||
{
|
||||
Close(peer_socket);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply_header[0] != 0)
|
||||
@ -406,27 +440,27 @@ void get_block(csc_block_t* block, csc_peer_t peer, unsigned char* hash, char* o
|
||||
{
|
||||
printf("Tracker error %d and out-of-memory reading error\n", reply_header[0]);
|
||||
Close(peer_socket);
|
||||
return NULL;
|
||||
return;
|
||||
}
|
||||
memset(error_buf, 0, msglen + 1);
|
||||
memcpy(error_buf, &rio_buf[PEER_RESPONSE_HEADER_SIZE], msglen);
|
||||
printf("Peer gave error: %d - %s\n", reply_header[0], error_buf);
|
||||
free(error_buf);
|
||||
Close(peer_socket);
|
||||
return NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t shabuffer[SHA256_HASH_SIZE];
|
||||
uint8_t* shabuffer = malloc(sizeof(uint8_t) * SHA256_HASH_SIZE);
|
||||
|
||||
SHA256_CTX shactx;
|
||||
sha256_init(&shactx);
|
||||
sha256_update(&shactx, &rio_buf[PEER_RESPONSE_HEADER_SIZE], msglen);
|
||||
sha256_final(&shactx, &shabuffer);
|
||||
sha256_final(&shactx, shabuffer);
|
||||
|
||||
if (memcmp(shabuffer, (&block->hash)->x, SHA256_HASH_SIZE) != 0) {
|
||||
printf("Not the same hash\n");
|
||||
Close(peer_socket);
|
||||
return NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
FILE* fp = fopen(output_file, "rb+");
|
||||
@ -438,9 +472,9 @@ void get_block(csc_block_t* block, csc_peer_t peer, unsigned char* hash, char* o
|
||||
}
|
||||
|
||||
fseek(fp, block->offset, SEEK_SET);
|
||||
fputs(&rio_buf[0,PEER_RESPONSE_HEADER_SIZE],fp);
|
||||
fwrite(&rio_buf[PEER_RESPONSE_HEADER_SIZE],msglen,1,fp);
|
||||
|
||||
printf("Got block %d. Wrote from %d to %d\n", block->index, block->offset, block->offset+msglen-1);
|
||||
printf("Got block %ld. Wrote from %ld to %ld\n", block->index, block->offset, block->offset+msglen-1);
|
||||
Close(peer_socket);
|
||||
fclose(fp);
|
||||
}
|
||||
@ -461,7 +495,7 @@ int get_peers_list(csc_peer_t** peers, uint8_t hash[32])
|
||||
Rio_readinitb(&rio, tracker_socket);
|
||||
|
||||
struct RequestHeader request_header;
|
||||
strncpy(request_header.protocol, "CASC", 4);
|
||||
memcpy(request_header.protocol, "CASC", 4);
|
||||
request_header.version = htonl(1);
|
||||
request_header.command = htonl(1);
|
||||
request_header.length = htonl(BODY_SIZE);
|
||||
@ -495,21 +529,21 @@ int get_peers_list(csc_peer_t** peers, uint8_t hash[32])
|
||||
{
|
||||
printf("Tracker error %d and out-of-memory reading error\n", reply_header[0]);
|
||||
Close(tracker_socket);
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
memset(error_buf, 0, msglen + 1);
|
||||
memcpy(error_buf, &rio_buf[REPLY_HEADER_SIZE], msglen); // Fixed by Rune
|
||||
printf("Tracker gave error: %d - %s\n", reply_header[0], error_buf);
|
||||
free(error_buf);
|
||||
Close(tracker_socket);
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (msglen % 12 != 0)
|
||||
{
|
||||
printf("LIST response from tracker was length %llu but should be evenly divisible by 12\n", msglen);
|
||||
printf("LIST response from tracker was length %u but should be evenly divisible by 12\n", msglen);
|
||||
Close(tracker_socket);
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
int peercount = msglen/12;
|
||||
*peers = malloc(peercount * sizeof(csc_peer_t));
|
||||
@ -517,7 +551,6 @@ int get_peers_list(csc_peer_t** peers, uint8_t hash[32])
|
||||
for (int i = 0;i<peercount;i++) {
|
||||
csc_peer_t peer;
|
||||
uint8_t* peer_data = &rio_buf[REPLY_HEADER_SIZE + 12*i];
|
||||
struct in_addr ip = {};
|
||||
sprintf(peer.ip, "%u.%u.%u.%u", peer_data[0], peer_data[1], peer_data[2], peer_data[3]);
|
||||
sprintf(peer.port, "%u", be16toh(*((uint16_t*)&peer_data[4])));
|
||||
|
||||
|
@ -67,6 +67,7 @@ typedef struct csc_file {
|
||||
uint64_t trailblocksize; // Size of last block. Will differ from standard block size if data does not evenly divide amoungst blocks
|
||||
uint64_t blockcount; // Number of blocks data is divided into
|
||||
csc_block_t* blocks; // Pointer to array of all blocks
|
||||
uint8_t completed;
|
||||
} csc_file_t;
|
||||
|
||||
typedef struct csc_peer {
|
||||
@ -76,9 +77,6 @@ typedef struct csc_peer {
|
||||
uint8_t good; // Flag for if this is 'Good' peer. e.g. Always provides valid responses according to protocol
|
||||
} csc_peer_t;
|
||||
|
||||
typedef struct csc_server {
|
||||
} csc_server_t;
|
||||
|
||||
/*
|
||||
* Parses a hex-string and returns the bytes corresponding to the value
|
||||
*/
|
||||
@ -114,4 +112,6 @@ int csc_download_block(csc_ipport_t client, csc_hashdata_t cascadehash, uint64_t
|
||||
int get_peers_list(csc_peer_t** peers, uint8_t hash[32]);
|
||||
void get_block(csc_block_t* block, csc_peer_t peer, unsigned char* hash, char* output_file);
|
||||
|
||||
void get_data_sha(const char* sourcedata, unsigned char* hash, uint32_t data_size, int hash_size);
|
||||
|
||||
#endif
|
||||
|
@ -124454,4 +124454,3 @@ End of this Etext of The Complete Works of William Shakespeare
|
||||
|
||||
|
||||
|
||||
Yネ3<EFBFBD>
|
Reference in New Issue
Block a user