Ver código fonte

qdevice: Force send of heartbeat

Previously client was not force to use heartbeat. Because we have to be
able to detect dead client in qnetd, heartbeat setting is now forced.
Insted of set_option message, heartbeat is force to exists in init
message. This also means that
QDEVICE_NET_INSTANCE_STATE_WAITING_SET_OPTION_REPLY can be removed and
client is considered as connected after init_reply is received. So
currently, set_option is not used (but implementation of these two
messages still exists).

Signed-off-by: Jan Friesse <jfriesse@redhat.com>
Jan Friesse 10 anos atrás
pai
commit
0c9df248f8

+ 1 - 1
qdevices/Makefile.am

@@ -56,7 +56,7 @@ corosync_qdevice_SOURCES	= corosync-qdevice.c qdevice-cmap.c qdevice-instance.c
 				  msg.c msgio.c nss-sock.c tlv.c \
 				  msg.c msgio.c nss-sock.c tlv.c \
 				  qdevice-net-poll.c qdevice-net-send.c qdevice-net-votequorum.c \
 				  qdevice-net-poll.c qdevice-net-send.c qdevice-net-votequorum.c \
 				  qdevice-net-socket.c qdevice-net-nss.c qdevice-net-msg-received.c \
 				  qdevice-net-socket.c qdevice-net-nss.c qdevice-net-msg-received.c \
-				  qdevice-net-cast-vote-timer.c \
+				  qdevice-net-cast-vote-timer.c qdevice-net-echo-request-timer.c \
 				  qdevice-net-algorithm.c \
 				  qdevice-net-algorithm.c \
 				  qdevice-net-algo-test.c qdevice-net-algo-ffsplit.c \
 				  qdevice-net-algo-test.c qdevice-net-algo-ffsplit.c \
 				  qdevice-net-algo-2nodelms.c qdevice-net-algo-lms.c
 				  qdevice-net-algo-2nodelms.c qdevice-net-algo-lms.c

+ 12 - 21
qdevices/msg.c

@@ -272,7 +272,8 @@ size_t
 msg_create_init(struct dynar *msg, int add_msg_seq_number, uint32_t msg_seq_number,
 msg_create_init(struct dynar *msg, int add_msg_seq_number, uint32_t msg_seq_number,
     enum tlv_decision_algorithm_type decision_algorithm,
     enum tlv_decision_algorithm_type decision_algorithm,
     const enum msg_type *supported_msgs, size_t no_supported_msgs,
     const enum msg_type *supported_msgs, size_t no_supported_msgs,
-    const enum tlv_opt_type *supported_opts, size_t no_supported_opts, uint32_t node_id)
+    const enum tlv_opt_type *supported_opts, size_t no_supported_opts, uint32_t node_id,
+    uint32_t heartbeat_interval, const struct tlv_tie_breaker *tie_breaker)
 {
 {
 	uint16_t *u16a;
 	uint16_t *u16a;
 	int res;
 	int res;
@@ -320,6 +321,14 @@ msg_create_init(struct dynar *msg, int add_msg_seq_number, uint32_t msg_seq_numb
 		goto small_buf_err;
 		goto small_buf_err;
 	}
 	}
 
 
+	if (tlv_add_heartbeat_interval(msg, heartbeat_interval) == -1) {
+		goto small_buf_err;
+	}
+
+	if (tlv_add_tie_breaker(msg, tie_breaker) == -1) {
+		goto small_buf_err;
+	}
+
 	msg_set_len(msg, dynar_size(msg) - (MSG_TYPE_LENGTH + MSG_LENGTH_LENGTH));
 	msg_set_len(msg, dynar_size(msg) - (MSG_TYPE_LENGTH + MSG_LENGTH_LENGTH));
 
 
 	return (dynar_size(msg));
 	return (dynar_size(msg));
@@ -404,8 +413,7 @@ small_buf_err:
 
 
 size_t
 size_t
 msg_create_set_option(struct dynar *msg, int add_msg_seq_number, uint32_t msg_seq_number,
 msg_create_set_option(struct dynar *msg, int add_msg_seq_number, uint32_t msg_seq_number,
-    int add_heartbeat_interval, uint32_t heartbeat_interval,
-    int add_tie_breaker, const struct tlv_tie_breaker *tie_breaker)
+    int add_heartbeat_interval, uint32_t heartbeat_interval)
 {
 {
 
 
 	dynar_clean(msg);
 	dynar_clean(msg);
@@ -425,12 +433,6 @@ msg_create_set_option(struct dynar *msg, int add_msg_seq_number, uint32_t msg_se
 		}
 		}
 	}
 	}
 
 
