Commit 4ceecd19 authored by xHire's avatar xHire
Browse files

Refactoring

parent cd5ee4fa
......@@ -4,8 +4,8 @@ bin_PROGRAMS = src/coincerd src/coincer
src_coincerd_SOURCES = \
src/coincerd.c \
src/p2p.c src/p2p.h \
src/neighbours.c src/neighbours.h
src/neighbours.c src/neighbours.h \
src/p2p.c src/p2p.h
src_coincerd_CFLAGS = $(AM_CFLAGS) $(JANSSON_CFLAGS) $(LIBEVENT_CFLAGS) $(LIBSODIUM_CFLAGS)
src_coincerd_LDADD = $(AM_LDADD) $(JANSSON_LIBS) $(LIBEVENT_LIBS) $(LIBSODIUM_LIBS)
......
......@@ -43,23 +43,20 @@ int main(void)
*/
struct evconnlistener *listener;
struct Loop_Data loop_data;
struct s_global_state global_state;
/* To store the return values of setup functions */
int ret;
global_state.event_loop = NULL;
neighbours_init(&global_state.neighbours);
loop_data.event_loop = NULL;
neighbours_init(&loop_data.neighbours);
if ((ret = listen_init(&listener, &loop_data)) != 0) {
return ret;
if (listen_init(&listener, &global_state) != 0) {
return 1;
}
event_base_dispatch(loop_data.event_loop);
event_base_dispatch(global_state.event_loop);
event_base_free(loop_data.event_loop);
event_base_free(global_state.event_loop);
evconnlistener_free(listener);
clear_neighbours(&loop_data.neighbours);
clear_neighbours(&global_state.neighbours);
return 0;
}
/*
* Coincer
* Copyright (C) 2017 Coincer Developers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include "linkedlist.h"
#include "log.h"
/**
* Creates root of a linked list.
*
* @return Root of new linked list
*/
linkedlist_t *linkedlist_create(void)
{
linkedlist_t *linkedlist;
if ((linkedlist = (linkedlist_t *) malloc(sizeof(linkedlist_t))) ==
NULL) {
log_error("Lack of free memory");
return NULL;
}
linkedlist->first.prev = NULL;
linkedlist->first.next = &linkedlist->last;
linkedlist->last.prev = &linkedlist->first;
linkedlist->last.next = NULL;
return linkedlist;
}
/**
* Destroys a linked list.
*
* @param root Root of the linked list to destroy
*/
void linkedlist_destroy(linkedlist_t *root)
{
linkedlist_node_t *tmp;
tmp = root->first.next;
while (tmp->next != NULL) {
tmp = tmp->next;
free(tmp->prev);
}
}
/**
* Append new node at the end of the linked list.
*
* @param root Root of the linked list
* @param data Data to append to the list
*
* @return pointer to created node if succeeded
* @return NULL if failed
*/
linkedlist_node_t *linkedlist_append(linkedlist_t *root, void *data)
{
linkedlist_node_t *node;
if ((node = (linkedlist_node_t *) malloc(sizeof(linkedlist_node_t))) ==
NULL) {
log_error("Lack of free memory");
return NULL;
}
node->data = data;
node->prev = root->last.prev;
node->next = &root->last;
root->last.prev->next = node;
root->last.prev = node;
return node;
}
/**
* Delete node from beginning of linked list.
*
* @param root Root of the linked list
* @param node Node to delete from the list
*/
void linkedlist_delete(linkedlist_t *root, linkedlist_node_t *node)
{
root->first.next = node->next;
node->next->prev = node->prev;
free(node);
node = NULL;
}
/*
* Coincer
* Copyright (C) 2017 Coincer Developers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
/* Linked list node structure */
typedef struct s_linkedlist_node {
struct s_linkedlist_node *prev;
struct s_linkedlist_node *next;
void *data;
} linkedlist_node_t;
/* Linked list root structure */
typedef struct s_linkedlist {
linkedlist_node_t first;
linkedlist_node_t last;
} linkedlist_t;
linkedlist_t *linkedlist_create(void);
void linkedlist_destroy(linkedlist_t *root);
linkedlist_node_t *linkedlist_append(linkedlist_t *root, void *data);
void linkedlist_delete(linkedlist_t *root, linkedlist_node_t *node);
#endif /* LINKEDLIST_H */
#include <assert.h>
/*
* Coincer
* Copyright (C) 2017-2018 Coincer Developers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <event2/bufferevent.h>
#include <stdio.h>
#include <stdlib.h>
......@@ -6,17 +23,16 @@
#include "neighbours.h"
void neighbours_init(struct Neighbours *neighbours)
void neighbours_init(struct s_neighbours *neighbours)
{
neighbours->first = neighbours->last = NULL;
neighbours->size = 0;
}
struct Neighbour *find_neighbour(const struct Neighbours *neighbours,
const struct bufferevent *bev)
struct s_neighbour *find_neighbour(const struct s_neighbours *neighbours,
const struct bufferevent *bev)
{
struct Neighbour *current = neighbours->first;
struct s_neighbour *current = neighbours->first;
while (current != NULL) {
if (current->buffer_event == bev) {
......@@ -28,10 +44,10 @@ struct Neighbour *find_neighbour(const struct Neighbours *neighbours,
return NULL;
}
struct Neighbour *find_neighbour_by_ip(const struct Neighbours *neighbours,
const char *ip_addr)
struct s_neighbour *find_neighbour_by_ip(const struct s_neighbours *neighbours,
const char *ip_addr)
{
struct Neighbour *current = neighbours->first;
struct s_neighbour *current = neighbours->first;
while (current != NULL) {
if (strcmp(current->ip_addr, ip_addr) == 0) {
......@@ -41,28 +57,34 @@ struct Neighbour *find_neighbour_by_ip(const struct Neighbours *neighbours,
}
return NULL;
}
struct Neighbour *add_new_neighbour(struct Neighbours *neighbours,
const char *ip_addr,
struct bufferevent *bev)
struct s_neighbour *add_new_neighbour(struct s_neighbours *neighbours,
const char *ip_addr,
struct bufferevent *bev)
{
struct Neighbour *new_neighbour = (struct Neighbour *)
malloc(sizeof(struct Neighbour));
struct s_neighbour *new_neighbour;
new_neighbour = (struct s_neighbour *)
malloc(sizeof(struct s_neighbour));
if (new_neighbour == NULL) {
/* WIP */
perror("malloc for a new neighbour");
return NULL;
}
/* don't add duplicates */
if (find_neighbour_by_ip(neighbours, ip_addr)) {
return NULL;
}
assert(new_neighbour != NULL);
/* TODO: comment why it is safe to use strcpy */
strcpy(new_neighbour->ip_addr, ip_addr);
new_neighbour->failed_pings = 0;
new_neighbour->next = NULL;
new_neighbour->buffer_event = bev;
/* TODO: comment */
if (neighbours->last == NULL) {
neighbours->first = neighbours->last = new_neighbour;
} else {
......@@ -75,10 +97,10 @@ struct Neighbour *add_new_neighbour(struct Neighbours *neighbours,
return new_neighbour;
}
void delete_neighbour(struct Neighbours *neighbours, struct bufferevent *bev)
void delete_neighbour(struct s_neighbours *neighbours, struct bufferevent *bev)
{
struct Neighbour *current = neighbours->first;
struct Neighbour *neighbour = find_neighbour(neighbours, bev);
struct s_neighbour *current = neighbours->first;
struct s_neighbour *neighbour = find_neighbour(neighbours, bev);
if (current == NULL || neighbour == NULL) {
return;
......@@ -89,7 +111,6 @@ void delete_neighbour(struct Neighbours *neighbours, struct bufferevent *bev)
}
if (neighbours->first == neighbour) {
if (neighbours->first == neighbours->last) {
neighbours->first = neighbours->last = NULL;
} else {
......@@ -103,7 +124,6 @@ void delete_neighbour(struct Neighbours *neighbours, struct bufferevent *bev)
while (current != NULL) {
if (current->next == neighbour) {
current->next = neighbour->next;
if (current->next == NULL) {
......@@ -118,13 +138,13 @@ void delete_neighbour(struct Neighbours *neighbours, struct bufferevent *bev)
}
}
void clear_neighbours(struct Neighbours *neighbours)
void clear_neighbours(struct s_neighbours *neighbours)
{
struct Neighbour *current = neighbours->first;
struct s_neighbour *current = neighbours->first;
while (current != NULL) {
struct Neighbour *temp = current;
struct s_neighbour *temp = current;
current = current->next;
if (temp->buffer_event != NULL) {
......@@ -136,9 +156,3 @@ void clear_neighbours(struct Neighbours *neighbours)
neighbours_init(neighbours);
}
/*
* Coincer
* Copyright (C) 2017-2018 Coincer Developers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NEIGHBOURS_H
#define NEIGHBOURS_H
#include <event2/bufferevent.h>
#include <stddef.h>
/* data type for the linked list of neighbours */
struct Neighbour {
/* neighbours's IPv6 address */
/** data type for the linked list of neighbours */
struct s_neighbour {
/** neighbours's IPv6 address;
* also allows storing IPv4-mapped IPv6 addresses */
char ip_addr[46];
/* bufferevent belonging to this neighbour */
/** bufferevent belonging to this neighbour */
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;
/* next Neighbour in the linked list - at struct Neighbours */
struct Neighbour *next;
/** next neighbour in the linked list (struct s_neighbours) */
struct s_neighbour *next;
};
/* linked list of Neighbours */
struct Neighbours {
/* number of neighbours we are connected to */
/** linked list of neighbours */
struct s_neighbours {
/** number of neighbours we are connected to */
size_t size;
struct Neighbour *first;
struct Neighbour *last;
struct s_neighbour *first;
struct s_neighbour *last;
};
/* set linked list variables to their default values */
void neighbours_init(struct Neighbours *neighbours);
/** set linked list variables to their default values */
void neighbours_init(struct s_neighbours *neighbours);
/** find neighbour in neighbours based on their buffer_event,
returns NULL if not found */
struct s_neighbour *find_neighbour(const struct s_neighbours *neighbours,
const struct bufferevent *bev);
/* find neighbour in neighbours based on their buffer_event,
returns NULL if not found */
struct Neighbour *find_neighbour(const struct Neighbours *neighbours,
const struct bufferevent *bev);
/** find neighbour in neighbours based on their ip_addr,
returns NULL if not found */
struct s_neighbour *find_neighbour_by_ip(const struct s_neighbours *neighbours,
const char *ip_addr);
/* find neighbour in neighbours based on their ip_addr,
returns NULL if not found */
struct Neighbour *find_neighbour_by_ip(const struct Neighbours *neighbours,
const char *ip_addr);
/* add new neighbour into neighbours
returns NULL if neighbour already exists */
struct Neighbour* add_new_neighbour(struct Neighbours *neighbours,
const char *ip_addr,
struct bufferevent *bev);
/** add new neighbour into neighbours
returns NULL if neighbour already exists */
struct s_neighbour *add_new_neighbour(struct s_neighbours *neighbours,
const char *ip_addr,
struct bufferevent *bev);
/* delete neighbour from neighbours */
void delete_neighbour(struct Neighbours *neighbours,
struct bufferevent *bev);
void delete_neighbour(struct s_neighbours *neighbours,
struct bufferevent *bev);
/* delete all neighbours */
void clear_neighbours(struct Neighbours *neighbours);
void clear_neighbours(struct s_neighbours *neighbours);
#endif
#endif /* NEIGHBOURS_H */
......@@ -33,17 +33,17 @@
*
* @brief Callback for reading an input buffer
* @param bev buffer to read data from
* @param ctx struct Loop_Data *
* @param ctx struct s_global_state *
*/
static void p2p_process(struct bufferevent *bev, void *ctx)
{
/* Using this we can know who's sent us the message and
reset their amount of failed pings */
struct Loop_Data *loop_data = (struct Loop_Data *) ctx;
struct s_global_state *global_state = (struct s_global_state *) ctx;
/* Find the neighbour based on their buffer event */
struct Neighbour *neighbour =
find_neighbour(&loop_data->neighbours, bev);
find_neighbour(&global_state->neighbours, bev);
/* Read from input buffer, write to output buffer */
struct evbuffer *input = bufferevent_get_input(bev);
......@@ -51,7 +51,7 @@ static void p2p_process(struct bufferevent *bev, void *ctx)
size_t len = evbuffer_get_length(input);
char *data = (char *) malloc(len * (sizeof(char) + 1));
/* FOR TESTING PURPOSES */
/* Drain input buffer into data */
......@@ -80,7 +80,6 @@ static void timeout_process(struct Neighbours *neighbours,
struct Neighbour *neighbour)
{
if (neighbour->failed_pings < 3) {
/* bufferevent was disabled when timeout flag was set */
bufferevent_enable(neighbour->buffer_event,
EV_READ | EV_WRITE | EV_TIMEOUT);
......@@ -105,13 +104,13 @@ static void timeout_process(struct Neighbours *neighbours,
* @brief Callback for bufferevent event detection
* @param bev bufferevent on which the event occured
* @param events flags of the events occured
* @param ctx struct Loop_Data *
* @param ctx struct s_global_state *
*/
static void event_cb(struct bufferevent *bev, short events, void *ctx)
{
struct Loop_Data *loop_data = (struct Loop_Data *) ctx;
struct s_global_state *global_state = (struct s_global_state *) ctx;
struct Neighbour *neighbour =
find_neighbour(&loop_data->neighbours, bev);
find_neighbour(&global_state->neighbours, bev);
if (neighbour == NULL) {
return;
......@@ -120,15 +119,15 @@ static void event_cb(struct bufferevent *bev, short events, void *ctx)
if (events & BEV_EVENT_ERROR) {
perror("Error from bufferevent");
printf("Removing %s from neighbours.\n", neighbour->ip_addr);
delete_neighbour(&loop_data->neighbours, bev);
delete_neighbour(&global_state->neighbours, bev);
}
if (events & (BEV_EVENT_EOF)) {
printf("%s has disconnected.\n", neighbour->ip_addr);
delete_neighbour(&loop_data->neighbours, bev);
delete_neighbour(&global_state->neighbours, bev);
}
if (events & BEV_EVENT_TIMEOUT) {
/* Bufferevent bev received timout event */
timeout_process(&loop_data->neighbours, neighbour);
timeout_process(&global_state->neighbours, neighbour);
}
}
......@@ -152,26 +151,28 @@ static void ip_to_string(struct sockaddr *addr, char *ip)
* @param fd file descriptor for the new connection
* @param address routing information
* @param socklen size of address
* @param ctx struct Loop_Data *
* @param ctx struct s_global_state *
*/
static void accept_connection(struct evconnlistener *listener,
evutil_socket_t fd, struct sockaddr *addr,
int socklen __attribute__((unused)),
void *ctx)
{
/* We need to add the new connection to the list
of our neighbours */
struct Loop_Data *loop_data = (struct Loop_Data *) ctx;
/* We need to add the new connection to the list of our neighbours */
struct s_global_state *global_state = (struct s_global_state *) ctx;
struct timeval write_timeout;
struct timeval read_timeout;
/* To display IP address of the other peer */
char ip[INET6_ADDRSTRLEN];
/* Set up a bufferevent for a new connection */
struct event_base *base = evconnlistener_get_base(listener);
struct bufferevent *bev =
bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
/* Bufferevent for a new connection */
struct event_base *base;
struct bufferevent *bev;
/* Set up the bufferevent for a new connection */
base = evconnlistener_get_base(listener);
bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *) addr;
......@@ -192,7 +193,7 @@ static void accept_connection(struct evconnlistener *listener,
ip_to_string(addr, ip);
/* Add the new connection to the list of our neighbours */
if (!add_new_neighbour(&loop_data->neighbours, ip, bev)) {
if (!add_new_neighbour(&global_state->neighbours, ip, bev)) {
bufferevent_free(bev);
return;
}
......@@ -203,34 +204,34 @@ static void accept_connection(struct evconnlistener *listener,
/**
* @brief Callback for listener error detection
* @param listener listener on which the error occured
* @param ctx struct Loop_Data *
* @param ctx struct s_global_state *
*/
static void accept_error_cb(struct evconnlistener *listener,
void *ctx)
{
struct event_base *base = evconnlistener_get_base(listener);
struct Loop_Data *loop_data = (struct Loop_Data *) ctx;
struct s_global_state *global_state = (struct s_global_state *) ctx;
int err = EVUTIL_SOCKET_ERROR();
fprintf(stderr, "Got an error %d (%s) on the listener. "
"Shutting down.\n", err, evutil_socket_error_to_string(err));
event_base_loopexit(base, NULL);
clear_neighbours(&loop_data->neighbours);
clear_neighbours(&global_state->neighbours);
}
/**
* @brief Initialize listening and set up callbacks
*
* @param listener The even loop listener
* @param loop_data Data for the event loop to work with
* @param global_state Data for the event loop to work with
*
* @return 1 if an error occured
* @return 0 if successfully initialized
*/
int listen_init(struct evconnlistener **listener,
struct Loop_Data *loop_data)
struct s_global_state *global_state)
{
struct event_base **base = &loop_data->event_loop;
struct event_base **base = &global_state->event_loop;
struct sockaddr_in6 sock_addr;
int port = DEFAULT_PORT;
......@@ -247,7 +248,7 @@ int listen_init(struct evconnlistener **listener,
sock_addr.sin6_addr = in6addr_any;
sock_addr.sin6_port = htons(port);
*listener = evconnlistener_new_bind(*base, accept_connection, loop_data,
*listener = evconnlistener_new_bind(*base, accept_connection, global_state,
LEV_OPT_CLOSE_ON_FREE |
LEV_OPT_REUSEABLE, -1,
(struct sockaddr *) &sock_addr,
......@@ -259,6 +260,6 @@ int listen_init(struct evconnlistener **listener,
}
evconnlistener_set_error_cb(*listener, accept_error_cb);
return 0;
}
......@@ -29,21 +29,21 @@
#define WRITE_TIMEOUT 30
/* event loop will work with the data stored in an instance of this struct */