mirror of
https://github.com/Sanae6/SmoOnlineServer.git
synced 2024-11-25 04:35:18 +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 be 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 now, remove the old object and add the new object to the collection.
This commit is contained in:
parent
391d020385
commit
9e6c312c8e
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);
|
||||||
|
@ -83,4 +94,4 @@ public class Client : IDisposable {
|
||||||
public override int GetHashCode() {
|
public override int GetHashCode() {
|
||||||
return Id.GetHashCode(); //relies upon same info as == operator.
|
return Id.GetHashCode(); //relies upon same info as == operator.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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