-	if (add_tie_breaker) {
-		if (tlv_add_tie_breaker(msg, tie_breaker) == -1) {
-			goto small_buf_err;
-		}
-	}
-
 	msg_set_len(msg, dynar_size(msg) - (MSG_TYPE_LENGTH + MSG_LENGTH_LENGTH));
 	msg_set_len(msg, dynar_size(msg) - (MSG_TYPE_LENGTH + MSG_LENGTH_LENGTH));
 
 
 	return (dynar_size(msg));
 	return (dynar_size(msg));
@@ -441,8 +443,7 @@ small_buf_err:
 
 
 size_t
 size_t
 msg_create_set_option_reply(struct dynar *msg, int add_msg_seq_number, uint32_t msg_seq_number,
 msg_create_set_option_reply(struct dynar *msg, int add_msg_seq_number, uint32_t msg_seq_number,
-    enum tlv_decision_algorithm_type decision_algorithm, uint32_t heartbeat_interval,
-    int add_tie_breaker, const struct tlv_tie_breaker *tie_breaker)
+    uint32_t heartbeat_interval)
 {
 {
 
 
 	dynar_clean(msg);
 	dynar_clean(msg);
@@ -456,20 +457,10 @@ msg_create_set_option_reply(struct dynar *msg, int add_msg_seq_number, uint32_t
 		}
 		}
 	}
 	}
 
 
-	if (tlv_add_decision_algorithm(msg, decision_algorithm) == -1) {
-		goto small_buf_err;
-	}
-
 	if (tlv_add_heartbeat_interval(msg, heartbeat_interval) == -1) {
 	if (tlv_add_heartbeat_interval(msg, heartbeat_interval) == -1) {
 		goto small_buf_err;
 		goto small_buf_err;
 	}
 	}
 
 
-	if (add_tie_breaker) {
-		if (tlv_add_tie_breaker(msg, tie_breaker) == -1) {
-			goto small_buf_err;
-		}
-	}
-
 	msg_set_len(msg, dynar_size(msg) - (MSG_TYPE_LENGTH + MSG_LENGTH_LENGTH));
 	msg_set_len(msg, dynar_size(msg) - (MSG_TYPE_LENGTH + MSG_LENGTH_LENGTH));
 
 
 	return (dynar_size(msg));
 	return (dynar_size(msg));

+ 4 - 6
qdevices/msg.h

@@ -126,7 +126,8 @@ extern size_t		msg_create_starttls(struct dynar *msg, int add_msg_seq_number,
 extern size_t		msg_create_init(struct dynar *msg, int add_msg_seq_number,
 extern size_t		msg_create_init(struct dynar *msg, int add_msg_seq_number,
     uint32_t msg_seq_number, enum tlv_decision_algorithm_type decision_algorithm,
     uint32_t msg_seq_number, enum tlv_decision_algorithm_type decision_algorithm,
     const enum msg_type *supported_msgs, size_t no_supported_msgs,
     const enum msg_type *supported_msgs, size_t no_supported_msgs,
-    const enum tlv_opt_type *supported_opts, size_t no_supported_opts, uint32_t node_id);
+    const enum tlv_opt_type *supported_opts, size_t no_supported_opts, uint32_t node_id,
+    uint32_t heartbeat_interval, const struct tlv_tie_breaker *tie_breaker);
 
 
 extern size_t		msg_create_server_error(struct dynar *msg, int add_msg_seq_number,
 extern size_t		msg_create_server_error(struct dynar *msg, int add_msg_seq_number,
     uint32_t msg_seq_number, enum tlv_reply_error_code reply_error_code);
     uint32_t msg_seq_number, enum tlv_reply_error_code reply_error_code);
@@ -141,13 +142,10 @@ extern size_t		msg_create_init_reply(struct dynar *msg, int add_msg_seq_number,
 
 
 extern size_t		msg_create_set_option(struct dynar *msg,
 extern size_t		msg_create_set_option(struct dynar *msg,
     int add_msg_seq_number, uint32_t msg_seq_number,
     int add_msg_seq_number, uint32_t msg_seq_number,
-    int add_heartbeat_interval, uint32_t heartbeat_interval,
-    int add_tie_breaker, const struct tlv_tie_breaker *tie_breaker);
+    int add_heartbeat_interval, uint32_t heartbeat_interval);
 
 
 extern size_t		msg_create_set_option_reply(struct dynar *msg,
 extern size_t		msg_create_set_option_reply(struct dynar *msg,
-    int add_msg_seq_number, uint32_t msg_seq_number,
-    enum tlv_decision_algorithm_type decision_algorithm, uint32_t heartbeat_interval,
-    int add_tie_breaker, const struct tlv_tie_breaker *tie_breaker);
+    int add_msg_seq_number, uint32_t msg_seq_number, uint32_t heartbeat_interval);
 
 
 extern size_t		msg_create_echo_request(struct dynar *msg, int add_msg_seq_number,
 extern size_t		msg_create_echo_request(struct dynar *msg, int add_msg_seq_number,
     uint32_t msg_seq_number);
     uint32_t msg_seq_number);

+ 1 - 1
qdevices/qdevice-model-net.c

@@ -159,7 +159,7 @@ qdevice_model_net_run(struct qdevice_instance *instance)
 			break ;
 			break ;
 		}
 		}
 
 
