Commit 2e3b123e authored by xpetrak2's avatar xpetrak2
Browse files

Merge request problems resolved

parent 2c541eb3
...@@ -56,13 +56,15 @@ int main(void) ...@@ -56,13 +56,15 @@ int main(void)
global_state_t global_state; global_state_t global_state;
struct evconnlistener *listener; struct evconnlistener *listener;
struct event *sigint_event; struct event *sigint_event;
time_t t; struct event *sigterm_event;
srand((unsigned) time(&t)); /* TODO: use randombytes (from libsodium?) for the seed of randomness */
srand((unsigned) time(NULL));
/* initialize all global_state variables */ /* initialize all global_state variables */
global_state.event_loop = NULL; global_state.event_loop = NULL;
if (setup_paths(&global_state.filepaths)) { if (setup_paths(&global_state.filepaths)) {
log_error("Initializing paths to needed files/dirs");
return 1; return 1;
} }
...@@ -70,13 +72,12 @@ int main(void) ...@@ -70,13 +72,12 @@ int main(void)
linkedlist_init(&global_state.neighbours); linkedlist_init(&global_state.neighbours);
linkedlist_init(&global_state.peers); linkedlist_init(&global_state.peers);
if (fetch_peers(global_state.filepaths.peers, &global_state.peers)) { fetch_peers(global_state.filepaths.peers, &global_state.peers);
return 2;
}
/* setup everything needed for TCP listening */ /* setup everything needed for TCP listening */
if (listen_init(&listener, &global_state) != 0) { if (listen_init(&listener, &global_state) != 0) {
return 3; log_error("Initialization of TCP listening");
return 2;
} }
/* register SIGINT event to its callback */ /* register SIGINT event to its callback */
...@@ -85,8 +86,18 @@ int main(void) ...@@ -85,8 +86,18 @@ int main(void)
signal_cb, signal_cb,
&global_state); &global_state);
if (!sigint_event || event_add(sigint_event, NULL) < 0) { if (!sigint_event || event_add(sigint_event, NULL) < 0) {
log_error("main - couldn't create or add SIGINT event"); log_error("Creating or adding SIGINT event");
return 4; return 3;
}
/* register SIGTERM event too */
sigterm_event = evsignal_new(global_state.event_loop,
SIGTERM,
signal_cb,
&global_state);
if (!sigterm_event || event_add(sigterm_event, NULL) < 0) {
log_error("Creating or adding SIGTERM event");
return 3;
} }
/* setup a function that actively checks the number of neighbours */ /* setup a function that actively checks the number of neighbours */
...@@ -99,8 +110,8 @@ int main(void) ...@@ -99,8 +110,8 @@ int main(void)
conns_cb, conns_cb,
&global_state); &global_state);
if (!conns_event || event_add(conns_event, &conns_interval) < 0) { if (!conns_event || event_add(conns_event, &conns_interval) < 0) {
log_error("main - couldn't create or add conns_event"); log_error("Creating or adding Connections event");
return 4; return 3;
} }
/* initiate joining the coincer network */ /* initiate joining the coincer network */
...@@ -119,6 +130,7 @@ int main(void) ...@@ -119,6 +130,7 @@ int main(void)
evconnlistener_free(listener); evconnlistener_free(listener);
event_free(sigint_event); event_free(sigint_event);
event_free(sigterm_event);
event_free(conns_event); event_free(conns_event);
event_base_free(global_state.event_loop); event_base_free(global_state.event_loop);
......
...@@ -38,7 +38,7 @@ static int set_homedir(char **homedir) ...@@ -38,7 +38,7 @@ static int set_homedir(char **homedir)
{ {
*homedir = getenv("HOME"); *homedir = getenv("HOME");
if (*homedir == NULL || *homedir[0] == '\0') { if (*homedir == NULL || *homedir[0] == '\0') {
log_error("set_homedir - cannot find home directory"); log_error("Can not find home directory");
return 1; return 1;
} }
return 0; return 0;
...@@ -70,7 +70,7 @@ static int set_directories(char **config_dir, char **data_dir) ...@@ -70,7 +70,7 @@ static int set_directories(char **config_dir, char **data_dir)
sizeof("/.config/" PACKAGE_NAME sizeof("/.config/" PACKAGE_NAME
"/")); "/"));
if (*config_dir == NULL) { if (*config_dir == NULL) {
log_error("set_directories - setting config_dir"); log_error("Setting configdir");
return 1; return 1;
} }
strcpy(*config_dir, homedir); strcpy(*config_dir, homedir);
...@@ -80,7 +80,7 @@ static int set_directories(char **config_dir, char **data_dir) ...@@ -80,7 +80,7 @@ static int set_directories(char **config_dir, char **data_dir)
*config_dir = (char *) malloc(tmpsize + *config_dir = (char *) malloc(tmpsize +
sizeof("/" PACKAGE_NAME "/")); sizeof("/" PACKAGE_NAME "/"));
if (*config_dir == NULL) { if (*config_dir == NULL) {
log_error("set_directories - setting config_dir"); log_error("Setting configdir");
return 1; return 1;
} }
strcpy(*config_dir, tmpchar); strcpy(*config_dir, tmpchar);
...@@ -99,7 +99,7 @@ static int set_directories(char **config_dir, char **data_dir) ...@@ -99,7 +99,7 @@ static int set_directories(char **config_dir, char **data_dir)
sizeof("/.local/share/" PACKAGE_NAME sizeof("/.local/share/" PACKAGE_NAME
"/")); "/"));
if (*data_dir == NULL) { if (*data_dir == NULL) {
log_error("set_directories - setting data_dir"); log_error("Setting datadir");
free(config_dir); free(config_dir);
return 1; return 1;
} }
...@@ -110,7 +110,7 @@ static int set_directories(char **config_dir, char **data_dir) ...@@ -110,7 +110,7 @@ static int set_directories(char **config_dir, char **data_dir)
*data_dir = (char *) malloc(tmpsize + *data_dir = (char *) malloc(tmpsize +
sizeof("/" PACKAGE_NAME "/")); sizeof("/" PACKAGE_NAME "/"));
if (*data_dir == NULL) { if (*data_dir == NULL) {
log_error("set_directories - setting data_dir"); log_error("Setting datadir");
free(config_dir); free(config_dir);
return 1; return 1;
} }
...@@ -139,16 +139,15 @@ static int create_dirs(const char *config_dir, const char *data_dir) ...@@ -139,16 +139,15 @@ static int create_dirs(const char *config_dir, const char *data_dir)
if (errno == ENOENT) { if (errno == ENOENT) {
/* create */ /* create */
if (mkdir(config_dir, S_IRWXU)) { if (mkdir(config_dir, S_IRWXU)) {
log_error("create_dirs - could not create " log_error("Could not create configuration "
"configuration directory %s", "directory %s", config_dir);
config_dir);
return 1; return 1;
} else { } else {
log_debug("create_dirs - created configuration " log_debug("create_dirs - created configuration "
"directory %s", config_dir); "directory %s", config_dir);
} }
} else { } else {
log_error("create_dirs - could not open configuration " log_error("Could not open configuration "
"directory %s", config_dir); "directory %s", config_dir);
return 1; return 1;
} }
...@@ -159,17 +158,15 @@ static int create_dirs(const char *config_dir, const char *data_dir) ...@@ -159,17 +158,15 @@ static int create_dirs(const char *config_dir, const char *data_dir)
if (errno == ENOENT) { if (errno == ENOENT) {
/* create */ /* create */
if (mkdir(data_dir, S_IRWXU)) { if (mkdir(data_dir, S_IRWXU)) {
log_error("create_dirs - could not create " log_error("Could not create "
"data directory %s", "data directory %s", data_dir);
data_dir);
return 1; return 1;
} else { } else {
log_debug("create_dirs - created data " log_debug("create_dirs - created data "
"directory %s", data_dir); "directory %s", data_dir);
} }
} else { } else {
log_error("create_dirs - could not open data " log_error("Could not open data directory %s", data_dir);
"directory %s", data_dir);
return 1; return 1;
} }
} }
......
...@@ -216,7 +216,7 @@ linkedlist_node_t *linkedlist_insert_after(linkedlist_t *root, ...@@ -216,7 +216,7 @@ linkedlist_node_t *linkedlist_insert_after(linkedlist_t *root,
new_node = (linkedlist_node_t *) malloc(sizeof(linkedlist_node_t)); new_node = (linkedlist_node_t *) malloc(sizeof(linkedlist_node_t));
if (new_node == NULL) { if (new_node == NULL) {
log_error("linkedlist_insert_after - malloc"); log_error("Inserting a new node");
return NULL; return NULL;
} }
......
...@@ -127,6 +127,54 @@ void delete_neighbour(linkedlist_t *neighbours, struct bufferevent *bev) ...@@ -127,6 +127,54 @@ void delete_neighbour(linkedlist_t *neighbours, struct bufferevent *bev)
linkedlist_delete(neighbour_node); linkedlist_delete(neighbour_node);
} }
/**
* Fetch pointers to neighbours with specific flags set, into an array
* that is being allocated in here.
*
* @param neighbours Our neighbours.
* @param output Output array of pointers to satisfying
* neighbours. If set to NULL, function just
* returns the number of them.
* @param flags Choose neighbours based on these flags.
* Fetches output with all neighbours if set to 0.
*
* @return >=0 The number of satisfying neighbours.
* @return -1 Allocation failure.
*/
int fetch_specific_neighbours(const linkedlist_t *neighbours,
neighbour_t ***output,
int flags)
{
linkedlist_node_t *current_node;
neighbour_t *current_neighbour;
size_t n = 0;
if (output != NULL) {
*output = (neighbour_t **) malloc(linkedlist_size(neighbours) *
sizeof(neighbour_t *));
if (*output == NULL) {
log_error("Fetching specific neighbours");
return -1;
}
}
current_node = linkedlist_get_first(neighbours);
while (current_node != NULL) {
current_neighbour = (neighbour_t *) current_node->data;
/* if all specified flags are being set on this neighbour */
if ((current_neighbour->flags & flags) == flags) {
if (output != NULL) {
(*output)[n++] = current_neighbour;
} else {
n++;
}
}
current_node = linkedlist_get_next(neighbours, current_node);
}
return n;
}
/** /**
* Find neighbour in neighbours based on their bufferevent. * Find neighbour in neighbours based on their bufferevent.
* *
...@@ -148,7 +196,6 @@ neighbour_t *find_neighbour(const linkedlist_t *neighbours, ...@@ -148,7 +196,6 @@ neighbour_t *find_neighbour(const linkedlist_t *neighbours,
/* bufferevents equal => neighbour found */ /* bufferevents equal => neighbour found */
if (current_data->buffer_event == bev) { if (current_data->buffer_event == bev) {
/* return node's data; struct s_neighbour */ /* return node's data; struct s_neighbour */
return current_data; return current_data;
} }
...@@ -189,3 +236,25 @@ neighbour_t *find_neighbour_by_addr(const linkedlist_t *neighbours, ...@@ -189,3 +236,25 @@ neighbour_t *find_neighbour_by_addr(const linkedlist_t *neighbours,
/* neighbour not found */ /* neighbour not found */
return NULL; return NULL;
} }
/**
* Set flags on given neighbour.
*
* @param neighbour Set flags on this neighbour.
* @param flags Set these flags on the neighbour.
*/
void set_neighbour_flags(neighbour_t *neighbour, int flags)
{
neighbour->flags |= flags;
}
/**
* Unset flags on given neighbour.
*
* @param neighbour Unset flags on this neighbour.
* @param flags Unset these flags on the neighbour.
*/
void unset_neighbour_flags(neighbour_t *neighbour, int flags)
{
neighbour->flags &= ~flags;
}
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
/* minimum number of peers we need to be connected to */ /* minimum number of peers we need to be connected to */
#define MIN_NEIGHBOURS 3 #define MIN_NEIGHBOURS 3
/* request for addresses */
#define NEIGHBOUR_ADDRS_REQ 0x01
/** Data type for the linkedlist of neighbours. */ /** Data type for the linkedlist of neighbours. */
typedef struct s_neighbour { typedef struct s_neighbour {
/** Neighbour's IPv6 address. /** Neighbour's IPv6 address.
...@@ -37,6 +40,8 @@ typedef struct s_neighbour { ...@@ -37,6 +40,8 @@ typedef struct s_neighbour {
struct bufferevent *buffer_event; struct bufferevent *buffer_event;
/** Number of failed ping attempts -- max 3, then disconnect. */ /** Number of failed ping attempts -- max 3, then disconnect. */
size_t failed_pings; size_t failed_pings;
/** A set of flags for this neighbour. */
int flags;
} neighbour_t; } neighbour_t;
neighbour_t *add_new_neighbour(linkedlist_t *neighbours, neighbour_t *add_new_neighbour(linkedlist_t *neighbours,
...@@ -47,6 +52,9 @@ void clear_neighbours(linkedlist_t *neighbours); ...@@ -47,6 +52,9 @@ void clear_neighbours(linkedlist_t *neighbours);
void delete_neighbour(linkedlist_t *neighbours, struct bufferevent *bev); void delete_neighbour(linkedlist_t *neighbours, struct bufferevent *bev);
int fetch_specific_neighbours(const linkedlist_t *neighbours,
neighbour_t ***output,
int flags);
neighbour_t *find_neighbour(const linkedlist_t *neighbours, neighbour_t *find_neighbour(const linkedlist_t *neighbours,
const struct bufferevent *bev); const struct bufferevent *bev);
...@@ -54,4 +62,7 @@ neighbour_t *find_neighbour(const linkedlist_t *neighbours, ...@@ -54,4 +62,7 @@ neighbour_t *find_neighbour(const linkedlist_t *neighbours,
neighbour_t *find_neighbour_by_addr(const linkedlist_t *neighbours, neighbour_t *find_neighbour_by_addr(const linkedlist_t *neighbours,
const struct in6_addr *ip_addr); const struct in6_addr *ip_addr);
void set_neighbour_flags(neighbour_t *neighbour, int flags);
void unset_neighbour_flags(neighbour_t *neighbour, int flags);
#endif /* NEIGHBOURS_H */ #endif /* NEIGHBOURS_H */
...@@ -48,12 +48,12 @@ static void ip_to_string(const struct in6_addr *binary_ip, char *ip) ...@@ -48,12 +48,12 @@ static void ip_to_string(const struct in6_addr *binary_ip, char *ip)
} }
/** /**
* Ask the neighbour for a list of peers. * Ask the neighbour for a list of addresses.
* *
* @param global_state Data for the event loop to work with. * @param global_state Data for the event loop to work with.
* @param neighbour The neighbour to be asked. * @param neighbour The neighbour to be asked.
*/ */
void ask_for_peers(neighbour_t *neighbour) static void ask_for_addresses(neighbour_t *neighbour)
{ {
struct bufferevent *bev; struct bufferevent *bev;
...@@ -64,6 +64,8 @@ void ask_for_peers(neighbour_t *neighbour) ...@@ -64,6 +64,8 @@ void ask_for_peers(neighbour_t *neighbour)
/* send message "peers" to the neighbour, as a request /* send message "peers" to the neighbour, as a request
* for the list of peers; 6 is the number of bytes to be transmitted */ * for the list of peers; 6 is the number of bytes to be transmitted */
evbuffer_add(bufferevent_get_output(bev), "peers", 6); evbuffer_add(bufferevent_get_output(bev), "peers", 6);
/* accept addresses only from those neighbours that we've asked */
set_neighbour_flags(neighbour, NEIGHBOUR_ADDRS_REQ);
} }
/** /**
...@@ -125,6 +127,10 @@ static void p2p_process(struct bufferevent *bev, void *ctx) ...@@ -125,6 +127,10 @@ static void p2p_process(struct bufferevent *bev, void *ctx)
/* allocate memory for the input message including '\0' */ /* allocate memory for the input message including '\0' */
message = (char *) malloc((len + 1) * sizeof(char)); message = (char *) malloc((len + 1) * sizeof(char));
if (message == NULL) {
log_error("Received message allocation");
return;
}
/* drain input buffer into data; -1 if evbuffer_remove failed */ /* drain input buffer into data; -1 if evbuffer_remove failed */
if (evbuffer_remove(input, message, len) == -1) { if (evbuffer_remove(input, message, len) == -1) {
...@@ -147,9 +153,12 @@ static void p2p_process(struct bufferevent *bev, void *ctx) ...@@ -147,9 +153,12 @@ static void p2p_process(struct bufferevent *bev, void *ctx)
/* "peers" is a request for list of addresses */ /* "peers" is a request for list of addresses */
} else if (strcmp(message, "peers") == 0) { } else if (strcmp(message, "peers") == 0) {
peers_to_str(&global_state->peers, response); peers_to_str(&global_state->peers, response);
/* list of peers */ /* list of addresses */
} else { } else {
process_peers(global_state, message); if (neighbour->flags & NEIGHBOUR_ADDRS_REQ) {
process_peers(global_state, message);
unset_neighbour_flags(neighbour, NEIGHBOUR_ADDRS_REQ);
}
} }
if (response[0] != '\0') { if (response[0] != '\0') {
...@@ -192,9 +201,7 @@ static void timeout_process(linkedlist_t *neighbours, ...@@ -192,9 +201,7 @@ static void timeout_process(linkedlist_t *neighbours,
neighbour->failed_pings++; neighbour->failed_pings++;
} else { } else {
log_info("timeout_process - 3 failed pings." log_info("%s timed out", text_ip);
" Removing %s from neighbours",
text_ip);
delete_neighbour(neighbours, neighbour->buffer_event); delete_neighbour(neighbours, neighbour->buffer_event);
} }
} }
...@@ -239,20 +246,22 @@ static void process_pending_neighbour(global_state_t *global_state, ...@@ -239,20 +246,22 @@ static void process_pending_neighbour(global_state_t *global_state,
neighbour_t *neighbour, neighbour_t *neighbour,
short events) short events)
{ {
size_t available_peers_size; int available_peers_size;
int needed_conns; int needed_conns;
neighbour_t *new_neighbour; neighbour_t *new_neighbour;
char text_ip[INET6_ADDRSTRLEN]; char text_ip[INET6_ADDRSTRLEN];
available_peers_size = fetch_available_peers(&global_state->peers, /* fetch peers with PEER_AVAILABLE flag set;
NULL); * no allocation with NULL parameter -> result always >=0 */
available_peers_size = fetch_specific_peers(&global_state->peers,
NULL,
PEER_AVAILABLE);
/* initialize text_ip */ /* initialize text_ip */
ip_to_string(&neighbour->addr, text_ip); ip_to_string(&neighbour->addr, text_ip);
/* we've successfully connected to the neighbour */ /* we've successfully connected to the neighbour */
if (events & BEV_EVENT_CONNECTED) { if (events & BEV_EVENT_CONNECTED) {
log_info("process_pending_neighbour - connecting to " log_info("%s successfully connected", text_ip);
"%s was SUCCESSFUL", text_ip);
/* we've got a new neighbour; /* we've got a new neighbour;
* we can't just delete the neighbour from pending * we can't just delete the neighbour from pending
* and add it into 'neighbours' as the delete would * and add it into 'neighbours' as the delete would
...@@ -268,14 +277,14 @@ static void process_pending_neighbour(global_state_t *global_state, ...@@ -268,14 +277,14 @@ static void process_pending_neighbour(global_state_t *global_state,
/* if we need more neighbours */ /* if we need more neighbours */
if (needed_conns > 0) { if (needed_conns > 0) {
/* and we don't have enough available */ /* and we don't have enough available */
if ((int) available_peers_size < needed_conns) { if (available_peers_size < needed_conns) {
ask_for_addresses(new_neighbour); ask_for_addresses(new_neighbour);
} }
} }
/* connecting to the neighbour was unsuccessful */ /* connecting to the neighbour was unsuccessful */
} else { } else {
log_info("process_pending_neighbour - connecting to " log_debug("process_pending_neighbour - connecting to "
"%s was NOT SUCCESSFUL", text_ip); "%s was unsuccessful", text_ip);
/* the peer is no longer a pending neighbour */ /* the peer is no longer a pending neighbour */
delete_neighbour(&global_state->pending_neighbours, delete_neighbour(&global_state->pending_neighbours,
neighbour->buffer_event); neighbour->buffer_event);
...@@ -299,12 +308,11 @@ static void process_neighbour(global_state_t *global_state, ...@@ -299,12 +308,11 @@ static void process_neighbour(global_state_t *global_state,
ip_to_string(&neighbour->addr, text_ip); ip_to_string(&neighbour->addr, text_ip);
if (events & BEV_EVENT_ERROR) { if (events & BEV_EVENT_ERROR) {
log_info("process_neighbour - error on bev: removing %s", log_info("Connection error, removing %s", text_ip);
text_ip);
delete_neighbour(&global_state->neighbours, delete_neighbour(&global_state->neighbours,
neighbour->buffer_event); neighbour->buffer_event);
} else if (events & BEV_EVENT_EOF) { } else if (events & BEV_EVENT_EOF) {
log_info("process_neighbour - %s disconnected", text_ip); log_info("%s disconnected", text_ip);
delete_neighbour(&global_state->neighbours, delete_neighbour(&global_state->neighbours,
neighbour->buffer_event); neighbour->buffer_event);
/* timeout flag on 'bev' */ /* timeout flag on 'bev' */
...@@ -357,6 +365,7 @@ static void accept_connection(struct evconnlistener *listener, ...@@ -357,6 +365,7 @@ static void accept_connection(struct evconnlistener *listener,
struct event_base *base; struct event_base *base;
struct bufferevent *bev; struct bufferevent *bev;
struct in6_addr *new_addr; struct in6_addr *new_addr;
peer_t *new_peer;
char text_ip[INET6_ADDRSTRLEN]; char text_ip[INET6_ADDRSTRLEN];
struct timeval timeout; struct timeval timeout;
...@@ -402,9 +411,12 @@ static void accept_connection(struct evconnlistener *listener, ...@@ -402,9 +411,12 @@ static void accept_connection(struct evconnlistener *listener,
return; return;
} }
log_info("accept_connection - new connection from [%s]:%d", text_ip, log_info("New connection from [%s]:%d", text_ip,
ntohs(addr_in6->sin6_port)); ntohs(addr_in6->sin6_port));
save_peer(&global_state->peers, new_addr); if ((new_peer = save_peer(&global_state->peers, new_addr))) {
/* we are now connected to this peer, hence unavailable */
unset_peer_flags(new_peer, PEER_AVAILABLE);
}
} }
/** /**
...@@ -420,8 +432,10 @@ static void accept_error_cb(struct evconnlistener *listener, ...@@ -420,8 +432,10 @@ static void accept_error_cb(struct evconnlistener *listener,
global_state_t *global_state = (struct s_global_state *) ctx; global_state_t *global_state = (struct s_global_state *) ctx;
int err = EVUTIL_SOCKET_ERROR(); int err = EVUTIL_SOCKET_ERROR();
log_error("accept_error_cb - got an error %d (%s) on the listener. "
"Shutting down.", err, evutil_socket_error_to_string(err)); /* TODO: If we have enough connections, don't stop the event loop */
log_error("Error %d (%s) on the listener, shutting down",
err, evutil_socket_error_to_string(err));
/* stop the event loop */ /* stop the event loop */
event_base_loopexit(base, NULL); event_base_loopexit(base, NULL);
...@@ -449,7 +463,7 @@ int listen_init(struct evconnlistener **listener, ...@@ -449,7 +463,7 @@ int listen_init(struct evconnlistener **listener,
*base = event_base_new(); *base = event_base_new();
if (!*base) { if (!*base) {
log_error("listen_init - event_base creation failure"); log_error("Creating eventbase");
return 1; return 1;
} }
...@@ -467,7 +481,7 @@ int listen_init(struct evconnlistener **listener, ...@@ -467,7 +481,7 @@ int listen_init(struct evconnlistener **listener,
sizeof(sock_addr)); sizeof(sock_addr));
if (!*listener) { if (!*