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