-		qdevice_log(LOG_DEBUG, "Trying connect to qnetd server %s:%u (timeout = %u)",
+		qdevice_log(LOG_DEBUG, "Trying connect to qnetd server %s:%u (timeout = %ums)",
 		    net_instance->host_addr, net_instance->host_port, net_instance->connect_timeout);
 		    net_instance->host_addr, net_instance->host_port, net_instance->connect_timeout);
 
 
 		res = nss_sock_non_blocking_client_init(net_instance->host_addr,
 		res = nss_sock_non_blocking_client_init(net_instance->host_addr,

+ 106 - 0
qdevices/qdevice-net-echo-request-timer.c

@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2015-2016 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Jan Friesse (jfriesse@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the Red Hat, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "qdevice-net-algorithm.h"
+#include "qdevice-net-echo-request-timer.h"
+#include "qdevice-net-send.h"
+#include "qdevice-log.h"
+
+static int
+qdevice_net_echo_request_timer_callback(void *data1, void *data2)
+{
+	struct qdevice_net_instance *instance;
+
+	instance = (struct qdevice_net_instance *)data1;
+
+	if (instance->echo_reply_received_msg_seq_num !=
+	    instance->echo_request_expected_msg_seq_num) {
+		qdevice_log(LOG_ERR, "Server didn't send echo reply message on time");
+
+		if (qdevice_net_algorithm_echo_reply_not_received(instance) != 0) {
+			qdevice_log(LOG_DEBUG, "Algorithm decided to disconnect");
+
+			instance->schedule_disconnect = 1;
+			instance->disconnect_reason =
+			    QDEVICE_NET_DISCONNECT_REASON_ALGO_ECHO_REPLY_NOT_RECEIVED_ERR;
+
+			instance->echo_request_timer = NULL;
+			return (0);
+		} else {
+			qdevice_log(LOG_DEBUG, "Algorithm decided to continue send heartbeat");
+
+			return (-1);
+		}
+	}
+
+	if (qdevice_net_send_echo_request(instance) == -1) {
+		instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER;
+
+		instance->schedule_disconnect = 1;
+		instance->echo_request_timer = NULL;
+		return (0);
+	}
+
+	/*
+	 * Schedule this function callback again
+	 */
+	return (-1);
+}
+
+int
+qdevice_net_echo_request_timer_schedule(struct qdevice_net_instance *instance)
+{
+	instance->echo_request_expected_msg_seq_num = 0;
+	instance->echo_reply_received_msg_seq_num = 0;
+
+	if (instance->echo_request_timer != NULL) {
+		timer_list_delete(&instance->main_timer_list, instance->echo_request_timer);
+		instance->echo_request_timer = NULL;
+	}
+
+	qdevice_log(LOG_DEBUG, "Scheduling send of heartbeat every %"PRIu32"ms", instance->heartbeat_interval);
+	instance->echo_request_timer = timer_list_add(&instance->main_timer_list,
+	    instance->heartbeat_interval, qdevice_net_echo_request_timer_callback,
+	    (void *)instance, NULL);
+
+	if (instance->echo_request_timer == NULL) {
+		qdevice_log(LOG_ERR, "Can't schedule regular sending of heartbeat.");
+
+		instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_SCHEDULE_HB_TIMER;
+
+		return (-1);
+	}
+
+	return (0);
+}

+ 50 - 0
qdevices/qdevice-net-echo-request-timer.h

@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016-2016 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Jan Friesse (jfriesse@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the Red Hat, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _QDEVICE_NET_ECHO_REQUEST_TIMER_H_
+#define _QDEVICE_NET_ECHO_REQUEST_TIMER_H_
+
+#include "qdevice-net-instance.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int	qdevice_net_echo_request_timer_schedule(struct qdevice_net_instance *instance);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _QDEVICE_NET_ECHO_REQUEST_TIMER_H_ */

+ 10 - 1
qdevices/qdevice-net-instance.c

@@ -228,7 +228,16 @@ qdevice_net_instance_init_from_cmap(struct qdevice_instance *instance)
 	 */
 	 */
 	cast_vote_timer_interval = instance->heartbeat_interval * 0.5;
 	cast_vote_timer_interval = instance->heartbeat_interval * 0.5;
 	heartbeat_interval = instance->heartbeat_interval * 0.8;
 	heartbeat_interval = instance->heartbeat_interval * 0.8;
-
+	if (heartbeat_interval < QDEVICE_HEARTBEAT_INTERVAL_MIN) {
+		qdevice_log(LOG_WARNING, "Heartbeat interval too small %"PRIu32". Adjusting to %"PRIu32".",
+		    heartbeat_interval, QNETD_HEARTBEAT_INTERVAL_MIN);
+		heartbeat_interval = QNETD_HEARTBEAT_INTERVAL_MIN;
+	}
+	if (heartbeat_interval > QDEVICE_HEARTBEAT_INTERVAL_MAX) {
+		qdevice_log(LOG_WARNING, "Heartbeat interval too big %"PRIu32". Adjusting to %"PRIu32".",
+		    heartbeat_interval, QNETD_HEARTBEAT_INTERVAL_MAX);
+		heartbeat_interval = QNETD_HEARTBEAT_INTERVAL_MAX;
+	}
 	sync_heartbeat_interval = instance->sync_heartbeat_interval * 0.8;
 	sync_heartbeat_interval = instance->sync_heartbeat_interval * 0.8;
 
 
 	/*
 	/*

+ 0 - 1
qdevices/qdevice-net-instance.h

@@ -60,7 +60,6 @@ enum qdevice_net_instance_state {
 	QDEVICE_NET_INSTANCE_STATE_WAITING_PREINIT_REPLY,
 	QDEVICE_NET_INSTANCE_STATE_WAITING_PREINIT_REPLY,
 	QDEVICE_NET_INSTANCE_STATE_WAITING_STARTTLS_BEING_SENT,
 	QDEVICE_NET_INSTANCE_STATE_WAITING_STARTTLS_BEING_SENT,
 	QDEVICE_NET_INSTANCE_STATE_WAITING_INIT_REPLY,
 	QDEVICE_NET_INSTANCE_STATE_WAITING_INIT_REPLY,
-	QDEVICE_NET_INSTANCE_STATE_WAITING_SET_OPTION_REPLY,
 	QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS,
 	QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS,
 };
 };
 
 

+ 73 - 170
qdevices/qdevice-net-msg-received.c

@@ -38,6 +38,7 @@
 #include "qdevice-net-msg-received.h"
 #include "qdevice-net-msg-received.h"
 #include "qdevice-net-send.h"
 #include "qdevice-net-send.h"
 #include "qdevice-net-votequorum.h"
 #include "qdevice-net-votequorum.h"
+#include "qdevice-net-echo-request-timer.h"
 #include "msg.h"
 #include "msg.h"
 
 
 /*
 /*
@@ -146,6 +147,8 @@ qdevice_net_msg_received_preinit_reply(struct qdevice_net_instance *instance,
 	int res;
 	int res;
 	struct send_buffer_list_entry *send_buffer;
 	struct send_buffer_list_entry *send_buffer;
 
 
+	qdevice_log(LOG_DEBUG, "Received preinit reply msg");
+
 	if (instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_PREINIT_REPLY) {
 	if (instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_PREINIT_REPLY) {
 		qdevice_log(LOG_ERR, "Received unexpected preinit reply message. "
 		qdevice_log(LOG_ERR, "Received unexpected preinit reply message. "
 		    "Disconnecting from server");
 		    "Disconnecting from server");
@@ -229,7 +232,14 @@ qdevice_net_msg_received_init_reply(struct qdevice_net_instance *instance,
 {
 {
 	size_t zi;
 	size_t zi;
 	int res;
 	int res;
-	struct send_buffer_list_entry *send_buffer;
+	int send_config_node_list;
+	int send_membership_node_list;
+	int send_quorum_node_list;
+	enum tlv_vote vote;
+	struct tlv_ring_id tlv_rid;
+	enum tlv_quorate quorate;
+
+	qdevice_log(LOG_DEBUG, "Received init reply msg");
 
 
 	if (instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_INIT_REPLY) {
 	if (instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_INIT_REPLY) {
 		qdevice_log(LOG_ERR, "Received unexpected init reply message. "
 		qdevice_log(LOG_ERR, "Received unexpected init reply message. "
@@ -335,159 +345,6 @@ qdevice_net_msg_received_init_reply(struct qdevice_net_instance *instance,
 		return (-1);
 		return (-1);
 	}
 	}
 
 
-	/*
-	 * Send set options message
-	 */
-	send_buffer = send_buffer_list_get_new(&instance->send_buffer_list);
-	if (send_buffer == NULL) {
-		qdevice_log(LOG_ERR, "Can't allocate send list buffer for set option msg");
-
-		instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER;
-
-		return (-1);
-	}
-
-	instance->last_msg_seq_num++;
-
-	if (msg_create_set_option(&send_buffer->buffer, 1, instance->last_msg_seq_num,
-	    1, instance->heartbeat_interval, 1, &instance->tie_breaker) == 0) {
-		qdevice_log(LOG_ERR, "Can't allocate send buffer for set option msg");
-
-		instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER;
-		send_buffer_list_discard_new(&instance->send_buffer_list, send_buffer);
-
-		return (-1);
-	}
-
-	send_buffer_list_put(&instance->send_buffer_list, send_buffer);
-
-	instance->state = QDEVICE_NET_INSTANCE_STATE_WAITING_SET_OPTION_REPLY;
-
-	return (0);
-}
-
-static int
-qdevice_net_msg_received_starttls(struct qdevice_net_instance *instance,
-    const struct msg_decoded *msg)
-{
-
-	return (qdevice_net_msg_received_unexpected_msg(instance, msg, "starttls"));
-}
-
-static int
-qdevice_net_msg_received_server_error(struct qdevice_net_instance *instance,
-    const struct msg_decoded *msg)
-{
-
-	if (!msg->reply_error_code_set) {
-		qdevice_log(LOG_ERR, "Received server error without error code set. "
-		    "Disconnecting from server");
-
-		instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
-	} else {
-		qdevice_log(LOG_ERR, "Received server error %"PRIu16". "
-		    "Disconnecting from server", msg->reply_error_code);
-
-		instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_SERVER_SENT_ERROR;
-	}
-
-	return (-1);
-}
-
-static int
-qdevice_net_msg_received_set_option(struct qdevice_net_instance *instance,
-    const struct msg_decoded *msg)
-{
-
-	return (qdevice_net_msg_received_unexpected_msg(instance, msg, "set option"));
-}
-
-static int
-qdevice_net_timer_send_heartbeat(void *data1, void *data2)
-{
-	struct qdevice_net_instance *instance;
-
-	instance = (struct qdevice_net_instance *)data1;
-
-	if (instance->echo_reply_received_msg_seq_num !=
-	    instance->echo_request_expected_msg_seq_num) {
-		qdevice_log(LOG_ERR, "Server didn't send echo reply message on time");
-
-		if (qdevice_net_algorithm_echo_reply_not_received(instance) != 0) {
-			qdevice_log(LOG_DEBUG, "Algorithm decided to disconnect");
-
-			instance->schedule_disconnect = 1;
-			instance->disconnect_reason =
-			    QDEVICE_NET_DISCONNECT_REASON_ALGO_ECHO_REPLY_NOT_RECEIVED_ERR;
-
-			instance->echo_request_timer = NULL;
-			return (0);
-		} else {
-			qdevice_log(LOG_DEBUG, "Algorithm decided to continue send heartbeat");
-
-			return (-1);
-		}
-	}
-
-	if (qdevice_net_send_echo_request(instance) == -1) {
-		instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER;
-
-		instance->schedule_disconnect = 1;
-		instance->echo_request_timer = NULL;
-		return (0);
-	}
-
-	/*
-	 * Schedule this function callback again
-	 */
-	return (-1);
-}
-
-static int
-qdevice_net_msg_received_set_option_reply(struct qdevice_net_instance *instance,
-    const struct msg_decoded *msg)
-{
-	struct tlv_ring_id tlv_rid;
-	enum tlv_quorate quorate;
-	int send_config_node_list;
-	int send_membership_node_list;
-	int send_quorum_node_list;
-	enum tlv_vote vote;
-
-	if (instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_SET_OPTION_REPLY) {
-		qdevice_log(LOG_ERR, "Received unexpected set option reply message. "
-		    "Disconnecting from server");
-
-		instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG;
-
-		return (-1);
-	}
-
-	if (qdevice_net_msg_check_seq_number(instance, msg) != 0) {
-		instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
-
-		return (-1);
-	}
-
-	if (!msg->decision_algorithm_set || !msg->heartbeat_interval_set) {
-		qdevice_log(LOG_ERR, "Received set option reply message without "
-		    "required options. Disconnecting from server");
-
-		instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
-
-		return (-1);
-	}
-
-	if (msg->decision_algorithm != instance->decision_algorithm ||
-	    msg->heartbeat_interval != instance->heartbeat_interval) {
-		qdevice_log(LOG_ERR, "Server doesn't accept sent decision algorithm or "
-		    "heartbeat interval.");
-
-		instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
-
-		return (-1);
-	}
-
 	/*
 	/*
 	 * Finally fully connected so it's possible to remove connection timer
 	 * Finally fully connected so it's possible to remove connection timer
 	 */
 	 */
@@ -499,22 +356,7 @@ qdevice_net_msg_received_set_option_reply(struct qdevice_net_instance *instance,
 	/*
 	/*
 	 * Server accepted heartbeat interval -> schedule regular sending of echo request
 	 * Server accepted heartbeat interval -> schedule regular sending of echo request
 	 */
 	 */
-	if (instance->heartbeat_interval > 0) {
-		instance->echo_request_expected_msg_seq_num = 0;
-		instance->echo_reply_received_msg_seq_num = 0;
-
-		instance->echo_request_timer = timer_list_add(&instance->main_timer_list,
-		    instance->heartbeat_interval, qdevice_net_timer_send_heartbeat,
-		    (void *)instance, NULL);
-
-		if (instance->echo_request_timer == NULL) {
-			qdevice_log(LOG_ERR, "Can't schedule regular sending of heartbeat.");
-
-			instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_SCHEDULE_HB_TIMER;
-
-			return (-1);
-		}
-	}
+	qdevice_net_echo_request_timer_schedule(instance);
 
 
 	send_config_node_list = 1;
 	send_config_node_list = 1;
 	send_membership_node_list = 1;
 	send_membership_node_list = 1;
@@ -584,6 +426,67 @@ qdevice_net_msg_received_set_option_reply(struct qdevice_net_instance *instance,
 	return (0);
 	return (0);
 }
 }
 
 
+static int
+qdevice_net_msg_received_starttls(struct qdevice_net_instance *instance,
+    const struct msg_decoded *msg)
+{
+
+	return (qdevice_net_msg_received_unexpected_msg(instance, msg, "starttls"));
+}
+
+static int
+qdevice_net_msg_received_server_error(struct qdevice_net_instance *instance,
+    const struct msg_decoded *msg)
+{
+
+	if (!msg->reply_error_code_set) {
+		qdevice_log(LOG_ERR, "Received server error without error code set. "
+		    "Disconnecting from server");
+
+		instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
+	} else {
+		qdevice_log(LOG_ERR, "Received server error %"PRIu16". "
+		    "Disconnecting from server", msg->reply_error_code);
+
+		instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_SERVER_SENT_ERROR;
+	}
+
+	return (-1);
+}
+
+static int
+qdevice_net_msg_received_set_option(struct qdevice_net_instance *instance,
+    const struct msg_decoded *msg)
+{
+
+	return (qdevice_net_msg_received_unexpected_msg(instance, msg, "set option"));
+}
+
+static int
+qdevice_net_msg_received_set_option_reply(struct qdevice_net_instance *instance,
+    const struct msg_decoded *msg)
+{
+
+	if (instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS) {
+		qdevice_log(LOG_ERR, "Received unexpected set option reply message. "
+		    "Disconnecting from server");
+
+		instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG;
+
+		return (-1);
+	}
+
+	if (qdevice_net_msg_check_seq_number(instance, msg) != 0) {
+		instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING;
+
+		return (-1);
+	}
+
+	qdevice_net_echo_request_timer_schedule(instance);
+
+	return (0);
+}
+
 static int
 static int
 qdevice_net_msg_received_echo_request(struct qdevice_net_instance *instance,
 qdevice_net_msg_received_echo_request(struct qdevice_net_instance *instance,
     const struct msg_decoded *msg)
     const struct msg_decoded *msg)

+ 2 - 1
qdevices/qdevice-net-send.c

@@ -115,7 +115,8 @@ qdevice_net_send_init(struct qdevice_net_instance *instance)
 	if (msg_create_init(&send_buffer->buffer, 1, instance->last_msg_seq_num,
 	if (msg_create_init(&send_buffer->buffer, 1, instance->last_msg_seq_num,
 	    instance->decision_algorithm,
 	    instance->decision_algorithm,
 	    supported_msgs, no_supported_msgs, supported_opts, no_supported_opts,
 	    supported_msgs, no_supported_msgs, supported_opts, no_supported_opts,
-	    instance->qdevice_instance_ptr->node_id) == 0) {
+	    instance->qdevice_instance_ptr->node_id, instance->heartbeat_interval,
+	    &instance->tie_breaker) == 0) {
 		qdevice_log(LOG_ERR, "Can't allocate send buffer for init msg");
 		qdevice_log(LOG_ERR, "Can't allocate send buffer for init msg");
 
 
 		send_buffer_list_discard_new(&instance->send_buffer_list, send_buffer);
 		send_buffer_list_discard_new(&instance->send_buffer_list, send_buffer);

+ 8 - 6
qdevices/qnet-config.h

@@ -60,8 +60,8 @@ extern "C" {
 #define QNETD_DEFAULT_TLS_SUPPORTED		TLV_TLS_SUPPORTED
 #define QNETD_DEFAULT_TLS_SUPPORTED		TLV_TLS_SUPPORTED
 #define QNETD_DEFAULT_TLS_CLIENT_CERT_REQUIRED	1
 #define QNETD_DEFAULT_TLS_CLIENT_CERT_REQUIRED	1
 
 
-#define QNETD_HEARTBEAT_INTERVAL_MIN		1000
-#define QNETD_HEARTBEAT_INTERVAL_MAX		200000
+#define QNETD_HEARTBEAT_INTERVAL_MIN		(1*1000)
+#define QNETD_HEARTBEAT_INTERVAL_MAX		(2*60*1000)
 
 
 #define QNETD_LOCK_FILE				LOCALSTATEDIR"/run/corosync-qnetd.pid"
 #define QNETD_LOCK_FILE				LOCALSTATEDIR"/run/corosync-qnetd.pid"
 
 
@@ -81,11 +81,13 @@ extern "C" {
 
 
 #define QDEVICE_NET_DEFAULT_TLS_SUPPORTED	TLV_TLS_SUPPORTED
 #define QDEVICE_NET_DEFAULT_TLS_SUPPORTED	TLV_TLS_SUPPORTED
 
 
-#define QNETD_DEFAULT_TIE_BREAKER_MODE		TLV_TIE_BREAKER_MODE_LOWEST
-#define QDEVICE_NET_DEFAULT_TIE_BREAKER_MODE	QNETD_DEFAULT_TIE_BREAKER_MODE
+#define QDEVICE_NET_DEFAULT_TIE_BREAKER_MODE	TLV_TIE_BREAKER_MODE_LOWEST
 
 
-#define QDEVICE_NET_MIN_CONNECT_TIMEOUT		1L
-#define QDEVICE_NET_MAX_CONNECT_TIMEOUT		(1000*60*10L)
+#define QDEVICE_HEARTBEAT_INTERVAL_MIN		QNETD_HEARTBEAT_INTERVAL_MIN
+#define QDEVICE_HEARTBEAT_INTERVAL_MAX		QNETD_HEARTBEAT_INTERVAL_MAX
+
+#define QDEVICE_NET_MIN_CONNECT_TIMEOUT		(1*1000L)
+#define QDEVICE_NET_MAX_CONNECT_TIMEOUT		(2*60*1000L)
 
 
 /*
 /*
  * Decision algorithms supported by qnetd
  * Decision algorithms supported by qnetd

+ 29 - 9
qdevices/qnetd-client-msg-received.c

@@ -287,6 +287,32 @@ qnetd_client_msg_received_init(struct qnetd_instance *instance, struct qnetd_cli
 		client->node_id = msg->node_id;
 		client->node_id = msg->node_id;
 	}
 	}
 
 
+	if (reply_error_code == TLV_REPLY_ERROR_CODE_NO_ERROR && !msg->heartbeat_interval_set) {
+		qnetd_log(LOG_ERR, "Received init message without heartbeat interval set. "
+		    "Sending error reply.");
+
+		reply_error_code = TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION;
+	} else {
+		if (msg->heartbeat_interval < QNETD_HEARTBEAT_INTERVAL_MIN ||
+		    msg->heartbeat_interval > QNETD_HEARTBEAT_INTERVAL_MAX) {
+			qnetd_log(LOG_ERR, "Client requested invalid heartbeat interval %u. "
+			    "Sending error reply.", msg->heartbeat_interval);
+
+			reply_error_code = TLV_REPLY_ERROR_CODE_INVALID_HEARTBEAT_INTERVAL;
+		} else {
+			client->heartbeat_interval = msg->heartbeat_interval;
+		}
+	}
+
+	if (reply_error_code == TLV_REPLY_ERROR_CODE_NO_ERROR && !msg->tie_breaker_set) {
+		qnetd_log(LOG_ERR, "Received init message without tie-breaker set. "
+		    "Sending error reply.");
+
+		reply_error_code = TLV_REPLY_ERROR_CODE_DOESNT_CONTAIN_REQUIRED_OPTION;
+	} else {
+		memcpy(&client->tie_breaker, &msg->tie_breaker, sizeof(msg->tie_breaker));
+	}
+
 	if (msg->supported_messages != NULL) {
 	if (msg->supported_messages != NULL) {
 		/*
 		/*
 		 * Client sent supported messages. For now this is ignored but in the future
 		 * Client sent supported messages. For now this is ignored but in the future
@@ -448,9 +474,8 @@ qnetd_client_msg_received_set_option(struct qnetd_instance *instance, struct qne
 		/*
 		/*
 		 * Check if heartbeat interval is valid
 		 * Check if heartbeat interval is valid
 		 */
 		 */
-		if (msg->heartbeat_interval != 0 &&
-		    (msg->heartbeat_interval < QNETD_HEARTBEAT_INTERVAL_MIN ||
-		    msg->heartbeat_interval > QNETD_HEARTBEAT_INTERVAL_MAX)) {
+		if (msg->heartbeat_interval < QNETD_HEARTBEAT_INTERVAL_MIN ||
+		    msg->heartbeat_interval > QNETD_HEARTBEAT_INTERVAL_MAX) {
 			qnetd_log(LOG_ERR, "Client requested invalid heartbeat interval %u. "
 			qnetd_log(LOG_ERR, "Client requested invalid heartbeat interval %u. "
 			    "Sending error reply.", msg->heartbeat_interval);
 			    "Sending error reply.", msg->heartbeat_interval);
 
 
@@ -465,10 +490,6 @@ qnetd_client_msg_received_set_option(struct qnetd_instance *instance, struct qne
 		client->heartbeat_interval = msg->heartbeat_interval;
 		client->heartbeat_interval = msg->heartbeat_interval;
 	}
 	}
 
 
-	if (msg->tie_breaker_set) {
-		memcpy(&client->tie_breaker, &msg->tie_breaker, sizeof(msg->tie_breaker));
-	}
-
 	send_buffer = send_buffer_list_get_new(&client->send_buffer_list);
 	send_buffer = send_buffer_list_get_new(&client->send_buffer_list);
 	if (send_buffer == NULL) {
 	if (send_buffer == NULL) {
 		qnetd_log(LOG_ERR, "Can't alloc set option reply msg from list. "
 		qnetd_log(LOG_ERR, "Can't alloc set option reply msg from list. "
@@ -478,8 +499,7 @@ qnetd_client_msg_received_set_option(struct qnetd_instance *instance, struct qne
 	}
 	}
 
 
 	if (msg_create_set_option_reply(&send_buffer->buffer, msg->seq_number_set, msg->seq_number,
 	if (msg_create_set_option_reply(&send_buffer->buffer, msg->seq_number_set, msg->seq_number,
-	    client->decision_algorithm, client->heartbeat_interval,
-	    msg->tie_breaker_set, &msg->tie_breaker) == -1) {
+	    client->heartbeat_interval) == -1) {
 		qnetd_log(LOG_ERR, "Can't alloc set option reply msg. "
 		qnetd_log(LOG_ERR, "Can't alloc set option reply msg. "
 		    "Disconnecting client connection.");
 		    "Disconnecting client connection.");
 
 

+ 0 - 1
qdevices/qnetd-client.c

@@ -54,7 +54,6 @@ qnetd_client_init(struct qnetd_client *client, PRFileDesc *sock, PRNetAddr *addr
 	node_list_init(&client->configuration_node_list);
 	node_list_init(&client->configuration_node_list);
 	node_list_init(&client->last_membership_node_list);
 	node_list_init(&client->last_membership_node_list);
 	node_list_init(&client->last_quorum_node_list);
 	node_list_init(&client->last_quorum_node_list);
-	client->tie_breaker.mode = QNETD_DEFAULT_TIE_BREAKER_MODE;
 	client->main_timer_list = main_timer_list;
 	client->main_timer_list = main_timer_list;
 }
 }