Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Michal Zima
coincer
Commits
2e3b123e
Commit
2e3b123e
authored
Jul 06, 2018
by
xpetrak2
Browse files
Merge request problems resolved
parent
2c541eb3
Changes
9
Show whitespace changes
Inline
Side-by-side
src/coincerd.c
View file @
2e3b123e
...
...
@@ -56,13 +56,15 @@ int main(void)
global_state_t
global_state
;
struct
evconnlistener
*
listener
;
struct
event
*
sigint_event
;
time_t
t
;
struct
event
*
sigterm_even
t
;
srand
((
unsigned
)
time
(
&
t
));
/* TODO: use randombytes (from libsodium?) for the seed of randomness */
srand
((
unsigned
)
time
(
NULL
));
/* 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
;
}
...
...
@@ -70,13 +72,12 @@ int main(void)
linkedlist_init
(
&
global_state
.
neighbours
);
linkedlist_init
(
&
global_state
.
peers
);
if
(
fetch_peers
(
global_state
.
filepaths
.
peers
,
&
global_state
.
peers
))
{
return
2
;
}
fetch_peers
(
global_state
.
filepaths
.
peers
,
&
global_state
.
peers
);
/* setup everything needed for TCP listening */
if
(
listen_init
(
&
listener
,
&
global_state
)
!=
0
)
{
return
3
;
log_error
(
"Initialization of TCP listening"
);
return
2
;
}
/* register SIGINT event to its callback */
...
...
@@ -85,8 +86,18 @@ int main(void)
signal_cb
,
&
global_state
);
if
(
!
sigint_event
||
event_add
(
sigint_event
,
NULL
)
<
0
)
{
log_error
(
"main - couldn't create or add SIGINT event"
);
return
4
;
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 */
...
...
@@ -99,8 +110,8 @@ int main(void)
conns_cb
,
&
global_state
);
if
(
!
conns_event
||
event_add
(
conns_event
,
&
conns_interval
)
<
0
)
{
log_error
(
"
main - couldn't c
reat
e
or add
con
ns
_
event"
);
return
4
;
log_error
(
"
C
reat
ing
or add
ing Connectio
ns
event"
);
return
3
;
}
/* initiate joining the coincer network */
...
...
@@ -119,6 +130,7 @@ int main(void)
evconnlistener_free
(
listener
);
event_free
(
sigint_event
);
event_free
(
sigterm_event
);
event_free
(
conns_event
);
event_base_free
(
global_state
.
event_loop
);
...
...
src/configuration.c
View file @
2e3b123e
...
...
@@ -38,7 +38,7 @@ static int set_homedir(char **homedir)
{
*
homedir
=
getenv
(
"HOME"
);
if
(
*
homedir
==
NULL
||
*
homedir
[
0
]
==
'\0'
)
{
log_error
(
"
set_homedir - c
annot find home directory"
);
log_error
(
"
C
an
not find home directory"
);
return
1
;
}
return
0
;
...
...
@@ -70,7 +70,7 @@ static int set_directories(char **config_dir, char **data_dir)
sizeof
(
"/.config/"
PACKAGE_NAME
"/"
));
if
(
*
config_dir
==
NULL
)
{
log_error
(
"
set_directories - s
etting config
_
dir"
);
log_error
(
"
S
etting configdir"
);
return
1
;
}
strcpy
(
*
config_dir
,
homedir
);
...
...
@@ -80,7 +80,7 @@ static int set_directories(char **config_dir, char **data_dir)
*
config_dir
=
(
char
*
)
malloc
(
tmpsize
+
sizeof
(
"/"
PACKAGE_NAME
"/"
));
if
(
*
config_dir
==
NULL
)
{
log_error
(
"
set_directories - s
etting config
_
dir"
);
log_error
(
"
S
etting configdir"
);
return
1
;
}
strcpy
(
*
config_dir
,
tmpchar
);
...
...
@@ -99,7 +99,7 @@ static int set_directories(char **config_dir, char **data_dir)
sizeof
(
"/.local/share/"
PACKAGE_NAME
"/"
));
if
(
*
data_dir
==
NULL
)
{
log_error
(
"
set_directories - s
etting data
_
dir"
);
log_error
(
"
S
etting datadir"
);
free
(
config_dir
);
return
1
;
}
...
...
@@ -110,7 +110,7 @@ static int set_directories(char **config_dir, char **data_dir)
*
data_dir
=
(
char
*
)
malloc
(
tmpsize
+
sizeof
(
"/"
PACKAGE_NAME
"/"
));
if
(
*
data_dir
==
NULL
)
{
log_error
(
"
set_directories - s
etting data
_
dir"
);
log_error
(
"
S
etting datadir"
);
free
(
config_dir
);
return
1
;
}
...
...
@@ -139,16 +139,15 @@ static int create_dirs(const char *config_dir, const char *data_dir)
if
(
errno
==
ENOENT
)
{
/* create */
if
(
mkdir
(
config_dir
,
S_IRWXU
))
{
log_error
(
"create_dirs - could not create "
"configuration directory %s"
,
config_dir
);
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
(
"
create_dirs - c
ould not open configuration "
log_error
(
"
C
ould not open configuration "
"directory %s"
,
config_dir
);
return
1
;
}
...
...
@@ -159,17 +158,15 @@ static int create_dirs(const char *config_dir, const char *data_dir)
if
(
errno
==
ENOENT
)
{
/* create */
if
(
mkdir
(
data_dir
,
S_IRWXU
))
{
log_error
(
"create_dirs - could not create "
"data directory %s"
,
data_dir
);
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
(
"create_dirs - could not open data "
"directory %s"
,
data_dir
);
log_error
(
"Could not open data directory %s"
,
data_dir
);
return
1
;
}
}
...
...
src/linkedlist.c
View file @
2e3b123e
...
...
@@ -216,7 +216,7 @@ linkedlist_node_t *linkedlist_insert_after(linkedlist_t *root,
new_node
=
(
linkedlist_node_t
*
)
malloc
(
sizeof
(
linkedlist_node_t
));
if
(
new_node
==
NULL
)
{
log_error
(
"
linkedlist_insert_after - malloc
"
);
log_error
(
"
Inserting a new node
"
);
return
NULL
;
}
...
...
src/neighbours.c
View file @
2e3b123e
...
...
@@ -127,6 +127,54 @@ void delete_neighbour(linkedlist_t *neighbours, struct bufferevent *bev)
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.
*
...
...
@@ -148,7 +196,6 @@ neighbour_t *find_neighbour(const linkedlist_t *neighbours,
/* bufferevents equal => neighbour found */
if
(
current_data
->
buffer_event
==
bev
)
{
/* return node's data; struct s_neighbour */
return
current_data
;
}
...
...
@@ -189,3 +236,25 @@ neighbour_t *find_neighbour_by_addr(const linkedlist_t *neighbours,
/* neighbour not found */
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
;
}
src/neighbours.h
View file @
2e3b123e
...
...
@@ -28,6 +28,9 @@
/* minimum number of peers we need to be connected to */
#define MIN_NEIGHBOURS 3
/* request for addresses */
#define NEIGHBOUR_ADDRS_REQ 0x01
/** Data type for the linkedlist of neighbours. */
typedef
struct
s_neighbour
{
/** Neighbour's IPv6 address.
...
...
@@ -37,6 +40,8 @@ typedef struct s_neighbour {
struct
bufferevent
*
buffer_event
;
/** Number of failed ping attempts -- max 3, then disconnect. */
size_t
failed_pings
;
/** A set of flags for this neighbour. */
int
flags
;
}
neighbour_t
;
neighbour_t
*
add_new_neighbour
(
linkedlist_t
*
neighbours
,
...
...
@@ -47,6 +52,9 @@ void clear_neighbours(linkedlist_t *neighbours);
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
,
const
struct
bufferevent
*
bev
);
...
...
@@ -54,4 +62,7 @@ neighbour_t *find_neighbour(const linkedlist_t *neighbours,
neighbour_t
*
find_neighbour_by_addr
(
const
linkedlist_t
*
neighbours
,
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 */
src/p2p.c
View file @
2e3b123e
...
...
@@ -48,12 +48,12 @@ static void ip_to_string(const struct in6_addr *binary_ip, char *ip)
}
/**
* Ask the neighbour for a list of
peer
s.
* Ask the neighbour for a list of
addresse
s.
*
* @param global_state Data for the event loop to work with.
* @param neighbour The neighbour to be asked.
*/
void
ask_for_
peer
s
(
neighbour_t
*
neighbour
)
static
void
ask_for_
addresse
s
(
neighbour_t
*
neighbour
)
{
struct
bufferevent
*
bev
;
...
...
@@ -64,6 +64,8 @@ void ask_for_peers(neighbour_t *neighbour)
/* send message "peers" to the neighbour, as a request
* for the list of peers; 6 is the number of bytes to be transmitted */
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)
/* allocate memory for the input message including '\0' */
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 */
if
(
evbuffer_remove
(
input
,
message
,
len
)
==
-
1
)
{
...
...
@@ -147,9 +153,12 @@ static void p2p_process(struct bufferevent *bev, void *ctx)
/* "peers" is a request for list of addresses */
}
else
if
(
strcmp
(
message
,
"peers"
)
==
0
)
{
peers_to_str
(
&
global_state
->
peers
,
response
);
/* list of
peer
s */
/* list of
addresse
s */
}
else
{
if
(
neighbour
->
flags
&
NEIGHBOUR_ADDRS_REQ
)
{
process_peers
(
global_state
,
message
);
unset_neighbour_flags
(
neighbour
,
NEIGHBOUR_ADDRS_REQ
);
}
}
if
(
response
[
0
]
!=
'\0'
)
{
...
...
@@ -192,9 +201,7 @@ static void timeout_process(linkedlist_t *neighbours,
neighbour
->
failed_pings
++
;
}
else
{
log_info
(
"timeout_process - 3 failed pings."
" Removing %s from neighbours"
,
text_ip
);
log_info
(
"%s timed out"
,
text_ip
);
delete_neighbour
(
neighbours
,
neighbour
->
buffer_event
);
}
}
...
...
@@ -239,20 +246,22 @@ static void process_pending_neighbour(global_state_t *global_state,
neighbour_t
*
neighbour
,
short
events
)
{
size_
t
available_peers_size
;
in
t
available_peers_size
;
int
needed_conns
;
neighbour_t
*
new_neighbour
;
char
text_ip
[
INET6_ADDRSTRLEN
];
available_peers_size
=
fetch_available_peers
(
&
global_state
->
peers
,
NULL
);
/* fetch peers with PEER_AVAILABLE flag set;
* no allocation with NULL parameter -> result always >=0 */
available_peers_size
=
fetch_specific_peers
(
&
global_state
->
peers
,
NULL
,
PEER_AVAILABLE
);
/* initialize text_ip */
ip_to_string
(
&
neighbour
->
addr
,
text_ip
);
/* we've successfully connected to the neighbour */
if
(
events
&
BEV_EVENT_CONNECTED
)
{
log_info
(
"process_pending_neighbour - connecting to "
"%s was SUCCESSFUL"
,
text_ip
);
log_info
(
"%s successfully connected"
,
text_ip
);
/* we've got a new neighbour;
* we can't just delete the neighbour from pending
* and add it into 'neighbours' as the delete would
...
...
@@ -268,14 +277,14 @@ static void process_pending_neighbour(global_state_t *global_state,
/* if we need more neighbours */
if
(
needed_conns
>
0
)
{
/* 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
);
}
}
/* connecting to the neighbour was unsuccessful */
}
else
{
log_
info
(
"process_pending_neighbour - connecting to "
"%s was
NOT SUCCESSFUL
"
,
text_ip
);
log_
debug
(
"process_pending_neighbour - connecting to "
"%s was
unsuccessful
"
,
text_ip
);
/* the peer is no longer a pending neighbour */
delete_neighbour
(
&
global_state
->
pending_neighbours
,
neighbour
->
buffer_event
);
...
...
@@ -299,12 +308,11 @@ static void process_neighbour(global_state_t *global_state,
ip_to_string
(
&
neighbour
->
addr
,
text_ip
);
if
(
events
&
BEV_EVENT_ERROR
)
{
log_info
(
"process_neighbour - error on bev: removing %s"
,
text_ip
);
log_info
(
"Connection error, removing %s"
,
text_ip
);
delete_neighbour
(
&
global_state
->
neighbours
,
neighbour
->
buffer_event
);
}
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
,
neighbour
->
buffer_event
);
/* timeout flag on 'bev' */
...
...
@@ -357,6 +365,7 @@ static void accept_connection(struct evconnlistener *listener,
struct
event_base
*
base
;
struct
bufferevent
*
bev
;
struct
in6_addr
*
new_addr
;
peer_t
*
new_peer
;
char
text_ip
[
INET6_ADDRSTRLEN
];
struct
timeval
timeout
;
...
...
@@ -402,9 +411,12 @@ static void accept_connection(struct evconnlistener *listener,
return
;
}
log_info
(
"
accept_connection - n
ew connection from [%s]:%d"
,
text_ip
,
log_info
(
"
N
ew connection from [%s]:%d"
,
text_ip
,
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,
global_state_t
*
global_state
=
(
struct
s_global_state
*
)
ctx
;
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 */
event_base_loopexit
(
base
,
NULL
);
...
...
@@ -449,7 +463,7 @@ int listen_init(struct evconnlistener **listener,
*
base
=
event_base_new
();
if
(
!*
base
)
{
log_error
(
"
listen_init -
event
_
base
creation failure
"
);
log_error
(
"
Creating
eventbase"
);
return
1
;
}
...
...
@@ -467,7 +481,7 @@ int listen_init(struct evconnlistener **listener,
sizeof
(
sock_addr
));
if
(
!*
listener
)
{
log_error
(
"
listen_init - evconnlistener_new_bind
"
);
log_error
(
"
Creating listener
"
);
return
1
;
}
...
...
@@ -558,7 +572,7 @@ int connect_to_addr(global_state_t *global_state,
peer
=
find_peer_by_addr
(
&
global_state
->
peers
,
addr
);
if
(
peer
!=
NULL
)
{
peer
->
is_available
=
0
;
unset_peer_flags
(
peer
,
PEER_AVAILABLE
)
;
}
/* connect to the peer; socket_connect also assigns fd */
...
...
@@ -576,16 +590,22 @@ int connect_to_addr(global_state_t *global_state,
void
add_more_connections
(
global_state_t
*
global_state
,
size_t
conns_amount
)
{
struct
in6_addr
addr
;
size_
t
available_peers_size
;
peer_t
*
available_peers
[
MAX_PEERS_SIZE
]
;
in
t
available_peers_size
;
peer_t
*
*
available_peers
;
size_t
cur_conn_attempts
=
0
;
size_t
idx
;
neighbour_t
*
neigh
;
size_t
result
;
peer_t
*
selected_peer
;
available_peers_size
=
fetch_available_peers
(
&
global_state
->
peers
,
available_peers
);
available_peers_size
=
fetch_specific_peers
(
&
global_state
->
peers
,
&
available_peers
,
PEER_AVAILABLE
);
/* if fetch_specific_peers had allocation failure */
if
(
available_peers_size
==
-
1
)
{
log_error
(
"Adding more connections"
);
return
;
}
/* only if we don't have any non-default peers available */
if
(
available_peers_size
==
0
)
{
...
...
@@ -613,7 +633,7 @@ void add_more_connections(global_state_t *global_state, size_t conns_amount)
neighbours
,
&
addr
);
assert
(
neigh
!=
NULL
);
ask_for_
peer
s
(
neigh
);
ask_for_
addresse
s
(
neigh
);
log_debug
(
"add_more_connections - "
"asking for peers"
);
/* the peer is a pending connection */
...
...
@@ -630,7 +650,7 @@ void add_more_connections(global_state_t *global_state, size_t conns_amount)
/* we need to choose 'conns_amount' of random connections */
shuffle_peers_arr
(
available_peers
,
available_peers_size
);
/* clamp to 'available_peers_size' */
if
(
conns_amount
>
available_peers_size
)
{
if
(
conns_amount
>
(
size_t
)
available_peers_size
)
{
conns_amount
=
available_peers_size
;
}
...
...
@@ -643,5 +663,6 @@ void add_more_connections(global_state_t *global_state, size_t conns_amount)
cur_conn_attempts
++
;
}
}
}
free
(
available_peers
);
}
src/p2p.h
View file @
2e3b123e
...
...
@@ -49,8 +49,6 @@ typedef struct s_global_state {
void
add_more_connections
(
global_state_t
*
global_state
,
size_t
conns_amount
);
void
ask_for_peers
(
neighbour_t
*
neighbour
);
int
connect_to_addr
(
global_state_t
*
global_state
,
const
struct
in6_addr
*
addr
);
...
...
src/peers.c
View file @
2e3b123e
...
...
@@ -37,49 +37,14 @@ void clear_peers(linkedlist_t *peers)
linkedlist_destroy
(
peers
);
}
/**
* Fetch available peers from linkedlist into an array.
*
* @param peers All peers known to us.
* @param available_peers The peers marked as available.
*
* @return >=0 The number of available peers.
*/
size_t
fetch_available_peers
(
const
linkedlist_t
*
peers
,
peer_t
*
available_peers
[
MAX_PEERS_SIZE
])
{
linkedlist_node_t
*
current_node
;
peer_t
*
current_peer
;
size_t
n
=
0
;
current_node
=
linkedlist_get_first
(
peers
);
while
(
current_node
!=
NULL
)
{
current_peer
=
(
peer_t
*
)
current_node
->
data
;
if
(
current_peer
->
is_available
)
{
/* we can use this function with 'available_peers'
* set to NULL just to get the number of available
* peers as return value
*/
if
(
available_peers
!=
NULL
)
{
available_peers
[
n
++
]
=
current_peer
;
}
else
{
n
++
;
}
}
current_node
=
linkedlist_get_next
(
peers
,
current_node
);
}
return
n
;
}
/**
* Fetch peers from file into linkedlist.
*
* @param peers_path Path to
'
peers
'
file.
* @param peers_path Path to peers file.
* @param peers Fetch loaded peers in here.
*
* @return 0 Successfully fetched.
* @return 1
Failure
.
* @return 1
Peers file could not be opened
.
*/
int
fetch_peers
(
const
char
*
peers_path
,
linkedlist_t
*
peers
)
{
...
...
@@ -88,18 +53,66 @@ int fetch_peers(const char *peers_path, linkedlist_t *peers)
peers_file
=
fopen
(
peers_path
,
"rb"
);
if
(
peers_file
==
NULL
)
{
log_
error
(
"fetch_peers - peers_file not found"
);
log_
warning
(
"Peers file not found at %"
,
peers_path
);
return
1
;
}
while
(
fread
(
&
addr
,
sizeof
(
struct
in6_addr
),
1
,
peers_file
)
==
1
)
{
add
_peer
(
peers
,
&
addr
);
save
_peer
(
peers
,
&
addr
);
}
fclose
(
peers_file
);
return
0
;
}
/**
* Fetch pointers to peers with specific flags set, into array that is being
* allocated in here.
*
* @param peers All peers known to us.
* @param output Output array of pointers to satisfying peers.
* If set to NULL, function just returns
* the number of them.
* @param flags Choose peers based on these flags.
* Fetches output with all known peers if set to 0.
*
* @return >=0 The number of satisfying peers.
* @return -1 Allocation failure.
*/
int
fetch_specific_peers
(
const
linkedlist_t
*
peers
,
peer_t
***
output
,
int
flags
)
{
linkedlist_node_t
*
current_node
;
peer_t
*
current_peer
;
size_t
n
=
0
;
if
(
output
!=
NULL
)
{
*
output
=
(
peer_t
**
)
malloc
(
linkedlist_size
(
peers
)
*
sizeof
(
peer_t
*
));
if
(
*
output
==
NULL
)
{
log_error
(
"Fetching specific peers"
);
return
-
1
;
}
}
current_node
=
linkedlist_get_first
(
peers
);
while
(
current_node
!=
NULL
)
{
current_peer
=
(
peer_t
*
)
current_node
->
data
;
/* if all specified flags are being set on this peer */
if
((
current_peer
->
flags
&
flags
)
==
flags
)
{
if
(
output
!=
NULL
)
{
(
*
output
)[
n
++
]
=
current_peer
;
}
else
{
n
++
;
}
}
current_node
=
linkedlist_get_next
(
peers
,
current_node
);