packet buffering and fixes

This commit is contained in:
Spirtix 2023-09-09 16:12:53 +02:00
parent 3b93594c8b
commit d162ce80aa
8 changed files with 90 additions and 31 deletions

View File

@ -9,6 +9,12 @@ class SetPositionVariablesHandler : ICommandHandler {
Client client;
NetworkObject spvData;
public void Handle(Client client, NetworkObject receivedObject) {
if (client.Room == null) {
Console.WriteLine($"SPV Missing Room IID: {client.ClientID}");
client.Send(NetworkObject.WrapObject(0, 1006, new NetworkObject()).Serialize());
client.SheduleDisconnect();
return;
}
this.client = client;
spvData = receivedObject;
UpdatePositionVariables();
@ -52,11 +58,9 @@ class SetPositionVariablesHandler : ICommandHandler {
NetworkPacket packet = NetworkObject.WrapObject(1, 13, cmd).Serialize();
lock (client.Room.roomLock) {
foreach (var roomClient in client.Room.Clients) {
if (roomClient != client)
roomClient.Send(packet);
}
}
}
}

View File

@ -81,10 +81,8 @@ class SetUserVariablesHandler : ICommandHandler {
data.Add("vl", vl);
NetworkPacket packet = NetworkObject.WrapObject(0, 12, data).Serialize();
lock (client.Room.roomLock) {
foreach (var roomClient in client.Room.Clients)
roomClient.Send(packet);
}
NetworkObject cmd = new();
cmd.Add("c", "SUV");

View File

@ -10,12 +10,10 @@ public class Client {
public int ClientID { get; private set; }
public PlayerData PlayerData { get; set; } = new();
public Room Room { get; set; }
public object ClientLock = new();
private readonly Socket socket;
private NetworkData? lastData;
private NetworkPacket? incompleteData;
private bool hasIncompletePakcet = false;
SocketBuffer socketBuffer = new();
private volatile bool scheduledDisconnect = false;
public Client(Socket clientSocket) {
socket = clientSocket;
@ -29,21 +27,11 @@ public class Client {
int len = await socket.ReceiveAsync(buffer, SocketFlags.None);
if (len == 0)
throw new SocketException();
lastData = new NetworkData(buffer);
socketBuffer.Write(buffer, len);
}
public bool TryGetNextPacket(out NetworkPacket packet) {
packet = new();
if (hasIncompletePakcet) {
// TODO
}
byte header = lastData!.ReadByte();
if (header != 0x80 && header != 0xa0)
return false;
short length = lastData.ReadShort();
byte[] data = lastData.ReadChunk(length);
packet = new NetworkPacket(header, data);
return true;
return socketBuffer.ReadPacket(out packet);
}
public void Send(NetworkPacket packet) {
@ -78,9 +66,13 @@ public class Client {
}
}
public void SheduleDisconnect() {
scheduledDisconnect = true;
}
public bool Connected {
get {
return socket.Connected;
return socket.Connected && !scheduledDisconnect;
}
}
}

View File

@ -17,7 +17,11 @@ public class Room {
public IEnumerable<Client> Clients {
get {
return new List<Client>(clients);
List<Client> list;
lock (roomLock) {
list = new List<Client>(clients);
}
return list;
}
}

View File

@ -17,6 +17,12 @@ public class NetworkData {
this.data = data;
}
public int RemainingLength {
get {
return data.Length - offset;
}
}
public void Seek(int offset) {
int newOffset = this.offset + offset;
if (newOffset >= 0 && newOffset < data.Length)

View File

@ -33,12 +33,14 @@ public class NetworkPacket {
header = 0xa0;
this.compressed = true;
}
this.data = data.Data;
this.data = new byte[data.Data.Length];
Buffer.BlockCopy(data.Data, 0, this.data, 0, data.Data.Length);
}
public NetworkPacket(byte header, byte[] data) {
this.header = header;
this.data = data;
this.data = new byte[data.Length];
Buffer.BlockCopy(data, 0, this.data, 0, data.Length);
if (header == 0xa0)
compressed = true;
}

54
src/Data/SocketBuffer.cs Normal file
View File

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace sodoffmmo.Data;
internal class SocketBuffer {
NetworkData data = new();
Status status = Status.Header;
byte header;
short length;
byte[] value = new byte[0];
public void Write(byte[] buffer, int length) {
data.WriteChunk(buffer, 0, length);
}
public bool ReadPacket(out NetworkPacket packet) {
packet = new();
if (status == Status.Header)
ReadHeader();
if (status == Status.Value) {
ReadValue();
if (status == Status.Header) {
packet = new(header, value);
return true;
}
}
return false;
}
private void ReadHeader() {
if (data.RemainingLength < 3)
return;
header = data.ReadByte();
length = data.ReadShort();
status = Status.Value;
}
private void ReadValue() {
if (data.RemainingLength < length)
return;
value = data.ReadChunk(length);
data = new(data.ReadChunk(data.RemainingLength));
status = Status.Header;
}
enum Status {
Header,
Value
}
}

View File

@ -47,12 +47,11 @@ public class Server {
_ = Task.Run(() => HandleObjects(networkObjects, client));
}
} catch (SocketException) {
client.Disconnect();
} finally {
try {
client.LeaveRoom();
} catch (Exception) { }
client.Disconnect();
Console.WriteLine("Socket disconnected IID: " + client.ClientID);
}
}