@@ -3416,6 +3416,7 @@ namespace eosio {
3416
3416
peer_fork_db_head_block_num = msg.fork_db_head_num ;
3417
3417
fc::unique_lock g_conn ( conn_mtx );
3418
3418
last_handshake_recv = msg;
3419
+ auto c_time = last_handshake_sent.time ;
3419
3420
g_conn.unlock ();
3420
3421
3421
3422
set_state (connection_state::connected);
@@ -3459,7 +3460,35 @@ namespace eosio {
3459
3460
fc::unique_lock g_check_conn ( check->conn_mtx );
3460
3461
fc_dlog ( logger, " dup check: connected ${c}, ${l} =? ${r}" ,
3461
3462
(" c" , check->connected ())(" l" , check->last_handshake_recv .node_id )(" r" , msg.node_id ) );
3462
- return check->connected () && check->last_handshake_recv .node_id == msg.node_id ;
3463
+ if (check->connected () && check->last_handshake_recv .node_id == msg.node_id ) {
3464
+ if (net_version < proto_dup_goaway_resolution || msg.network_version < proto_dup_goaway_resolution) {
3465
+ // It's possible that both peers could arrive here at relatively the same time, so
3466
+ // we need to avoid the case where they would both tell a different connection to go away.
3467
+ // Using the sum of the initial handshake times of the two connections, we will
3468
+ // arbitrarily (but consistently between the two peers) keep one of them.
3469
+
3470
+ auto check_time = check->last_handshake_sent .time + check->last_handshake_recv .time ;
3471
+ g_check_conn.unlock ();
3472
+ if (msg.time + c_time <= check_time)
3473
+ return false ;
3474
+ } else if (net_version < proto_dup_node_id_goaway || msg.network_version < proto_dup_node_id_goaway) {
3475
+ if (listen_address < msg.p2p_address ) {
3476
+ fc_dlog ( logger, " listen_address '${lhs}' < msg.p2p_address '${rhs}'" ,
3477
+ (" lhs" , listen_address)( " rhs" , msg.p2p_address ) );
3478
+ // only the connection from lower p2p_address to higher p2p_address will be considered as a duplicate,
3479
+ // so there is no chance for both connections to be closed
3480
+ return false ;
3481
+ }
3482
+ } else if (my_impl->node_id < msg.node_id ) {
3483
+ fc_dlog ( logger, " not duplicate, my_impl->node_id '${lhs}' < msg.node_id '${rhs}'" ,
3484
+ (" lhs" , my_impl->node_id )(" rhs" , msg.node_id ) );
3485
+ // only the connection from lower node_id to higher node_id will be considered as a duplicate,
3486
+ // so there is no chance for both connections to be closed
3487
+ return false ;
3488
+ }
3489
+ return true ;
3490
+ }
3491
+ return false ;
3463
3492
};
3464
3493
if (my_impl->connections .any_of_connections (std::move (is_duplicate))) {
3465
3494
peer_dlog ( this , " sending go_away duplicate, msg.p2p_address: ${add}" , (" add" , msg.p2p_address ) );
0 commit comments