0
0
Fork 0
mirror of https://github.com/Sanae6/SmoOnlineServer.git synced 2024-11-22 03:05:16 +00:00

fix: on reconnect do not disconnect the new client

Currently when a client connects that is already there,
the old socket is closed, and the code tries to reuse the existing client object by exchanging its socket.

Reusing the same client object and just changing its socket does cause issues though with copies of the client in other threads.
In the situations that I could reproduce, it always disconnected both sockets, the old one and then the new one.

Instead I make a copy of the client object, use the new socket, remove the old object and add the new object to the collection.

(cherry picked from commit 9e6c312c8e)
This commit is contained in:
Robin C. Ladiges 2022-09-03 23:04:01 +02:00 committed by Sanae
parent 6285abfc4e
commit 69cef89953
2 changed files with 22 additions and 23 deletions

View file

@ -28,6 +28,17 @@ public class Client : IDisposable {
Logger = new Logger("Unknown User"); Logger = new Logger("Unknown User");
} }
// copy Client to use existing data for a new reconnected connection with a new socket
public Client(Client other, Socket socket) {
Metadata = other.Metadata;
Connected = other.Connected;
CurrentCostume = other.CurrentCostume;
Id = other.Id;
Socket = socket;
Server = other.Server;
Logger = other.Logger;
}
public void Dispose() { public void Dispose() {
if (Socket?.Connected is true) if (Socket?.Connected is true)
Socket.Disconnect(false); Socket.Disconnect(false);

View file

@ -180,32 +180,21 @@ public class Server {
goto disconnect; goto disconnect;
} }
bool firstConn = false; bool firstConn = true;
switch (connect.ConnectionType) { switch (connect.ConnectionType) {
case ConnectPacket.ConnectionTypes.FirstConnection: { case ConnectPacket.ConnectionTypes.FirstConnection:
firstConn = true;
if (FindExistingClient(header.Id) is { } newClient) {
if (newClient.Connected) {
newClient.Logger.Info($"Disconnecting already connected client {newClient.Socket?.RemoteEndPoint} for {client.Socket?.RemoteEndPoint}");
newClient.Dispose();
}
newClient.Socket = client.Socket;
client = newClient;
}
break;
}
case ConnectPacket.ConnectionTypes.Reconnecting: { case ConnectPacket.ConnectionTypes.Reconnecting: {
client.Id = header.Id; client.Id = header.Id;
if (FindExistingClient(header.Id) is { } newClient) { if (FindExistingClient(header.Id) is { } oldClient) {
if (newClient.Connected) { firstConn = false;
newClient.Logger.Info($"Disconnecting already connected client {newClient.Socket?.RemoteEndPoint} for {client.Socket?.RemoteEndPoint}"); client = new Client(oldClient, socket);
newClient.Dispose(); Clients.Remove(oldClient);
Clients.Add(client);
if (oldClient.Connected) {
oldClient.Logger.Info($"Disconnecting already connected client {oldClient.Socket?.RemoteEndPoint} for {client.Socket?.RemoteEndPoint}");
oldClient.Dispose();
} }
newClient.Socket = client.Socket;
client = newClient;
} else { } else {
firstConn = true;
connect.ConnectionType = ConnectPacket.ConnectionTypes.FirstConnection; connect.ConnectionType = ConnectPacket.ConnectionTypes.FirstConnection;
} }
@ -222,7 +211,6 @@ public class Server {
List<Client> toDisconnect = Clients.FindAll(c => c.Id == header.Id && c.Connected && c.Socket != null); List<Client> toDisconnect = Clients.FindAll(c => c.Id == header.Id && c.Connected && c.Socket != null);
Clients.RemoveAll(c => c.Id == header.Id); Clients.RemoveAll(c => c.Id == header.Id);
client.Id = header.Id;
Clients.Add(client); Clients.Add(client);
Parallel.ForEachAsync(toDisconnect, (c, token) => c.Socket!.DisconnectAsync(false, token)); Parallel.ForEachAsync(toDisconnect, (c, token) => c.Socket!.DisconnectAsync(false, token));