Commit 978d3a36 authored by xpetrak2's avatar xpetrak2
Browse files

Peers representation, extended linkedlist

* neighbours, peers and linked list functions in alphabetical order
* more functions in the linked list
* the peers are being represented by their own structure
* linkedlist of pending_neighbours and peers for the next commit
parent 07d01c79
......@@ -9,7 +9,8 @@ src_coincerd_SOURCES = \
src/linkedlist.c src/linkedlist.h \
src/log.c src/log.h \
src/neighbours.c src/neighbours.h \
src/p2p.c src/p2p.h
src/p2p.c src/p2p.h \
src/peers.c src/peers.h
src_coincerd_CFLAGS = $(AM_CFLAGS) $(JANSSON_CFLAGS) $(LIBEVENT_CFLAGS) $(LIBSODIUM_CFLAGS)
src_coincerd_LDADD = $(AM_LDADD) $(JANSSON_LIBS) $(LIBEVENT_LIBS) $(LIBSODIUM_LIBS)
......
......@@ -20,30 +20,96 @@
#include <stdlib.h>
#include "linkedlist.h"
#include "log.h"
/**
* Initializes linked list to default values.
* Append new node at the end of the linked list.
*
* @param root Linked list to initialize.
* @param root Root of the linked list.
* @param data Data of the new node.
*
* @return linkedlist_node_t Pointer to created node if succeeded.
* @return NULL If failure.
*/
void linkedlist_init(linkedlist_t *root)
linkedlist_node_t *linkedlist_append(linkedlist_t *root, void *data)
{
root->first.prev = NULL;
root->first.next = &root->last;
root->last.prev = &root->first;
root->last.next = NULL;
return linkedlist_insert_after(root,
root->last.prev,
data);
}
root->first.data = NULL;
root->last.data = NULL;
/**
* Delete node from the linked list.
*
* @param node Node to be deleted from the linked list.
*/
void linkedlist_delete(linkedlist_node_t *node)
{
/* fix the links of neighbour nodes */
node->prev->next = node->next;
node->next->prev = node->prev;
/* node's data deletion part */
if (node->data != NULL) {
free(node->data);
}
/* node deletion part */
free(node);
}
/**
* Get first node of the linked list.
* Destroys a linked list.
*
* @param root Root of the 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;
if (tmp->prev->data != NULL) {
free(tmp->prev->data);
}
free(tmp->prev);
}
}
/**
* Find node in the linked list by data.
*
* @return First node of the linked list.
* @return NULL if linkedlist is empty.
* @param root Root of the linked list.
* @param data Data of the requested node.
*
* @return linkedlist_node_t Node containing 'data'.
* @return NULL If the node doesn't exist.
*/
linkedlist_node_t *linkedlist_find(const linkedlist_t *root, const void *data)
{
/* start the search from the first node of the linked list */
linkedlist_node_t *current = linkedlist_get_first(root);
while (current != NULL) {
/* node found */
if (current->data == data) {
/* return the node containing 'data' */
return current;
}
/* move to the next node and continue with the search */
current = linkedlist_get_next(root, current);
}
/* node not found */
return NULL;
}
/**
* Get the first node of the linked list.
*
* @param root Root of the linked list.
*
* @return linkedlist_node_t First node of the linked list.
* @return NULL If the linkedlist is empty.
*/
linkedlist_node_t *linkedlist_get_first(const linkedlist_t *root)
{
......@@ -55,12 +121,12 @@ linkedlist_node_t *linkedlist_get_first(const linkedlist_t *root)
}
/**
* Get last node of the linkedlist.
* Get the last node of the linkedlist.
*
* @param root Root of the linked list.
* @param root Root of the linked list.
*
* @return Last node of the linked list.
* @return NULL if linkedlist is empty.
* @return linkedlist_node_t Last node of the linked list.
* @return NULL If linkedlist is empty.
*/
linkedlist_node_t *linkedlist_get_last(const linkedlist_t *root)
{
......@@ -72,13 +138,14 @@ linkedlist_node_t *linkedlist_get_last(const linkedlist_t *root)
}
/**
* Get node that is right after 'node' in the linked list.
* Get a node that is right after 'node' in the linked list.
*
* @param root Root of the linked list.
* @param node We want node that is right after this node.
* @param root Root of the linked list.
* @param node A node right after this node.
*
* @return The node we requested.
* @return NULL if 'node' was last in the linked list or NULL.
* @return linkedlist_node_t The node we requested.
* @return NULL If 'node' was the last or 'root'
* is empty.
*/
linkedlist_node_t *linkedlist_get_next(const linkedlist_t *root,
const linkedlist_node_t *node)
......@@ -91,110 +158,115 @@ linkedlist_node_t *linkedlist_get_next(const linkedlist_t *root,
}
/**
* Destroys a linked list.
* Get a node that is right before 'node' in the linked list.
*
* @param root Root of the linked list to destroy.
* @param root Root of the linked list.
* @param node A node right before this node.
*
* @return linkedlist_node The node we requested.
* @return NULL If 'node' was the first or 'root'
* is empty.
*/
void linkedlist_destroy(linkedlist_t *root)
linkedlist_node_t *linkedlist_get_prev(const linkedlist_t *root,
const linkedlist_node_t *node)
{
linkedlist_node_t *tmp;
tmp = root->first.next;
while (tmp->next != NULL) {
tmp = tmp->next;
free(tmp->prev);
if (node == NULL || node->prev == &root->first) {
return NULL;
}
return node->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.
* Initializes linked list to default values.
*
* @return Pointer to created node if succeeded.
* @return NULL if failed.
* @param root Linked list to initialize.
*/
linkedlist_node_t *linkedlist_append(linkedlist_t *root, void *data)
void linkedlist_init(linkedlist_t *root)
{
linkedlist_node_t *node;
if ((node = (linkedlist_node_t *) malloc(sizeof(linkedlist_node_t))) ==
NULL) {
perror("linkedlist_append malloc");
return NULL;
}
node->data = data;
node->prev = root->last.prev;
node->next = &root->last;
root->last.prev->next = node;
root->last.prev = node;
root->first.prev = NULL;
root->first.next = &root->last;
root->last.prev = &root->first;
root->last.next = NULL;
return node;
root->first.data = NULL;
root->last.data = NULL;
}
/**
* Delete node from the linked list.
* Insert new node into linked list after 'node'.
*
* @param root Root of the linked list.
* @param node Node to be deleted from the linked list.
* @param root Root of the linked list.
* @param node Insert new node right after this node.
* @param data Data of the new node.
*
* @return linkedlist_node_t Pointer to the new node.
* @return NULL If failure.
*/
void linkedlist_delete(linkedlist_t *root, linkedlist_node_t *node)
linkedlist_node_t *linkedlist_insert_after(linkedlist_t *root,
linkedlist_node_t *node,
void *data)
{
/* start the search from the first node of the linked list */
linkedlist_node_t *current = linkedlist_get_first(root);
linkedlist_node_t *new_node;
while (current != NULL) {
if (node == &root->last) {
node = root->last.prev;
}
/* node found */
if (current == node) {
new_node = (linkedlist_node_t *) malloc(sizeof(linkedlist_node_t));
if (new_node == NULL) {
log_error("linkedlist_insert_after - malloc");
return NULL;
}
/* fix the links of neighbour nodes */
node->prev->next = node->next;
node->next->prev = node->prev;
new_node->data = data;
/* node deletion part */
free(node);
node = NULL;
new_node->prev = node;
new_node->next = node->next;
node->next->prev = new_node;
node->next = new_node;
/* no need to continue */
return;
}
return new_node;
}
/* go to next node and continue the search */
current = linkedlist_get_next(root, current);
/**
* Insert new node into linkedlist before 'node'.
*
* @param root Root of the linked list.
* @param node Insert new node right before this node.
* @param data Data of the new node.
*
* @return linkedlist_node_t Pointer to the new node.
* @return NULL If failure.
*/
linkedlist_node_t *linkedlist_insert_before(linkedlist_t *root,
linkedlist_node_t *node,
void *data)
{
if (node == &root->first) {
node = root->first.next;
}
return linkedlist_insert_after(root, node->prev, data);
}
/**
* Find node in the linked list by data.
* Get the number of elements in the linked list.
*
* @param root Root of the linked list.
* @param data Data of the requested node.
*
* @return Node containing 'data'.
* @return NULL if the node doesn't exist.
* @return n Number of linked list elements.
*/
linkedlist_node_t *linkedlist_find(const linkedlist_t *root, const void *data)
size_t linkedlist_size(const linkedlist_t *root)
{
/* start the search from the first node of the linked list */
linkedlist_node_t *current = linkedlist_get_first(root);
while (current != NULL) {
/* node found */
if (current->data == data) {
/* return the node containing 'data' */
return current;
}
linkedlist_node_t *tmp;
size_t n = 0;
/* move to the next node and continue with the search */
current = linkedlist_get_next(root, current);
tmp = root->first.next;
while (tmp->next != NULL) {
n++;
tmp = tmp->next;
}
/* node not found */
return NULL;
return n;
}
......@@ -19,6 +19,8 @@
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <stdint.h>
/**
* Node of the linked list structure.
*/
......@@ -36,7 +38,13 @@ typedef struct s_linkedlist {
struct s_linkedlist_node last; /**< Auxiliary last node. */
} linkedlist_t;
void linkedlist_init(linkedlist_t *root);
linkedlist_node_t *linkedlist_append(linkedlist_t *root, void *data);
void linkedlist_delete(linkedlist_node_t *node);
void linkedlist_destroy(linkedlist_t *root);
linkedlist_node_t *linkedlist_find(const linkedlist_t *root, const void *data);
linkedlist_node_t *linkedlist_get_first(const linkedlist_t *root);
......@@ -45,12 +53,20 @@ linkedlist_node_t *linkedlist_get_last(const linkedlist_t *root);
linkedlist_node_t *linkedlist_get_next(const linkedlist_t *root,
const linkedlist_node_t *node);
void linkedlist_destroy(linkedlist_t *root);
linkedlist_node_t *linkedlist_get_prev(const linkedlist_t *root,
const linkedlist_node_t *node);
linkedlist_node_t *linkedlist_append(linkedlist_t *root, void *data);
void linkedlist_init(linkedlist_t *root);
void linkedlist_delete(linkedlist_t *root, linkedlist_node_t *node);
linkedlist_node_t *linkedlist_insert_after(linkedlist_t *root,
linkedlist_node_t *node,
void *data);
linkedlist_node_t *linkedlist_find(const linkedlist_t *root, const void *data);
linkedlist_node_t *linkedlist_insert_before(linkedlist_t *root,
linkedlist_node_t *node,
void *data);
size_t linkedlist_size(const linkedlist_t *root);
#endif /* LINKEDLIST_H */
......@@ -16,32 +16,24 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <event2/bufferevent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "linkedlist.h"
#include "log.h"
#include "neighbours.h"
/**
* Initialize the linked list of neighbours to default values.
*
* @param neighbours Linked list to be initialized.
*/
void neighbours_init(linkedlist_t *neighbours)
{
linkedlist_init(neighbours);
}
/**
* Find neighbour in neighbours based on their bufferevent.
*
* @param neighbours Linked list of our neighbours.
* @param neighbours Our neighbours.
* @param bev Neighbour's bufferevent.
*
* @return Desired neighbour.
* @return NULL if not found.
* @return neighbour_t Requested neighbour.
* @return NULL If not found.
*/
neighbour_t *find_neighbour(const linkedlist_t *neighbours,
const struct bufferevent *bev)
......@@ -60,25 +52,24 @@ neighbour_t *find_neighbour(const linkedlist_t *neighbours,
/* return node's data; struct s_neighbour */
return current_data;
}
/* get next node in the linked list */
current = linkedlist_get_next(neighbours, current);
}
/* neighbour not found */
return NULL;
}
/**
* Find neighbour in neighbours based on their ip_addr.
/**
* Find neighbour in neighbours based on their addr.
*
* @param neighbours Linked list of our neighbours.
* @param ip_addr Binary ip address stored in 16 bytes.
* @param neighbours Our neighbours.
* @param addr Binary ip address stored in 16 bytes.
*
* @return Desired neighbour.
* @return NULL if not found.
* @return neighbour_t Requested neighbour.
* @return NULL If not found.
*/
neighbour_t *find_neighbour_by_ip(const linkedlist_t *neighbours,
const unsigned char *ip_addr)
neighbour_t *find_neighbour_by_addr(const linkedlist_t *neighbours,
const struct in6_addr *addr)
{
/* start the search from the first linked list node */
const linkedlist_node_t *current = linkedlist_get_first(neighbours);
......@@ -89,58 +80,57 @@ neighbour_t *find_neighbour_by_ip(const linkedlist_t *neighbours,
neighbour_t *current_data = (neighbour_t *) current->data;
/* ip addresses match => neighbour found */
if (memcmp(current_data->ip_addr, ip_addr, 16) == 0) {
if (memcmp(&current_data->addr, addr, 16) == 0) {
/* return node's data; struct s_neighbour */
return current_data;
}
/* get next node in the linked list */
current = linkedlist_get_next(neighbours, current);
}
/* neighbour not found */
return NULL;
}
/**
/**
* Add new neighbour into neighbours.
*
* @param neighbours Linked list of our neighbours.
* @param ip_addr Binary ip address stored in 16 bytes.
* @param neighbours Linked list of our neighbours.
* @param addr Binary ip address stored in 16 bytes.
* @param bev Neighbour's bufferevent.
*
* @return Newly added neighbour.
* @return NULL if neighbour already exists or allocation failure occured.
* @return neighbour_t Newly added neighbour.
* @return NULL If the neighbour already exists or allocation
* failure occured.
*/
neighbour_t *add_new_neighbour(linkedlist_t *neighbours,
const unsigned char *ip_addr,
const struct in6_addr *addr,
struct bufferevent *bev)
{
/* create new neighbour */
neighbour_t *new_neighbour;
new_neighbour = (neighbour_t *) malloc(sizeof(neighbour_t));
/* create new neighbour */
new_neighbour = (neighbour_t *) malloc(sizeof(neighbour_t));
/* allocation failure */
if (new_neighbour == NULL) {
/* WIP */
perror("malloc for a new neighbour");
log_error("add_new_neighbour - new_neighbour malloc");
return NULL;
}
/* don't add duplicates */
if (find_neighbour_by_ip(neighbours, ip_addr)) {
if (find_neighbour_by_addr(neighbours, addr) ||
find_neighbour(neighbours, bev)) {
free(new_neighbour);
return NULL;
}
/* initialize new neighbour */
memcpy(new_neighbour->ip_addr, ip_addr, 16);
memcpy(&new_neighbour->addr, addr, 16);
new_neighbour->failed_pings = 0;
new_neighbour->buffer_event = bev;
/* add new neighbour into linked list; NULL if allocation failed */
/* add new neighbour into linked list; NULL if the allocation failed */
if (linkedlist_append(neighbours, new_neighbour) == NULL) {
/* WIP */
perror("malloc for a new neighbour of linkedlist node");
free(new_neighbour);
return NULL;
}
......@@ -159,29 +149,19 @@ void delete_neighbour(linkedlist_t *neighbours, struct bufferevent *bev)
linkedlist_node_t *neighbour_node;
neighbour = find_neighbour(neighbours, bev);
/* no neighbour with bufferevent 'bev' => nothing to delete */
if (neighbour == NULL) {
return;
}
neighbour_node = linkedlist_find(neighbours, neighbour);
/* since neighbour was found, neighbour_node should never be NULL */
if (neighbour_node == NULL) {
/* WIP */
perror("delete_neighbour");
return;
}
assert(neighbour_node != NULL);
/* free neighbour's bufferevent */
bufferevent_free(bev);
/* free the linked list node's data; neighbour_t * */
free(neighbour_node->data);
/* delete the neighbour from the linked list */
linkedlist_delete(neighbours, neighbour_node);
linkedlist_delete(neighbour_node);
}
/**
......@@ -191,27 +171,23 @@ void delete_neighbour(linkedlist_t *neighbours, struct bufferevent *bev)
*/
void clear_neighbours(linkedlist_t *neighbours)
{
linkedlist_node_t *current_node = linkedlist_get_first(neighbours);
neighbour_t *current;
linkedlist_node_t *current_node;
current_node = linkedlist_get_first(neighbours);
/* safely delete data from the linked list nodes */
while (current_node != NULL) {
neighbour_t *current;
/* load current node's data into 'current' */
current = (neighbour_t *) current_node->data;
/* deallocate neighbour's bufferevent */
bufferevent_free(current->buffer_event);
/* deallocate data */
free(current_node->data);
current_node->data = NULL;
/* get next node in the linked list */
current_node = linkedlist_get_next(neighbours, current_node);
}
/* safely delete all nodes in the linked list */
/* safely delete all nodes and their data in the linked list */
linkedlist_destroy(neighbours);
}
......@@ -20,33 +20,33 @@
#define NEIGHBOURS_H
#include <event2/bufferevent.h>
#include <netinet/in.h>
#include <stddef.h>
#include "linkedlist.h"
/** Data type for the linked list of neighbours. */
/* minimum number of peers we need to be connected to */
#define MIN_NEIGHBOURS 3
/** Data type for the linkedlist of neighbours. */
typedef struct s_neighbour {
/**< Neighbours's IPv6 address;
* also allows storing IPv4-mapped IPv6 addresses. */
unsigned char ip_addr[16];
* also allows storing IPv4-mapped IPv6 addresses. */
struct in6_addr addr;
/**< Bufferevent belonging to this neighbour. */
struct bufferevent *buffer_event;
/**< Number of failed ping attempts -- max 3, then disconnect. */
size_t failed_pings;
} neighbour_t;
void neighbours_init(linkedlist_t *neighbours);
neighbour_t *find_neighbour(const linkedlist_t *neighbours,
const struct bufferevent *bev);