Opened 9 years ago

Last modified 8 years ago

#3264 closed enhancement

Better timeout handling — at Initial Version

Reported by: elexis Owned by:
Priority: Should Have Milestone: Alpha 20
Component: Network Keywords: patch
Cc: Patch:

Description

Refs #69 Enhance Multiplayer Experience, #2854 Extensive lag may cause disconnections

Problem: When a client drops, the game hangs for up to 30 seconds sometimes. The game appears to be paused and no one knows what's going on (although you can be sure that someone is dropping after like 10 seconds).

Fix: (1) Some seconds after the last turn was processed, a message should be displayed for all clients that we are waiting for. (2) The maximum timeout duration could be reduced from 30 to 10-20 seconds.


Reproduce timeout pauses: Without modifying 0ad, I could reproduce a 5 to 8 second timeout, where the game appears to be paused for that duration. You need to start a game with another client and then kill that client with

kill -9 <pid>

To get the correct process ID use:

pidof pyrogenesis

Following the timeout model of enet (see below), the 30 second timeout can only be reproduced if you have actual lag.


Technical Background: Currently the client network timeouts are not set in 0ad, i.e. the default values of the enet library are used. They are hardcoded in enet.h:

   ENET_PEER_TIMEOUT_LIMIT                = 32,
   ENET_PEER_TIMEOUT_MINIMUM              = 5000,
   ENET_PEER_TIMEOUT_MAXIMUM              = 30000,

The documentation doesn't have too much information. The code can be obtained from http://enet.bespin.org/Downloads.html.

In peer.c you can find the following method to change the timeout settings for each peer:

/** Sets the timeout parameters for a peer.

    The timeout parameter control how and when a peer will timeout from a failure to acknowledge
    reliable traffic. Timeout values use an exponential backoff mechanism, where if a reliable
    packet is not acknowledge within some multiple of the average RTT plus a variance tolerance, 
    the timeout will be doubled until it reaches a set limit. If the timeout is thus at this
    limit and reliable packets have been sent but not acknowledged within a certain minimum time 
    period, the peer will be disconnected. Alternatively, if reliable packets have been sent
    but not acknowledged for a certain maximum time period, the peer will be disconnected regardless
    of the current timeout limit value.
    
    @param peer the peer to adjust
    @param timeoutLimit the timeout limit; defaults to ENET_PEER_TIMEOUT_LIMIT if 0
    @param timeoutMinimum the timeout minimum; defaults to ENET_PEER_TIMEOUT_MINIMUM if 0
    @param timeoutMaximum the timeout maximum; defaults to ENET_PEER_TIMEOUT_MAXIMUM if 0
*/

Therefore timeouts can be changed in NetServer.cppin the function CNetServerWorker::RunStep, for the case ENET_EVENT_TYPE_CONNECT by adding for example:

enet_peer_timeout(event.peer, 0, 0, 10000);

The timeout logic can be found in protocol.c.

If I understand the matter correctly, the client will be disconnected after 5 seconds if he had good latency before disconnecting. If he already had bad latency then enet will wait up to 30 seconds.

Change History (0)

Note: See TracTickets for help on using tickets.