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:
parent
6285abfc4e
commit
69cef89953
2 changed files with 22 additions and 23 deletions
|
@ -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);
|
||||||
|
|
|
@ -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));
|
||||||
|
|
Loading…
Reference in a new issue