summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2015-11-18 03:44:26 +0100
committerMatthias Schiffer <mschiffer@universe-factory.net>2015-11-18 03:44:26 +0100
commit5b1d1a36df766dd60eb68b24a5edf4229b68e564 (patch)
treeca098c7f7c8c2044c39752c7bf7bfa0511804738
parent16e2b0213b54991d9f493d4c0ee7efca18436427 (diff)
downloadfastd-5b1d1a36df766dd60eb68b24a5edf4229b68e564.tar
fastd-5b1d1a36df766dd60eb68b24a5edf4229b68e564.zip
Unify periodic handshakes and peer maintenance
-rw-r--r--src/build.h.in6
-rw-r--r--src/peer.c147
-rw-r--r--src/peer.h22
-rw-r--r--src/task.c4
-rw-r--r--src/types.h3
5 files changed, 98 insertions, 84 deletions
diff --git a/src/build.h.in b/src/build.h.in
index 9b4727e..503348b 100644
--- a/src/build.h.in
+++ b/src/build.h.in
@@ -111,6 +111,12 @@
#define MAX_CONFIG_DEPTH @MAX_CONFIG_DEPTH_NUM@
+/** The default handshake interval */
+#define DEFAULT_HANDSHAKE_INTERVAL 20000 /* 20 seconds */
+
+/** The default handshake interval jitter */
+#define DEFAULT_HANDSHAKE_JITTER 2500 /* 2.5 seconds */
+
/** The interval of periodic maintenance tasks */
#define MAINTENANCE_INTERVAL 10000 /* 10 seconds */
diff --git a/src/peer.c b/src/peer.c
index 22339b4..8b2dfdb 100644
--- a/src/peer.c
+++ b/src/peer.c
@@ -256,6 +256,36 @@ void fastd_peer_reset_socket(fastd_peer_t *peer) {
return;
}
+/** Schedules the peer maintenance task (or removes the scheduled task if there's nothing to do) */
+static void schedule_peer_task(fastd_peer_t *peer) {
+ fastd_timeout_t timeout = fastd_timeout_min(peer->reset_timeout,
+ fastd_timeout_min(peer->keepalive_timeout,
+ peer->next_handshake));
+
+ if (timeout == fastd_timeout_inv) {
+ pr_debug2("Removing scheduled task for %P", peer);
+ fastd_task_unschedule(&peer->task);
+ }
+ else if (fastd_task_timeout(&peer->task) > timeout) {
+ pr_debug2("Replacing scheduled task for %P", peer);
+ fastd_task_unschedule(&peer->task);
+ fastd_task_schedule(&peer->task, TASK_TYPE_PEER, timeout);
+ }
+ else {
+ pr_debug2("Keeping scheduled task for %P", peer);
+ }
+}
+
+/** Sets the timeout for the next handshake without actually rescheduling */
+static void set_next_handshake(fastd_peer_t *peer, int delay) {
+ peer->next_handshake = ctx.now + delay;
+}
+
+/** Sets the timeout for the next handshake to the default delay and jitter without actually rescheduling */
+static void set_next_handshake_default(fastd_peer_t *peer) {
+ set_next_handshake(peer, fastd_peer_handshake_default_rand());
+}
+
/**
Schedules a handshake after the given delay
@@ -263,8 +293,8 @@ void fastd_peer_reset_socket(fastd_peer_t *peer) {
@param delay the delay in milliseconds
*/
void fastd_peer_schedule_handshake(fastd_peer_t *peer, int delay) {
- fastd_peer_unschedule_handshake(peer);
- fastd_task_schedule(&peer->handshake_task, TASK_TYPE_HANDSHAKE, ctx.now + delay);
+ set_next_handshake(peer, delay);
+ schedule_peer_task(peer);
}
/** Checks if the peer group \e group1 lies in \e group2 */
@@ -313,7 +343,6 @@ static void reset_peer(fastd_peer_t *peer) {
VECTOR_RESIZE(ctx.eth_addrs, VECTOR_LEN(ctx.eth_addrs)-deleted);
- fastd_peer_unschedule_handshake(peer);
fastd_task_unschedule(&peer->task);
fastd_peer_hashtable_remove(peer);
@@ -364,23 +393,6 @@ void fastd_peer_handle_resolve(fastd_peer_t *peer, fastd_remote_t *remote, size_
init_handshake(peer);
}
-/** Schedules the peer maintenance task (or removes the scheduled task if there's nothing to do) */
-static void schedule_peer_task(fastd_peer_t *peer) {
- fastd_timeout_t timeout = fastd_timeout_min(peer->reset_timeout, peer->keepalive_timeout);
- if (timeout == fastd_timeout_inv) {
- pr_debug2("Removing scheduled task for %P", peer);
- fastd_task_unschedule(&peer->task);
- }
- else if (fastd_task_timeout(&peer->task) > timeout) {
- pr_debug2("Replacing scheduled task for %P", peer);
- fastd_task_unschedule(&peer->task);
- fastd_task_schedule(&peer->task, TASK_TYPE_PEER, timeout);
- }
- else {
- pr_debug2("Keeping scheduled task for %P", peer);
- }
-}
-
/** Initializes a peer */
static void setup_peer(fastd_peer_t *peer) {
if (VECTOR_LEN(peer->remotes) == 0) {
@@ -415,13 +427,12 @@ static void setup_peer(fastd_peer_t *peer) {
peer->verify_valid_timeout = ctx.now;
#endif
+ peer->next_handshake = fastd_timeout_inv;
peer->reset_timeout = fastd_timeout_inv;
peer->keepalive_timeout = fastd_timeout_inv;
- if (fastd_peer_is_dynamic(peer)) {
+ if (fastd_peer_is_dynamic(peer))
peer->reset_timeout = ctx.now;
- schedule_peer_task(peer);
- }
if (!fastd_peer_is_enabled(peer))
/* Keep the peer in STATE_INACTIVE */
@@ -447,7 +458,7 @@ static void setup_peer(fastd_peer_t *peer) {
if (next_remote->hostname) {
peer->state = STATE_RESOLVING;
fastd_resolve_peer(peer, next_remote);
- fastd_peer_schedule_handshake_default(peer);
+ set_next_handshake_default(peer);
}
else {
init_handshake(peer);
@@ -456,6 +467,8 @@ static void setup_peer(fastd_peer_t *peer) {
else {
peer->state = STATE_PASSIVE;
}
+
+ schedule_peer_task(peer);
}
/**
@@ -842,47 +855,6 @@ static void send_handshake(fastd_peer_t *peer, fastd_remote_t *next_remote) {
conf.protocol->handshake_init(peer->sock, &peer->local_address, &peer->address, peer);
}
-/** Sends a handshake to one peer, if a scheduled handshake is due */
-void fastd_peer_handle_handshake_task(fastd_task_t *task) {
- fastd_peer_t *peer = container_of(task, fastd_peer_t, handshake_task);
-
- fastd_peer_schedule_handshake_default(peer);
-
- if (!fastd_peer_may_connect(peer)) {
- if (peer->next_remote != -1) {
- pr_debug("temporarily disabling handshakes with %P", peer);
- peer->next_remote = -1;
- }
-
- return;
- }
-
- fastd_remote_t *next_remote = fastd_peer_get_next_remote(peer);
-
- if (next_remote || fastd_peer_is_established(peer)) {
- send_handshake(peer, next_remote);
-
- if (fastd_peer_is_established(peer))
- return;
-
- peer->state = STATE_HANDSHAKE;
-
- if (++next_remote->current_address < next_remote->n_addresses)
- return;
-
- peer->next_remote++;
- }
-
- if (peer->next_remote < 0 || (size_t)peer->next_remote >= VECTOR_LEN(peer->remotes))
- peer->next_remote = 0;
-
- next_remote = fastd_peer_get_next_remote(peer);
- next_remote->current_address = 0;
-
- if (next_remote->hostname)
- fastd_resolve_peer(peer, next_remote);
-}
-
/** Marks a peer as established */
bool fastd_peer_set_established(fastd_peer_t *peer) {
if (fastd_peer_is_established(peer))
@@ -963,6 +935,45 @@ bool fastd_peer_find_by_eth_addr(const fastd_eth_addr_t addr, fastd_peer_t **pee
return true;
}
+/** Sends a handshake to one peer, if a scheduled handshake is due */
+static void handle_task_handshake(fastd_peer_t *peer) {
+ set_next_handshake_default(peer);
+
+ if (!fastd_peer_may_connect(peer)) {
+ if (peer->next_remote != -1) {
+ pr_debug("temporarily disabling handshakes with %P", peer);
+ peer->next_remote = -1;
+ }
+
+ return;
+ }
+
+ fastd_remote_t *next_remote = fastd_peer_get_next_remote(peer);
+
+ if (next_remote || fastd_peer_is_established(peer)) {
+ send_handshake(peer, next_remote);
+
+ if (fastd_peer_is_established(peer))
+ return;
+
+ peer->state = STATE_HANDSHAKE;
+
+ if (++next_remote->current_address < next_remote->n_addresses)
+ return;
+
+ peer->next_remote++;
+ }
+
+ if (peer->next_remote < 0 || (size_t)peer->next_remote >= VECTOR_LEN(peer->remotes))
+ peer->next_remote = 0;
+
+ next_remote = fastd_peer_get_next_remote(peer);
+ next_remote->current_address = 0;
+
+ if (next_remote->hostname)
+ fastd_resolve_peer(peer, next_remote);
+}
+
/**
Performs maintenance tasks for a peer
@@ -972,9 +983,6 @@ bool fastd_peer_find_by_eth_addr(const fastd_eth_addr_t addr, fastd_peer_t **pee
void fastd_peer_handle_task(fastd_task_t *task) {
fastd_peer_t *peer = container_of(task, fastd_peer_t, task);
- if (!fastd_peer_is_dynamic(peer) && !fastd_peer_is_established(peer))
- return;
-
/* check for peer timeout */
if (fastd_timed_out(peer->reset_timeout)) {
if (fastd_peer_is_dynamic(peer))
@@ -991,6 +999,9 @@ void fastd_peer_handle_task(fastd_task_t *task) {
conf.protocol->send(peer, fastd_buffer_alloc(0, conf.min_encrypt_head_space, conf.min_encrypt_tail_space));
}
+ if (fastd_timed_out(peer->next_handshake))
+ handle_task_handshake(peer);
+
schedule_peer_task(peer);
}
diff --git a/src/peer.h b/src/peer.h
index 27894f5..88e192b 100644
--- a/src/peer.h
+++ b/src/peer.h
@@ -90,13 +90,14 @@ struct fastd_peer {
fastd_peer_state_t state; /**< The peer's state */
- fastd_task_t handshake_task; /**< Entry in the handshake queue */
+ fastd_task_t task; /**< Task queue entry for periodic maintenance tasks */
+
+ fastd_timeout_t next_handshake; /**< The time of the next handshake */
fastd_timeout_t last_handshake_timeout; /**< No handshakes are sent to the peer until this timeout has occured to avoid flooding the peer */
fastd_timeout_t last_handshake_response_timeout; /**< All handshakes from last_handshake_address will be ignored until this timeout has occured */
fastd_timeout_t establish_handshake_timeout; /**< A timeout during which all handshakes for this peer will be ignored after a new connection has been established */
int64_t established; /**< The time this peer connection has been established */
- fastd_task_t task; /**< Task queue entry for periodic maintenance tasks */
fastd_timeout_t reset_timeout; /**< The timeout after which the peer is reset */
fastd_timeout_t keepalive_timeout; /**< The timeout after which a keepalive is sent to the peer */
@@ -153,7 +154,6 @@ void fastd_peer_exec_shell_command(const fastd_shell_command_t *command, const f
void fastd_peer_eth_addr_add(fastd_peer_t *peer, fastd_eth_addr_t addr);
bool fastd_peer_find_by_eth_addr(const fastd_eth_addr_t addr, fastd_peer_t **peer);
-void fastd_peer_handle_handshake_task(fastd_task_t *task);
void fastd_peer_handle_task(fastd_task_t *task);
void fastd_peer_eth_addr_cleanup(void);
void fastd_peer_reset_all(void);
@@ -173,18 +173,20 @@ static inline uint16_t fastd_peer_address_get_port(const fastd_peer_address_t *a
}
}
-/**
- Schedules a handshake with the default delay and jitter
+/** Returns a random value in the range DEFAULT_HANDSHAKE_INTERVAL +/- DEFAULT_HANDSHAKE_JITTER */
+static inline int fastd_peer_handshake_default_rand(void) {
+ return fastd_rand(DEFAULT_HANDSHAKE_INTERVAL-DEFAULT_HANDSHAKE_JITTER,
+ DEFAULT_HANDSHAKE_INTERVAL+DEFAULT_HANDSHAKE_JITTER);
+}
- The default relay is between 17.5 and 22.5 seconds
-*/
+/** Schedules a handshake with the default delay and jitter */
static inline void fastd_peer_schedule_handshake_default(fastd_peer_t *peer) {
- fastd_peer_schedule_handshake(peer, fastd_rand(17500, 22500));
+ fastd_peer_schedule_handshake(peer, fastd_peer_handshake_default_rand());
}
/** Cancels a scheduled handshake */
static inline void fastd_peer_unschedule_handshake(fastd_peer_t *peer) {
- fastd_task_unschedule(&peer->handshake_task);
+ peer->next_handshake = fastd_timeout_inv;
}
#ifdef WITH_DYNAMIC_PEERS
@@ -205,7 +207,7 @@ static inline void fastd_peer_set_verified(fastd_peer_t *peer, bool ok) {
/** Checks if there's a handshake queued for the peer */
static inline bool fastd_peer_handshake_scheduled(fastd_peer_t *peer) {
- return fastd_task_scheduled(&peer->handshake_task);
+ return (peer->next_handshake != fastd_timeout_inv);
}
/** Checks if a peer is floating (is has at least one floating remote or no remotes at all) */
diff --git a/src/task.c b/src/task.c
index 079fc4a..8a95b06 100644
--- a/src/task.c
+++ b/src/task.c
@@ -51,10 +51,6 @@ static void handle_task(void) {
maintenance();
break;
- case TASK_TYPE_HANDSHAKE:
- fastd_peer_handle_handshake_task(task);
- break;
-
case TASK_TYPE_PEER:
fastd_peer_handle_task(task);
break;
diff --git a/src/types.h b/src/types.h
index edc84f8..e29943c 100644
--- a/src/types.h
+++ b/src/types.h
@@ -89,8 +89,7 @@ typedef enum fastd_poll_type {
typedef enum fastd_task_type {
TASK_TYPE_UNSPEC = 0, /**< Unspecified task type */
TASK_TYPE_MAINTENANCE, /**< Scheduled maintenance */
- TASK_TYPE_HANDSHAKE, /**< Scheduled handshake */
- TASK_TYPE_PEER, /**< Peer maintenance */
+ TASK_TYPE_PEER, /**< Peer maintenance (handshake, reset, keepalive) */
} fastd_task_type_t;