Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Michal Zima
coincer
Commits
7098f83f
Commit
7098f83f
authored
Jul 12, 2018
by
xHire
Browse files
Merge management of peers
parents
f0144a75
2e3b123e
Changes
16
Expand all
Hide whitespace changes
Inline
Side-by-side
Makefile.am
View file @
7098f83f
...
...
@@ -4,9 +4,13 @@ bin_PROGRAMS = src/coincerd src/coincer
src_coincerd_SOURCES
=
\
src/coincerd.c
\
src/configuration.c src/configuration.h
\
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/paths.c src/paths.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)
...
...
src/coincerd.c
View file @
7098f83f
/*
* Coincer
* Copyright (C) 2017 Coincer Developers
* 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
...
...
@@ -18,9 +18,18 @@
#include <event2/event.h>
#include <event2/listener.h>
#include <signal.h>
#include <stdlib.h>
#include <time.h>
#include "log.h"
#include "neighbours.h"
#include "p2p.h"
#include "paths.h"
#include "peers.h"
static
void
signal_cb
(
evutil_socket_t
fd
,
short
events
,
void
*
ctx
);
static
void
conns_cb
(
evutil_socket_t
fd
,
short
events
,
void
*
ctx
);
int
main
(
void
)
{
...
...
@@ -42,21 +51,128 @@ int main(void)
* - terminate on SIGTERM
*/
struct
evconnlistener
*
listener
;
struct
s_global_state
global_state
;
struct
event
*
conns_event
;
struct
timeval
conns_interval
;
global_state_t
global_state
;
struct
evconnlistener
*
listener
;
struct
event
*
sigint_event
;
struct
event
*
sigterm_event
;
global_state
.
event_loop
=
NULL
;
neighbours_init
(
&
global_state
.
neighbours
);
/* TODO: use randombytes (from libsodium?) for the seed of randomness */
srand
((
unsigned
)
time
(
NULL
)
);
if
(
listen_init
(
&
listener
,
&
global_state
)
!=
0
)
{
/* initialize all global_state variables */
global_state
.
event_loop
=
NULL
;
if
(
setup_paths
(
&
global_state
.
filepaths
))
{
log_error
(
"Initializing paths to needed files/dirs"
);
return
1
;
}
linkedlist_init
(
&
global_state
.
pending_neighbours
);
linkedlist_init
(
&
global_state
.
neighbours
);
linkedlist_init
(
&
global_state
.
peers
);
fetch_peers
(
global_state
.
filepaths
.
peers
,
&
global_state
.
peers
);
/* setup everything needed for TCP listening */
if
(
listen_init
(
&
listener
,
&
global_state
)
!=
0
)
{
log_error
(
"Initialization of TCP listening"
);
return
2
;
}
/* register SIGINT event to its callback */
sigint_event
=
evsignal_new
(
global_state
.
event_loop
,
SIGINT
,
signal_cb
,
&
global_state
);
if
(
!
sigint_event
||
event_add
(
sigint_event
,
NULL
)
<
0
)
{
log_error
(
"Creating or adding SIGINT event"
);
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 */
conns_interval
.
tv_sec
=
10
;
conns_interval
.
tv_usec
=
0
;
conns_event
=
event_new
(
global_state
.
event_loop
,
-
1
,
EV_PERSIST
,
conns_cb
,
&
global_state
);
if
(
!
conns_event
||
event_add
(
conns_event
,
&
conns_interval
)
<
0
)
{
log_error
(
"Creating or adding Connections event"
);
return
3
;
}
/* initiate joining the coincer network */
add_more_connections
(
&
global_state
,
MIN_NEIGHBOURS
);
/* start the event loop */
event_base_dispatch
(
global_state
.
event_loop
);
event_base_free
(
global_state
.
event_loop
);
evconnlistener_free
(
listener
);
/* SIGINT received, loop terminated; the clean-up part */
clear_neighbours
(
&
global_state
.
pending_neighbours
);
clear_neighbours
(
&
global_state
.
neighbours
);
/* store peers into 'peers' file before cleaning them */
store_peers
(
global_state
.
filepaths
.
peers
,
&
global_state
.
peers
);
clear_peers
(
&
global_state
.
peers
);
clear_paths
(
&
global_state
.
filepaths
);
evconnlistener_free
(
listener
);
event_free
(
sigint_event
);
event_free
(
sigterm_event
);
event_free
(
conns_event
);
event_base_free
(
global_state
.
event_loop
);
return
0
;
}
/**
* Callback function for a received signal.
*
* @param signal What signal was invoked.
* @param events Flags of the event occurred.
* @param ctx Global state.
*/
static
void
signal_cb
(
evutil_socket_t
signal
__attribute__
((
unused
)),
short
events
__attribute__
((
unused
)),
void
*
ctx
)
{
global_state_t
*
global_state
=
(
global_state_t
*
)
ctx
;
event_base_loopexit
(
global_state
->
event_loop
,
NULL
);
}
/**
* Actively check the number of neighbours and add more if needed.
*
* @param fd File descriptor.
* @param events Event flags.
* @param ctx Global state.
*/
static
void
conns_cb
(
int
fd
__attribute__
((
unused
)),
short
events
__attribute__
((
unused
)),
void
*
ctx
)
{
int
needed_conns
;
global_state_t
*
global_state
=
(
global_state_t
*
)
ctx
;
needed_conns
=
MIN_NEIGHBOURS
-
linkedlist_size
(
&
global_state
->
neighbours
);
if
(
needed_conns
>
0
)
{
log_debug
(
"conns_cb - we need %d more neighbours"
);
/* ask twice more peers than we need; it's preferable
* to have more neighbours than minimum */
add_more_connections
(
global_state
,
2
*
needed_conns
);
}
}
src/configuration.c
0 → 100644
View file @
7098f83f
/*
* 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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "autoconfig.h"
#include "configuration.h"
#include "log.h"
/**
* Set home directory.
*
* @param homedir Path to homedir.
*
* @return 0 Path successfully set.
* @return 1 Home directory retrieval failure.
*/
static
int
set_homedir
(
char
**
homedir
)
{
*
homedir
=
getenv
(
"HOME"
);
if
(
*
homedir
==
NULL
||
*
homedir
[
0
]
==
'\0'
)
{
log_error
(
"Can not find home directory"
);
return
1
;
}
return
0
;
}
/**
* Set paths to config and data directories.
*
* @param config_dir Config directory.
* @param data_dir Data directory.
*
* @return 0 Paths successfully set.
* @return 1 Allocation failure.
*/
static
int
set_directories
(
char
**
config_dir
,
char
**
data_dir
)
{
char
*
homedir
=
NULL
,
*
tmpchar
=
NULL
;
size_t
tmpsize
;
/* configuration directory */
tmpchar
=
getenv
(
"XDG_CONFIG_HOME"
);
if
(
tmpchar
==
NULL
||
tmpchar
[
0
]
==
'\0'
)
{
if
(
set_homedir
(
&
homedir
))
{
return
1
;
}
tmpsize
=
strlen
(
homedir
);
*
config_dir
=
(
char
*
)
malloc
(
tmpsize
+
sizeof
(
"/.config/"
PACKAGE_NAME
"/"
));
if
(
*
config_dir
==
NULL
)
{
log_error
(
"Setting configdir"
);
return
1
;
}
strcpy
(
*
config_dir
,
homedir
);
strcpy
(
*
config_dir
+
tmpsize
,
"/.config/"
PACKAGE_NAME
"/"
);
}
else
{
tmpsize
=
strlen
(
tmpchar
);
*
config_dir
=
(
char
*
)
malloc
(
tmpsize
+
sizeof
(
"/"
PACKAGE_NAME
"/"
));
if
(
*
config_dir
==
NULL
)
{
log_error
(
"Setting configdir"
);
return
1
;
}
strcpy
(
*
config_dir
,
tmpchar
);
strcpy
(
*
config_dir
+
tmpsize
,
"/"
PACKAGE_NAME
"/"
);
}
/* data directory */
tmpchar
=
getenv
(
"XDG_DATA_HOME"
);
if
(
tmpchar
==
NULL
||
tmpchar
[
0
]
==
'\0'
)
{
if
(
homedir
==
NULL
&&
set_homedir
(
&
homedir
))
{
free
(
config_dir
);
return
1
;
}
tmpsize
=
strlen
(
homedir
);
*
data_dir
=
(
char
*
)
malloc
(
tmpsize
+
sizeof
(
"/.local/share/"
PACKAGE_NAME
"/"
));
if
(
*
data_dir
==
NULL
)
{
log_error
(
"Setting datadir"
);
free
(
config_dir
);
return
1
;
}
strcpy
(
*
data_dir
,
homedir
);
strcpy
(
*
data_dir
+
tmpsize
,
"/.local/share/"
PACKAGE_NAME
"/"
);
}
else
{
tmpsize
=
strlen
(
tmpchar
);
*
data_dir
=
(
char
*
)
malloc
(
tmpsize
+
sizeof
(
"/"
PACKAGE_NAME
"/"
));
if
(
*
data_dir
==
NULL
)
{
log_error
(
"Setting datadir"
);
free
(
config_dir
);
return
1
;
}
strcpy
(
*
data_dir
,
tmpchar
);
strcpy
(
*
data_dir
+
tmpsize
,
"/"
PACKAGE_NAME
"/"
);
}
return
0
;
}
/**
* Creates directories if they don't exist yet.
*
* @param config_dir Config directory.
* @param data_dir Data directory.
*
* @return 0 Directories created.
* @return 1 Creating directories failed.
*/
static
int
create_dirs
(
const
char
*
config_dir
,
const
char
*
data_dir
)
{
struct
stat
buffer
;
/* configuration directory */
if
(
stat
(
config_dir
,
&
buffer
))
{
if
(
errno
==
ENOENT
)
{
/* create */
if
(
mkdir
(
config_dir
,
S_IRWXU
))
{
log_error
(
"Could not create configuration "
"directory %s"
,
config_dir
);
return
1
;
}
else
{
log_debug
(
"create_dirs - created configuration "
"directory %s"
,
config_dir
);
}
}
else
{
log_error
(
"Could not open configuration "
"directory %s"
,
config_dir
);
return
1
;
}
}
/* data directory */
if
(
stat
(
data_dir
,
&
buffer
))
{
if
(
errno
==
ENOENT
)
{
/* create */
if
(
mkdir
(
data_dir
,
S_IRWXU
))
{
log_error
(
"Could not create "
"data directory %s"
,
data_dir
);
return
1
;
}
else
{
log_debug
(
"create_dirs - created data "
"directory %s"
,
data_dir
);
}
}
else
{
log_error
(
"Could not open data directory %s"
,
data_dir
);
return
1
;
}
}
return
0
;
}
/**
* Create needed directories and fetch their paths into params.
*
* @param config_dir Config directory.
* @param data_dir Data directory.
*
* @return 0 Directories created.
* @return 1 Directories setup failure.
*/
int
setup_directories
(
char
**
config_dir
,
char
**
data_dir
)
{
if
(
set_directories
(
config_dir
,
data_dir
)
||
create_dirs
(
*
config_dir
,
*
data_dir
))
{
return
1
;
}
return
0
;
}
src/configuration.h
0 → 100644
View file @
7098f83f
/*
* 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 CONFIGURATION_H
#define CONFIGURATION_H
int
setup_directories
(
char
**
config_dir
,
char
**
data_dir
);
#endif
/* CONFIGURATION_H */
src/linkedlist.c
View file @
7098f83f
/*
* Coincer
* Copyright (C) 2017 Coincer Developers
* 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
...
...
@@ -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
)
{
r
oot
->
first
.
prev
=
NULL
;
root
->
first
.
next
=
&
root
->
last
;
root
->
last
.
prev
=
&
root
->
first
;
root
->
last
.
next
=
NULL
;
r
eturn
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.
*
* @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.
*
* @return First node of the linked list.
* @return NULL if linkedlist is empty.
* @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
i
f linkedlist is empty.
* @return
linkedlist_node_t
Last node of the linked list.
* @return NULL
I
f 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,116 @@ 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 linkedlist after 'node'. In case of 'node' being the
* last (stub) node, insert before it.
*
* @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.
*