Næsten virker mest af det
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@ -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 -pthread
|
||||
#GCC=gcc -O3 -pthread
|
||||
LD_FLAGS= -lpthread
|
||||
|
||||
all: cascade
|
||||
@ -11,7 +11,6 @@ csapp.o: csapp.c csapp.h
|
||||
|
||||
common.o: common.c common.h
|
||||
$(GCC) -c $< -o $@
|
||||
|
||||
cascade: cascade.c cascade.h common.o csapp.o sha256.o
|
||||
$(GCC) $< *.o -o $@ $(LD_FLAGS)
|
||||
|
||||
|
BIN
A4/src/cascade
BIN
A4/src/cascade
Binary file not shown.
237
A4/src/cascade.c
237
A4/src/cascade.c
@ -1,10 +1,12 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "./endian.h"
|
||||
@ -20,17 +22,12 @@ char tracker_port[PORT_LEN];
|
||||
char my_ip[IP_LEN];
|
||||
char my_port[PORT_LEN];
|
||||
|
||||
struct csc_file *casc_file;
|
||||
csc_block_t** queue;
|
||||
csc_peer_t* peers;
|
||||
|
||||
/*
|
||||
* Frees global resources that are malloc'ed during peer downloads.
|
||||
*/
|
||||
void free_resources()
|
||||
void free_resources(csc_file_t* casc_file)
|
||||
{
|
||||
free(queue);
|
||||
free(peers);
|
||||
free(casc_file->peers);
|
||||
csc_free_file(casc_file);
|
||||
}
|
||||
|
||||
@ -63,8 +60,9 @@ void get_file_sha(const char* sourcefile, uint8_t hash[32], int size)
|
||||
}
|
||||
|
||||
|
||||
csc_file_t* check_blocks(const char* destination, csc_file_t* casc_file_data) {
|
||||
csc_file_t* check_blocks(csc_file_t* casc_file_data) {
|
||||
casc_file_data->completed = 1;
|
||||
char* destination = casc_file_data->outputfile;
|
||||
|
||||
FILE* fp = fopen(destination, "a+w");
|
||||
if (fp == NULL)
|
||||
@ -151,81 +149,6 @@ void get_data_sha(const char* sourcedata, unsigned char* hash, uint32_t data_siz
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform all client based interactions in the P2P network for a given cascade file.
|
||||
* E.g. parse a cascade file and get all the relevent data from somewhere else on the
|
||||
* network.
|
||||
*/
|
||||
void download_only_client(char *cascade_file)
|
||||
{
|
||||
printf("Managing download only for: %s\n", cascade_file);
|
||||
if (access(cascade_file, F_OK ) != 0 )
|
||||
{
|
||||
fprintf(stderr, ">> File %s does not exist\n", cascade_file);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char output_file[strlen(cascade_file)];
|
||||
memcpy(output_file, cascade_file, strlen(cascade_file));
|
||||
char* r = strstr(cascade_file, "cascade");
|
||||
int cutoff = r - cascade_file ;
|
||||
output_file[cutoff-1] = '\0';
|
||||
printf("Downloading to: %s\n", output_file);
|
||||
|
||||
casc_file = csc_parse_file(cascade_file, output_file);
|
||||
|
||||
int uncomp_count = 0;
|
||||
queue = malloc(casc_file->blockcount * sizeof(csc_block_t*));
|
||||
for (unsigned long long i = 0;i<casc_file->blockcount;i++) {
|
||||
if ((&casc_file->blocks[i])->completed == 0) {
|
||||
queue[uncomp_count] = &casc_file->blocks[i];
|
||||
uncomp_count++;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t hash_buf[32];
|
||||
get_file_sha(cascade_file, hash_buf, 32);
|
||||
|
||||
while (!casc_file->completed) {
|
||||
int peercount = 0;
|
||||
while (peercount == 0)
|
||||
{
|
||||
peercount = get_peers_list(&peers, hash_buf);
|
||||
if (peercount == 0)
|
||||
{
|
||||
printf("No peers were found. Will try again in %d seconds\n", PEER_REQUEST_DELAY);
|
||||
fflush(stdout);
|
||||
sleep(PEER_REQUEST_DELAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Found %d peer(s)\n", peercount);
|
||||
}
|
||||
}
|
||||
|
||||
csc_peer_t peer = (peers[0]);
|
||||
// Get a good peer if one is available
|
||||
for (int i=0; i<peercount; i++)
|
||||
{
|
||||
if (peers[i].good)
|
||||
{
|
||||
peer = (peers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<uncomp_count; i++)
|
||||
{
|
||||
get_block(queue[i], peer, hash_buf, output_file);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
casc_file = check_blocks(output_file,casc_file);
|
||||
}
|
||||
|
||||
printf("File fully downloaded\n");
|
||||
free_resources();
|
||||
}
|
||||
|
||||
/*
|
||||
* Count how many times a character occurs in a string
|
||||
*/
|
||||
@ -287,7 +210,7 @@ uint8_t* hex_to_bytes(const char* string) {
|
||||
* Parses a cascade file, given the sourcepath input and destination, which may or may not exist.
|
||||
* Returns a pointer to a datastructure describing the file, or NULL if the file could not be parsed
|
||||
*/
|
||||
csc_file_t* csc_parse_file(const char* sourcefile, const char* destination)
|
||||
csc_file_t* csc_parse_file(const char* sourcefile)
|
||||
{
|
||||
FILE* fp = fopen(sourcefile, "rb");
|
||||
if (fp == 0)
|
||||
@ -314,6 +237,15 @@ csc_file_t* csc_parse_file(const char* sourcefile, const char* destination)
|
||||
}
|
||||
|
||||
csc_file_t* casc_file_data = (csc_file_t*)malloc(sizeof(csc_file_t));
|
||||
uint8_t hash_buf[32];
|
||||
get_file_sha(sourcefile, hash_buf, 32);
|
||||
memcpy(casc_file_data->cascadehash,hash_buf,32);
|
||||
|
||||
char* outputfile = malloc(strlen(sourcefile)-7);
|
||||
memcpy(outputfile, sourcefile, strlen(sourcefile)-8);
|
||||
outputfile[strlen(sourcefile)-8] = '\0';
|
||||
casc_file_data->outputfile = outputfile;
|
||||
printf("Downloading to: %s\n", casc_file_data->outputfile);
|
||||
|
||||
casc_file_data->targetsize = be64toh(*((unsigned long long*)&header[16]));
|
||||
casc_file_data->blocksize = be64toh(*((unsigned long long*)&header[24]));
|
||||
@ -365,7 +297,7 @@ csc_file_t* csc_parse_file(const char* sourcefile, const char* destination)
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return check_blocks(destination, casc_file_data);
|
||||
return check_blocks(casc_file_data);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -488,7 +420,7 @@ void get_block(csc_block_t* block, csc_peer_t peer, unsigned char* hash, char* o
|
||||
* Get a list of peers on the network from a tracker. Note that this query is doing double duty according to
|
||||
* the protocol, and by asking for a list of peers we are also enrolling on the network ourselves.
|
||||
*/
|
||||
int get_peers_list(csc_peer_t** peers, uint8_t hash[32])
|
||||
int send_tracker_request(csc_peer_t** peers, uint8_t hash[32], int command)
|
||||
{
|
||||
rio_t rio;
|
||||
uint8_t rio_buf[MAX_LINE];
|
||||
@ -501,7 +433,7 @@ int get_peers_list(csc_peer_t** peers, uint8_t hash[32])
|
||||
struct RequestHeader request_header;
|
||||
memcpy(request_header.protocol, "CASC", 4);
|
||||
request_header.version = htonl(1);
|
||||
request_header.command = htonl(1);
|
||||
request_header.command = htonl(command);
|
||||
request_header.length = htonl(BODY_SIZE);
|
||||
memcpy(rio_buf, &request_header, HEADER_SIZE);
|
||||
|
||||
@ -564,31 +496,131 @@ int get_peers_list(csc_peer_t** peers, uint8_t hash[32])
|
||||
return peercount;
|
||||
}
|
||||
|
||||
void service_block_request(char* request) {
|
||||
// decode request
|
||||
// send block, or if something goes wrong, an error code
|
||||
void service_block_request(void* arg) {
|
||||
block_request_t* request = (block_request_t*)arg;
|
||||
printf("servicing block request for %s\n",request->casc_file->outputfile);
|
||||
|
||||
char request_header[HEADER_SIZE];
|
||||
memcpy(request_header, request->request, HEADER_SIZE);
|
||||
|
||||
if (!memcmp(request_header, "CASCADE1",8)) {
|
||||
// send error
|
||||
close(request->socket);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!memcmp(request_header[8], 0, 16)) {
|
||||
// send error
|
||||
close(request->socket);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void server(csc_file_t cascade_file) {
|
||||
// accept requests and make new threads to
|
||||
// send blocks
|
||||
void server_mt(void* arg) {
|
||||
csc_file_t* casc_file = (csc_file_t*)arg;
|
||||
char rio_buf[64];
|
||||
|
||||
int socket = open_listenfd(my_port);
|
||||
struct sockaddr* peer_address = malloc(sizeof(struct sockaddr));
|
||||
int address_length;
|
||||
|
||||
while (1) {
|
||||
rio_t rio;
|
||||
int new_socket = Accept(socket, peer_address, &address_length);
|
||||
Rio_readinitb(&rio, new_socket);
|
||||
Rio_readnb(&rio, rio_buf, MAXLINE);
|
||||
|
||||
pthread_t request_handler;
|
||||
block_request_t* request = malloc(sizeof(block_request_t));
|
||||
memcpy(request->request,rio_buf,64);
|
||||
request->peer_address = peer_address;
|
||||
request->casc_file = casc_file;
|
||||
request->rio = rio;
|
||||
request->socket = new_socket;
|
||||
|
||||
pthread_create(&request_handler, NULL, service_block_request, (void*)request);
|
||||
}
|
||||
}
|
||||
|
||||
void subscribe(csc_file_t cascade_file) {
|
||||
// Send 'subscribe' request to peer
|
||||
}
|
||||
void client_mt(void* arg) {
|
||||
csc_file_t* casc_file = (csc_file_t*)arg;
|
||||
printf("Starting client for %s.\n", casc_file->outputfile);
|
||||
|
||||
|
||||
void client(csc_file_t cascade_file) {
|
||||
// Mostly just the code from download_only_client
|
||||
csc_block_t** queue = malloc(casc_file->blockcount * sizeof(csc_block_t*));
|
||||
|
||||
while (!casc_file->completed){
|
||||
while (casc_file->peercount == 0) {
|
||||
casc_file->peercount = send_tracker_request(&(casc_file->peers), casc_file->cascadehash, 1);
|
||||
if (casc_file->peercount == 0)
|
||||
{
|
||||
printf("No peers were found. Will try again in %d seconds\n", PEER_REQUEST_DELAY);
|
||||
fflush(stdout);
|
||||
sleep(PEER_REQUEST_DELAY);
|
||||
}
|
||||
}
|
||||
printf("Found %d peer(s)\n", casc_file->peercount);
|
||||
|
||||
int uncomp_count = 0;
|
||||
for (unsigned long long i = 0;i<casc_file->blockcount;i++) {
|
||||
if ((&casc_file->blocks[i])->completed == 0) {
|
||||
queue[uncomp_count] = &casc_file->blocks[i];
|
||||
uncomp_count++;
|
||||
}
|
||||
}
|
||||
|
||||
csc_peer_t peer = (casc_file->peers[0]);
|
||||
// Get a good peer if one is available
|
||||
for (int i=0; i<casc_file->peercount; i++)
|
||||
{
|
||||
if (casc_file->peers[i].good)
|
||||
{
|
||||
peer = (casc_file->peers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<uncomp_count; i++)
|
||||
{
|
||||
get_block(queue[i], peer, casc_file->cascadehash, casc_file->outputfile);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
casc_file = check_blocks(casc_file);
|
||||
|
||||
check_blocks(casc_file);
|
||||
if (!casc_file->completed) {
|
||||
send_tracker_request(&(casc_file->peers), casc_file->cascadehash,1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
free(casc_file->peers);
|
||||
free(queue);
|
||||
printf("Fully downloaded %s\n",casc_file->outputfile);
|
||||
}
|
||||
|
||||
void start_peer(char* cascade_file){
|
||||
// parse cascade file (remove from client())
|
||||
// mutex in csc_file_t struct
|
||||
printf("Managing download only for: %s\n", cascade_file);
|
||||
if (access(cascade_file, F_OK ) != 0 )
|
||||
{
|
||||
fprintf(stderr, ">> File %s does not exist\n", cascade_file);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
csc_file_t *casc_file;
|
||||
casc_file = csc_parse_file(cascade_file);
|
||||
|
||||
// start client and server on separate threads
|
||||
download_only_client(cascade_file);
|
||||
pthread_t client;
|
||||
|
||||
|
||||
// subscribe to peer
|
||||
casc_file->peercount = send_tracker_request(&(casc_file->peers), casc_file->cascadehash, 2);
|
||||
|
||||
|
||||
pthread_create(&client, NULL, client_mt, (void*)casc_file);
|
||||
pthread_join(client, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -652,6 +684,9 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
pthread_t server;
|
||||
pthread_create(&server, NULL, server_mt, (void*)casc_file);
|
||||
|
||||
for (int j=0; j<casc_count; j++)
|
||||
{
|
||||
start_peer(cascade_files[j]);
|
||||
|
@ -60,7 +60,17 @@ typedef struct csc_block {
|
||||
csc_hashdata_t hash; // Hash of this blocks bytes
|
||||
} csc_block_t;
|
||||
|
||||
typedef struct csc_peer {
|
||||
char ip[16]; // IP of a peer
|
||||
char port[8]; // Port of a peer
|
||||
uint32_t lastseen; // Timestamp of last time Tracker saw this 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_file {
|
||||
csc_peer_t* peers;
|
||||
int peercount;
|
||||
uint64_t cascadehash[32];
|
||||
uint64_t targetsize; // Size of completed data file
|
||||
uint64_t blocksize; // Size of individual blocks data is divided into
|
||||
csc_hashdata_t targethash; // Hash of complete data file
|
||||
@ -68,14 +78,17 @@ typedef struct csc_file {
|
||||
uint64_t blockcount; // Number of blocks data is divided into
|
||||
csc_block_t* blocks; // Pointer to array of all blocks
|
||||
uint8_t completed;
|
||||
pthread_mutex_t mutex; // Mutex to block when output file is accessed
|
||||
char* outputfile;
|
||||
} csc_file_t;
|
||||
|
||||
typedef struct csc_peer {
|
||||
char ip[16]; // IP of a peer
|
||||
char port[8]; // Port of a peer
|
||||
uint32_t lastseen; // Timestamp of last time Tracker saw this 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 block_request {
|
||||
char request[64];
|
||||
csc_file_t* casc_file;
|
||||
struct sockaddr* peer_address;
|
||||
rio_t rio;
|
||||
int socket;
|
||||
} block_request_t;
|
||||
|
||||
/*
|
||||
* Parses a hex-string and returns the bytes corresponding to the value
|
||||
@ -86,7 +99,7 @@ uint8_t* hex_to_bytes(const char* string);
|
||||
* Parses a cascade file, given the sourcepath input and destination, which may or may not exist.
|
||||
* Returns a pointer to a datastructure describing the file, or NULL if the file could not be parsed
|
||||
*/
|
||||
csc_file_t* csc_parse_file(const char* sourcefile, const char* destination);
|
||||
csc_file_t* csc_parse_file(const char* sourcefile);
|
||||
|
||||
/*
|
||||
* Releases the memory allocated by a file datastructure
|
||||
@ -109,7 +122,7 @@ int csc_get_peers(csc_ipport_t tracker, csc_hashdata_t cascadehash, csc_ipport_t
|
||||
*/
|
||||
int csc_download_block(csc_ipport_t client, csc_hashdata_t cascadehash, uint64_t blockno, uint64_t blocklength, void* buffer);
|
||||
|
||||
int get_peers_list(csc_peer_t** peers, uint8_t hash[32]);
|
||||
int send_tracker_request(csc_peer_t** peers, uint8_t hash[32], int command);
|
||||
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);
|
||||
|
124456
A4/src/tests/shakespeare.1kib.txt
Normal file
124456
A4/src/tests/shakespeare.1kib.txt
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user