Skip to content
Snippets Groups Projects
Unverified Commit 0ada3823 authored by Michal 'vorner' Vaner's avatar Michal 'vorner' Vaner
Browse files

Reclaim a connection on reconnect

Don't let the client wait too long when it reconnects because of a
broken connection.
parent 53432513
No related branches found
No related tags found
No related merge requests found
......@@ -562,6 +562,11 @@ static void handle_buffer(struct uplink *uplink) {
uplink->auth_status = AUTHENTICATED; // We are authenticated if the server writes to us
} else {
if (command == 'C' && uplink->auth_status == NOT_STARTED) {
// The server is sending a challenge.
// We send a „sesssion ID“ ‒ our PID. This way, the server will know if it's the same process reconnecting and drop the old connection sooner.
ulog(LLOG_DEBUG, "Sending session ID\n");
uint32_t sid = htonl(getpid());
uplink_send_message(uplink, 'S', &sid, sizeof sid);
ulog(LLOG_DEBUG, "Sending login info\n");
// Prepare data
#define HALF_SIZE 16
......
......@@ -124,3 +124,9 @@ which means the login failed.
Any of the above commands from above are forbidden before the
authentication step is complete.
During the authentication phase, the client may send an `S` message,
followed by a 4-byte integer. The integer is a session ID which serves
to distinguish a reconnect of the same client from the situation when
two instances on the same client machine fight over the connection.
Currently, the PID of the client is used.
......@@ -66,6 +66,7 @@ class ClientConn(twisted.protocols.basic.Int32StringReceiver):
self.__plugin_versions = {}
self.MAX_LENGTH = 1024 * 1024 * 1024 # A gigabyte should be enough
self.last_pong = time.time()
self.session_id = None
def has_plugin(self, plugin_name):
return plugin_name in self.__available_plugins
......@@ -187,6 +188,12 @@ class ClientConn(twisted.protocols.basic.Int32StringReceiver):
else:
login_failure('Asked for session before loging in')
return
elif msg == 'S':
if len(params) != 4:
logger.warn("Wrong session ID length on client %s: %s", self.cid(), len(params))
return
(self.session_id,) = struct.unpack("!I", params)
logger.debug("Client %s uses session ID %s", self.cid(), self.session_id)
return
elif msg == 'P': # Ping. Answer pong.
self.sendString('p' + params)
......
......@@ -171,6 +171,8 @@ class Plugins:
if self.__clients[client.cid()].last_pong + 900 < time.time():
# The client seems connected, but it didn't pong for really long time, kill it
logger.warn('Stray connection from %s, dropping old connection', client.cid())
if client.session_id is not None and self.__clients[client.cid()].session_id == client.session_id:
logger.warn('Taking over previous connection from session %s on client %s', client.session_id, client.cid())
else:
logger.warn("%s already connected, dropping connection", client.cid())
return False
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment