2 * Copyright (c) 2015-2019 Red Hat, Inc.
6 * Author: Jan Friesse (jfriesse@redhat.com)
8 * This software licensed under BSD license, the text of which follows:
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
13 * - Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 * - Neither the name of the Red Hat, Inc. nor the names of its
19 * contributors may be used to endorse or promote products derived from this
20 * software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
36 #include "qdevice-net-algorithm.h"
37 #include "qdevice-net-cast-vote-timer.h"
38 #include "qdevice-net-heuristics.h"
39 #include "qdevice-net-msg-received.h"
40 #include "qdevice-net-send.h"
41 #include "qdevice-net-votequorum.h"
42 #include "qdevice-net-echo-request-timer.h"
47 * -1 - Incompatible tls combination
52 qdevice_net_msg_received_check_tls_compatibility(enum tlv_tls_supported server_tls
,
53 enum tlv_tls_supported client_tls
)
60 case TLV_TLS_UNSUPPORTED
:
62 case TLV_TLS_UNSUPPORTED
: res
= 0; break;
63 case TLV_TLS_SUPPORTED
: res
= 0; break;
64 case TLV_TLS_REQUIRED
: res
= -1; break;
67 case TLV_TLS_SUPPORTED
:
69 case TLV_TLS_UNSUPPORTED
: res
= 0; break;
70 case TLV_TLS_SUPPORTED
: res
= 1; break;
71 case TLV_TLS_REQUIRED
: res
= 1; break;
74 case TLV_TLS_REQUIRED
:
76 case TLV_TLS_UNSUPPORTED
: res
= -1; break;
77 case TLV_TLS_SUPPORTED
: res
= 1; break;
78 case TLV_TLS_REQUIRED
: res
= 1; break;
87 qdevice_net_msg_received_log_msg_decode_error(int ret
)
92 log(LOG_WARNING
, "Received message with option with invalid length");
95 log(LOG_CRIT
, "Can't allocate memory");
98 log(LOG_WARNING
, "Received inconsistent msg (tlv len > msg size)");
101 log(LOG_ERR
, "Received message with option with invalid value");
104 log(LOG_ERR
, "Unknown error occurred when decoding message");
110 qdevice_net_msg_received_unexpected_msg(struct qdevice_net_instance
*instance
,
111 const struct msg_decoded
*msg
, const char *msg_str
)
114 log(LOG_ERR
, "Received unexpected %s message. Disconnecting from server",
117 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG
;
123 qdevice_net_msg_received_init(struct qdevice_net_instance
*instance
,
124 const struct msg_decoded
*msg
)
127 return (qdevice_net_msg_received_unexpected_msg(instance
, msg
, "init"));
131 qdevice_net_msg_received_preinit(struct qdevice_net_instance
*instance
,
132 const struct msg_decoded
*msg
)
135 return (qdevice_net_msg_received_unexpected_msg(instance
, msg
, "preinit"));
139 qdevice_net_msg_check_seq_number(struct qdevice_net_instance
*instance
,
140 const struct msg_decoded
*msg
)
143 if (!msg
->seq_number_set
|| msg
->seq_number
!= instance
->last_msg_seq_num
) {
144 log(LOG_ERR
, "Received message doesn't contain seq_number or "
145 "it's not expected one.");
154 qdevice_net_msg_received_preinit_reply(struct qdevice_net_instance
*instance
,
155 const struct msg_decoded
*msg
)
158 struct send_buffer_list_entry
*send_buffer
;
160 log(LOG_DEBUG
, "Received preinit reply msg");
162 if (instance
->state
!= QDEVICE_NET_INSTANCE_STATE_WAITING_PREINIT_REPLY
) {
163 log(LOG_ERR
, "Received unexpected preinit reply message. "
164 "Disconnecting from server");
166 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG
;
171 if (qdevice_net_msg_check_seq_number(instance
, msg
) != 0) {
172 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING
;
180 if (!msg
->tls_supported_set
|| !msg
->tls_client_cert_required_set
) {
181 log(LOG_ERR
, "Required tls_supported or tls_client_cert_required "
184 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING
;
189 res
= qdevice_net_msg_received_check_tls_compatibility(msg
->tls_supported
, instance
->tls_supported
);
191 log(LOG_ERR
, "Incompatible tls configuration (server %u client %u)",
192 msg
->tls_supported
, instance
->tls_supported
);
194 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_INCOMPATIBLE_TLS
;
197 } else if (res
== 1) {
201 send_buffer
= send_buffer_list_get_new(&instance
->send_buffer_list
);
202 if (send_buffer
== NULL
) {
203 log(LOG_ERR
, "Can't allocate send list buffer for "
206 instance
->disconnect_reason
=
207 QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER
;
212 instance
->last_msg_seq_num
++;
213 if (msg_create_starttls(&send_buffer
->buffer
, 1,
214 instance
->last_msg_seq_num
) == 0) {
215 log(LOG_ERR
, "Can't allocate send buffer for starttls msg");
217 instance
->disconnect_reason
=
218 QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER
;
220 send_buffer_list_discard_new(&instance
->send_buffer_list
, send_buffer
);
224 send_buffer_list_put(&instance
->send_buffer_list
, send_buffer
);
226 instance
->state
= QDEVICE_NET_INSTANCE_STATE_WAITING_STARTTLS_BEING_SENT
;
227 } else if (res
== 0) {
228 if (qdevice_net_send_init(instance
) != 0) {
229 instance
->disconnect_reason
=
230 QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER
;
240 qdevice_net_msg_received_init_reply(struct qdevice_net_instance
*instance
,
241 const struct msg_decoded
*msg
)
245 enum qdevice_heuristics_mode active_heuristics_mode
;
247 log(LOG_DEBUG
, "Received init reply msg");
249 if (instance
->state
!= QDEVICE_NET_INSTANCE_STATE_WAITING_INIT_REPLY
) {
250 log(LOG_ERR
, "Received unexpected init reply message. "
251 "Disconnecting from server");
253 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG
;
258 if (qdevice_net_msg_check_seq_number(instance
, msg
) != 0) {
259 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING
;
264 if (!msg
->reply_error_code_set
) {
265 log(LOG_ERR
, "Received init reply message without error code."
266 "Disconnecting from server");
268 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING
;
273 if (msg
->reply_error_code
!= TLV_REPLY_ERROR_CODE_NO_ERROR
) {
274 log(LOG_ERR
, "Received init reply message with error code %"PRIu16
". "
275 "Disconnecting from server", msg
->reply_error_code
);
277 if (msg
->reply_error_code
== TLV_REPLY_ERROR_CODE_DUPLICATE_NODE_ID
) {
278 log(LOG_ERR
, "Duplicate node id may be result of server not yet "
279 "accepted this node disconnect. Retry again.");
280 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_SERVER_SENT_DUPLICATE_NODE_ID_ERROR
;
281 } else if (msg
->reply_error_code
== TLV_REPLY_ERROR_CODE_TIE_BREAKER_DIFFERS_FROM_OTHER_NODES
) {
282 log(LOG_ERR
, "Configured tie-breaker differs in cluster. This may be "
283 "result of server not yet accepted this node disconnect. Retry again.");
284 instance
->disconnect_reason
=
285 QDEVICE_NET_DISCONNECT_REASON_SERVER_SENT_TIE_BREAKER_DIFFERS_FROM_OTHER_NODES_ERROR
;
286 } else if (msg
->reply_error_code
== TLV_REPLY_ERROR_CODE_ALGORITHM_DIFFERS_FROM_OTHER_NODES
) {
287 log(LOG_ERR
, "Configured algorithm differs in cluster. This may be "
288 "result of server not yet accepted this node disconnect. Retry again.");
289 instance
->disconnect_reason
=
290 QDEVICE_NET_DISCONNECT_REASON_SERVER_SENT_ALGORITHM_DIFFERS_FROM_OTHER_NODES_ERROR
;
292 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_SERVER_SENT_ERROR
;
298 if (!msg
->server_maximum_request_size_set
|| !msg
->server_maximum_reply_size_set
) {
299 log(LOG_ERR
, "Required maximum_request_size or maximum_reply_size "
302 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING
;
307 if (msg
->supported_messages
== NULL
|| msg
->supported_options
== NULL
) {
308 log(LOG_ERR
, "Required supported messages or supported options "
311 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING
;
316 if (msg
->supported_decision_algorithms
== NULL
) {
317 log(LOG_ERR
, "Required supported decision algorithms option is unset");
319 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING
;
324 if (msg
->server_maximum_request_size
< instance
->advanced_settings
->net_min_msg_send_size
) {
326 "Server accepts maximum %zu bytes message but this client minimum "
327 "is %zu bytes.", msg
->server_maximum_request_size
,
328 instance
->advanced_settings
->net_min_msg_send_size
);
330 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_INCOMPATIBLE_MSG_SIZE
;
334 if (msg
->server_maximum_reply_size
> instance
->advanced_settings
->net_max_msg_receive_size
) {
336 "Server may send message up to %zu bytes message but this client maximum "
337 "is %zu bytes.", msg
->server_maximum_reply_size
,
338 instance
->advanced_settings
->net_max_msg_receive_size
);
340 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_INCOMPATIBLE_MSG_SIZE
;
345 * Change buffer sizes
347 dynar_set_max_size(&instance
->receive_buffer
, msg
->server_maximum_reply_size
);
348 send_buffer_list_set_max_buffer_size(&instance
->send_buffer_list
,
349 msg
->server_maximum_request_size
);
353 * Check if server supports decision algorithm we need
357 for (zi
= 0; zi
< msg
->no_supported_decision_algorithms
&& !res
; zi
++) {
358 if (msg
->supported_decision_algorithms
[zi
] == instance
->decision_algorithm
) {
364 log(LOG_ERR
, "Server doesn't support required decision algorithm");
366 instance
->disconnect_reason
=
367 QDEVICE_NET_DISCONNECT_REASON_SERVER_DOESNT_SUPPORT_REQUIRED_ALGORITHM
;
373 * Check if server supports heuristics
376 for (zi
= 0; zi
< msg
->no_supported_options
; zi
++) {
377 if (msg
->supported_options
[zi
] == TLV_OPT_HEURISTICS
) {
382 instance
->server_supports_heuristics
= res
;
385 active_heuristics_mode
= instance
->qdevice_instance_ptr
->heuristics_instance
.mode
;
387 if (active_heuristics_mode
== QDEVICE_HEURISTICS_MODE_ENABLED
||
388 active_heuristics_mode
== QDEVICE_HEURISTICS_MODE_SYNC
) {
389 log(LOG_ERR
, "Heuristics are enabled but not supported by server");
391 instance
->disconnect_reason
=
392 QDEVICE_NET_DISCONNECT_REASON_SERVER_DOESNT_SUPPORT_REQUIRED_OPT
;
399 * Finally fully connected so it's possible to remove connection timer
401 if (instance
->connect_timer
!= NULL
) {
402 timer_list_delete(&instance
->main_timer_list
, instance
->connect_timer
);
403 instance
->connect_timer
= NULL
;
407 * Server accepted heartbeat interval -> schedule regular sending of echo request
409 if (qdevice_net_echo_request_timer_schedule(instance
) != 0) {
414 * Run heuristics (even when it is disabled, undefined result is ok, rest of sending
415 * is handled by qdevice_net_connect_heuristics_exec_result_callback
417 if (qdevice_net_heuristics_exec_after_connect(instance
) != 0) {
425 qdevice_net_msg_received_starttls(struct qdevice_net_instance
*instance
,
426 const struct msg_decoded
*msg
)
429 return (qdevice_net_msg_received_unexpected_msg(instance
, msg
, "starttls"));
433 qdevice_net_msg_received_server_error(struct qdevice_net_instance
*instance
,
434 const struct msg_decoded
*msg
)
437 if (!msg
->reply_error_code_set
) {
438 log(LOG_ERR
, "Received server error without error code set. "
439 "Disconnecting from server");
441 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING
;
443 log(LOG_ERR
, "Received server error %"PRIu16
". "
444 "Disconnecting from server", msg
->reply_error_code
);
446 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_SERVER_SENT_ERROR
;
453 qdevice_net_msg_received_set_option(struct qdevice_net_instance
*instance
,
454 const struct msg_decoded
*msg
)
457 return (qdevice_net_msg_received_unexpected_msg(instance
, msg
, "set option"));
461 qdevice_net_msg_received_set_option_reply(struct qdevice_net_instance
*instance
,
462 const struct msg_decoded
*msg
)
465 if (instance
->state
!= QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS
) {
466 log(LOG_ERR
, "Received unexpected set option reply message. "
467 "Disconnecting from server");
469 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG
;
474 if (qdevice_net_msg_check_seq_number(instance
, msg
) != 0) {
475 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING
;
480 if (qdevice_net_echo_request_timer_schedule(instance
) != 0) {
488 qdevice_net_msg_received_echo_request(struct qdevice_net_instance
*instance
,
489 const struct msg_decoded
*msg
)
492 return (qdevice_net_msg_received_unexpected_msg(instance
, msg
, "echo request"));
496 qdevice_net_msg_received_echo_reply(struct qdevice_net_instance
*instance
,
497 const struct msg_decoded
*msg
)
500 if (!msg
->seq_number_set
) {
501 log(LOG_ERR
, "Received echo reply message doesn't contain seq_number.");
503 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING
;
507 if (msg
->seq_number
!= instance
->echo_request_expected_msg_seq_num
) {
508 log(LOG_WARNING
, "Received echo reply message seq_number is not expected one.");
511 if (qdevice_net_algorithm_echo_reply_received(instance
, msg
->seq_number
,
512 msg
->seq_number
== instance
->echo_request_expected_msg_seq_num
) != 0) {
513 log(LOG_DEBUG
, "Algorithm returned error. Disconnecting");
515 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_ALGO_ECHO_REPLY_RECEIVED_ERR
;
519 instance
->echo_reply_received_msg_seq_num
= msg
->seq_number
;
520 instance
->last_echo_reply_received_time
= time(NULL
);
526 qdevice_net_msg_received_node_list(struct qdevice_net_instance
*instance
,
527 const struct msg_decoded
*msg
)
530 return (qdevice_net_msg_received_unexpected_msg(instance
, msg
, "node list"));
534 qdevice_net_msg_received_node_list_reply(struct qdevice_net_instance
*instance
,
535 const struct msg_decoded
*msg
)
538 enum tlv_vote result_vote
;
541 int ring_id_is_valid
;
543 if (instance
->state
!= QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS
) {
544 log(LOG_ERR
, "Received unexpected node list reply message. "
545 "Disconnecting from server");
547 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG
;
551 if (!msg
->vote_set
|| !msg
->seq_number_set
|| !msg
->node_list_type_set
) {
552 log(LOG_ERR
, "Received node list reply message without "
553 "required options. Disconnecting from server");
555 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING
;
559 if (!msg
->ring_id_set
) {
560 log(LOG_ERR
, "Received node list reply message "
561 "without ring id set. Disconnecting from server");
563 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING
;
569 switch (msg
->node_list_type
) {
570 case TLV_NODE_LIST_TYPE_INITIAL_CONFIG
: str
= "initial config"; break;
571 case TLV_NODE_LIST_TYPE_CHANGED_CONFIG
: str
= "changed config"; break;
572 case TLV_NODE_LIST_TYPE_MEMBERSHIP
: str
="membership"; break;
573 case TLV_NODE_LIST_TYPE_QUORUM
: str
="quorum"; break;
575 * Default is not defined intentionally. Compiler shows warning when new node list type
581 log(LOG_CRIT
, "qdevice_net_msg_received_node_list_reply fatal error. "
582 "Unhandled node_list_type (debug output)");
586 log(LOG_DEBUG
, "Received %s node list reply", str
);
587 log(LOG_DEBUG
, " seq = "UTILS_PRI_MSG_SEQ
, msg
->seq_number
);
588 log(LOG_DEBUG
, " vote = %s", tlv_vote_to_str(msg
->vote
));
589 log(LOG_DEBUG
, " ring id = ("UTILS_PRI_RING_ID
")",
590 msg
->ring_id
.node_id
, msg
->ring_id
.seq
);
595 result_vote
= msg
->vote
;
597 if (!tlv_ring_id_eq(&msg
->ring_id
, &instance
->last_sent_ring_id
)) {
598 ring_id_is_valid
= 0;
599 log(LOG_DEBUG
, "Received node list reply with old ring id.");
601 ring_id_is_valid
= 1;
605 switch (msg
->node_list_type
) {
606 case TLV_NODE_LIST_TYPE_INITIAL_CONFIG
:
607 case TLV_NODE_LIST_TYPE_CHANGED_CONFIG
:
609 res
= qdevice_net_algorithm_config_node_list_reply_received(instance
,
610 msg
->seq_number
, (msg
->node_list_type
== TLV_NODE_LIST_TYPE_INITIAL_CONFIG
),
611 &msg
->ring_id
, ring_id_is_valid
, &result_vote
);
613 case TLV_NODE_LIST_TYPE_MEMBERSHIP
:
615 res
= qdevice_net_algorithm_membership_node_list_reply_received(instance
,
616 msg
->seq_number
, &msg
->ring_id
, ring_id_is_valid
, &result_vote
);
618 case TLV_NODE_LIST_TYPE_QUORUM
:
620 res
= qdevice_net_algorithm_quorum_node_list_reply_received(instance
,
621 msg
->seq_number
, &msg
->ring_id
, ring_id_is_valid
, &result_vote
);
624 * Default is not defined intentionally. Compiler shows warning when new node list type
629 if (!case_processed
) {
630 log(LOG_CRIT
, "qdevice_net_msg_received_node_list_reply fatal error. "
631 "Unhandled node_list_type (algorithm call)");
636 log(LOG_DEBUG
, "Algorithm returned error. Disconnecting.");
638 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_ALGO_NODE_LIST_REPLY_ERR
;
641 log(LOG_DEBUG
, "Algorithm result vote is %s", tlv_vote_to_str(result_vote
));
644 if (qdevice_net_cast_vote_timer_update(instance
, result_vote
) != 0) {
645 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_CANT_SCHEDULE_VOTING_TIMER
;
653 qdevice_net_msg_received_ask_for_vote(struct qdevice_net_instance
*instance
,
654 const struct msg_decoded
*msg
)
657 return (qdevice_net_msg_received_unexpected_msg(instance
, msg
, "ask for vote"));
661 qdevice_net_msg_received_ask_for_vote_reply(struct qdevice_net_instance
*instance
,
662 const struct msg_decoded
*msg
)
664 enum tlv_vote result_vote
;
665 int ring_id_is_valid
;
667 if (instance
->state
!= QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS
) {
668 log(LOG_ERR
, "Received unexpected ask for vote reply message. "
669 "Disconnecting from server");
671 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG
;
675 if (!msg
->vote_set
|| !msg
->seq_number_set
|| !msg
->ring_id_set
) {
676 log(LOG_ERR
, "Received ask for vote reply message without "
677 "required options. Disconnecting from server");
679 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING
;
683 log(LOG_DEBUG
, "Received ask for vote reply");
684 log(LOG_DEBUG
, " seq = "UTILS_PRI_MSG_SEQ
, msg
->seq_number
);
685 log(LOG_DEBUG
, " vote = %s", tlv_vote_to_str(msg
->vote
));
686 log(LOG_DEBUG
, " ring id = ("UTILS_PRI_RING_ID
")",
687 msg
->ring_id
.node_id
, msg
->ring_id
.seq
);
689 result_vote
= msg
->vote
;
691 if (!tlv_ring_id_eq(&msg
->ring_id
, &instance
->last_sent_ring_id
)) {
692 ring_id_is_valid
= 0;
693 log(LOG_DEBUG
, "Received ask for vote reply with old ring id.");
695 ring_id_is_valid
= 1;
698 if (qdevice_net_algorithm_ask_for_vote_reply_received(instance
, msg
->seq_number
,
699 &msg
->ring_id
, ring_id_is_valid
, &result_vote
) != 0) {
700 log(LOG_DEBUG
, "Algorithm returned error. Disconnecting.");
702 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_ALGO_ASK_FOR_VOTE_REPLY_ERR
;
705 log(LOG_DEBUG
, "Algorithm result vote is %s", tlv_vote_to_str(result_vote
));
708 if (qdevice_net_cast_vote_timer_update(instance
, result_vote
) != 0) {
709 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_CANT_SCHEDULE_VOTING_TIMER
;
717 qdevice_net_msg_received_vote_info(struct qdevice_net_instance
*instance
,
718 const struct msg_decoded
*msg
)
720 struct send_buffer_list_entry
*send_buffer
;
721 enum tlv_vote result_vote
;
722 int ring_id_is_valid
;
724 if (instance
->state
!= QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS
) {
725 log(LOG_ERR
, "Received unexpected vote info message. "
726 "Disconnecting from server");
728 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG
;
732 if (!msg
->vote_set
|| !msg
->seq_number_set
|| !msg
->ring_id_set
) {
733 log(LOG_ERR
, "Received node list reply message without "
734 "required options. Disconnecting from server");
735 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING
;
739 log(LOG_DEBUG
, "Received vote info");
740 log(LOG_DEBUG
, " seq = "UTILS_PRI_MSG_SEQ
, msg
->seq_number
);
741 log(LOG_DEBUG
, " vote = %s", tlv_vote_to_str(msg
->vote
));
742 log(LOG_DEBUG
, " ring id = ("UTILS_PRI_RING_ID
")",
743 msg
->ring_id
.node_id
, msg
->ring_id
.seq
);
745 result_vote
= msg
->vote
;
747 if (!tlv_ring_id_eq(&msg
->ring_id
, &instance
->last_sent_ring_id
)) {
748 ring_id_is_valid
= 0;
749 log(LOG_DEBUG
, "Received vote info with old ring id.");
751 ring_id_is_valid
= 1;
754 if (qdevice_net_algorithm_vote_info_received(instance
, msg
->seq_number
,
755 &msg
->ring_id
, ring_id_is_valid
, &result_vote
) != 0) {
756 log(LOG_DEBUG
, "Algorithm returned error. Disconnecting.");
758 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_ALGO_VOTE_INFO_ERR
;
761 log(LOG_DEBUG
, "Algorithm result vote is %s", tlv_vote_to_str(result_vote
));
764 if (qdevice_net_cast_vote_timer_update(instance
, result_vote
) != 0) {
765 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_CANT_SCHEDULE_VOTING_TIMER
;
770 * Create reply message
772 send_buffer
= send_buffer_list_get_new(&instance
->send_buffer_list
);
773 if (send_buffer
== NULL
) {
774 log(LOG_ERR
, "Can't allocate send list buffer for "
775 "vote info reply msg");
777 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER
;
781 if (msg_create_vote_info_reply(&send_buffer
->buffer
, msg
->seq_number
) == 0) {
782 log(LOG_ERR
, "Can't allocate send buffer for "
783 "vote info reply list msg");
785 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER
;
786 send_buffer_list_discard_new(&instance
->send_buffer_list
, send_buffer
);
790 send_buffer_list_put(&instance
->send_buffer_list
, send_buffer
);
796 qdevice_net_msg_received_vote_info_reply(struct qdevice_net_instance
*instance
,
797 const struct msg_decoded
*msg
)
800 return (qdevice_net_msg_received_unexpected_msg(instance
, msg
, "vote info reply"));
804 qdevice_net_msg_received_heuristics_change(struct qdevice_net_instance
*instance
,
805 const struct msg_decoded
*msg
)
808 return (qdevice_net_msg_received_unexpected_msg(instance
, msg
, "heuristics change"));
812 qdevice_net_msg_received_heuristics_change_reply(struct qdevice_net_instance
*instance
,
813 const struct msg_decoded
*msg
)
815 enum tlv_vote result_vote
;
816 int ring_id_is_valid
;
818 if (instance
->state
!= QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS
) {
819 log(LOG_ERR
, "Received unexpected heuristics change reply message. "
820 "Disconnecting from server");
822 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG
;
826 if (!msg
->vote_set
|| !msg
->seq_number_set
|| !msg
->ring_id_set
||
827 msg
->heuristics
== TLV_HEURISTICS_UNDEFINED
) {
828 log(LOG_ERR
, "Received heuristics change reply message without "
829 "required options. Disconnecting from server");
831 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_REQUIRED_OPTION_MISSING
;
835 log(LOG_DEBUG
, "Received heuristics change reply");
836 log(LOG_DEBUG
, " seq = "UTILS_PRI_MSG_SEQ
, msg
->seq_number
);
837 log(LOG_DEBUG
, " vote = %s", tlv_vote_to_str(msg
->vote
));
838 log(LOG_DEBUG
, " ring id = ("UTILS_PRI_RING_ID
")",
839 msg
->ring_id
.node_id
, msg
->ring_id
.seq
);
840 log(LOG_DEBUG
, " heuristics = %s", tlv_heuristics_to_str(msg
->heuristics
));
842 result_vote
= msg
->vote
;
844 if (!tlv_ring_id_eq(&msg
->ring_id
, &instance
->last_sent_ring_id
)) {
845 ring_id_is_valid
= 0;
846 log(LOG_DEBUG
, "Received heuristics change reply with old ring id.");
848 ring_id_is_valid
= 1;
851 if (qdevice_net_algorithm_heuristics_change_reply_received(instance
, msg
->seq_number
,
852 &msg
->ring_id
, ring_id_is_valid
, msg
->heuristics
, &result_vote
) != 0) {
853 log(LOG_DEBUG
, "Algorithm returned error. Disconnecting.");
855 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_ALGO_HEURISTICS_CHANGE_REPLY_ERR
;
858 log(LOG_DEBUG
, "Algorithm result vote is %s", tlv_vote_to_str(result_vote
));
861 if (qdevice_net_cast_vote_timer_update(instance
, result_vote
) != 0) {
862 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_CANT_SCHEDULE_VOTING_TIMER
;
870 qdevice_net_msg_received(struct qdevice_net_instance
*instance
)
872 struct msg_decoded msg
;
877 msg_decoded_init(&msg
);
879 res
= msg_decode(&instance
->receive_buffer
, &msg
);
882 * Error occurred. Disconnect.
884 qdevice_net_msg_received_log_msg_decode_error(res
);
885 log(LOG_ERR
, "Disconnecting from server");
886 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_MSG_DECODE_ERROR
;
898 ret_val
= qdevice_net_msg_received_init(instance
, &msg
);
900 case MSG_TYPE_PREINIT
:
902 ret_val
= qdevice_net_msg_received_preinit(instance
, &msg
);
904 case MSG_TYPE_PREINIT_REPLY
:
906 ret_val
= qdevice_net_msg_received_preinit_reply(instance
, &msg
);
908 case MSG_TYPE_STARTTLS
:
910 ret_val
= qdevice_net_msg_received_starttls(instance
, &msg
);
912 case MSG_TYPE_SERVER_ERROR
:
914 ret_val
= qdevice_net_msg_received_server_error(instance
, &msg
);
916 case MSG_TYPE_INIT_REPLY
:
918 ret_val
= qdevice_net_msg_received_init_reply(instance
, &msg
);
920 case MSG_TYPE_SET_OPTION
:
922 ret_val
= qdevice_net_msg_received_set_option(instance
, &msg
);
924 case MSG_TYPE_SET_OPTION_REPLY
:
926 ret_val
= qdevice_net_msg_received_set_option_reply(instance
, &msg
);
928 case MSG_TYPE_ECHO_REQUEST
:
930 ret_val
= qdevice_net_msg_received_echo_request(instance
, &msg
);
932 case MSG_TYPE_ECHO_REPLY
:
934 ret_val
= qdevice_net_msg_received_echo_reply(instance
, &msg
);
936 case MSG_TYPE_NODE_LIST
:
938 ret_val
= qdevice_net_msg_received_node_list(instance
, &msg
);
940 case MSG_TYPE_NODE_LIST_REPLY
:
942 ret_val
= qdevice_net_msg_received_node_list_reply(instance
, &msg
);
944 case MSG_TYPE_ASK_FOR_VOTE
:
946 ret_val
= qdevice_net_msg_received_ask_for_vote(instance
, &msg
);
948 case MSG_TYPE_ASK_FOR_VOTE_REPLY
:
950 ret_val
= qdevice_net_msg_received_ask_for_vote_reply(instance
, &msg
);
952 case MSG_TYPE_VOTE_INFO
:
954 ret_val
= qdevice_net_msg_received_vote_info(instance
, &msg
);
956 case MSG_TYPE_VOTE_INFO_REPLY
:
958 ret_val
= qdevice_net_msg_received_vote_info_reply(instance
, &msg
);
960 case MSG_TYPE_HEURISTICS_CHANGE
:
962 ret_val
= qdevice_net_msg_received_heuristics_change(instance
, &msg
);
964 case MSG_TYPE_HEURISTICS_CHANGE_REPLY
:
966 ret_val
= qdevice_net_msg_received_heuristics_change_reply(instance
, &msg
);
968 * Default is not defined intentionally. Compiler shows warning when msg type is added
972 if (!msg_processed
) {
973 log(LOG_ERR
, "Received unsupported message %u. "
974 "Disconnecting from server", msg
.type
);
975 instance
->disconnect_reason
= QDEVICE_NET_DISCONNECT_REASON_UNEXPECTED_MSG
;
980 msg_decoded_destroy(&msg
);