refactor(net): own complete live session lifecycle
This commit is contained in:
parent
23b43d1859
commit
d9ccf8a6b9
5 changed files with 1618 additions and 91 deletions
|
|
@ -10,6 +10,29 @@ using AcDream.Core.Net.Packets;
|
|||
|
||||
namespace AcDream.Core.Net;
|
||||
|
||||
internal interface IWorldSessionTransport : IDisposable
|
||||
{
|
||||
void Send(ReadOnlySpan<byte> datagram);
|
||||
void Send(IPEndPoint remote, ReadOnlySpan<byte> datagram);
|
||||
byte[]? Receive(TimeSpan timeout, out IPEndPoint? from);
|
||||
}
|
||||
|
||||
internal sealed class NetClientWorldSessionTransport(IPEndPoint remote)
|
||||
: IWorldSessionTransport
|
||||
{
|
||||
private readonly NetClient _client = new(remote);
|
||||
|
||||
public void Send(ReadOnlySpan<byte> datagram) => _client.Send(datagram);
|
||||
|
||||
public void Send(IPEndPoint endpoint, ReadOnlySpan<byte> datagram) =>
|
||||
_client.Send(endpoint, datagram);
|
||||
|
||||
public byte[]? Receive(TimeSpan timeout, out IPEndPoint? from) =>
|
||||
_client.Receive(timeout, out from);
|
||||
|
||||
public void Dispose() => _client.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// High-level AC client session: owns a <see cref="NetClient"/>, drives
|
||||
/// the full handshake + character-enter-world flow, and converts the
|
||||
|
|
@ -600,7 +623,7 @@ public sealed class WorldSession : IDisposable
|
|||
|
||||
public CharacterList.Parsed? Characters { get; private set; }
|
||||
|
||||
private readonly NetClient _net;
|
||||
private readonly IWorldSessionTransport _net;
|
||||
private long _lastInboundPacketTicks = Stopwatch.GetTimestamp();
|
||||
private long _lastPingRequestTicks;
|
||||
private long _lastPingRoundTripBits = BitConverter.DoubleToInt64Bits(double.NaN);
|
||||
|
|
@ -676,10 +699,34 @@ public sealed class WorldSession : IDisposable
|
|||
private uint _gameActionSequence;
|
||||
|
||||
public WorldSession(IPEndPoint serverLogin)
|
||||
: this(
|
||||
serverLogin,
|
||||
static endpoint => new NetClientWorldSessionTransport(endpoint))
|
||||
{
|
||||
}
|
||||
|
||||
internal WorldSession(
|
||||
IPEndPoint serverLogin,
|
||||
IWorldSessionTransport transport)
|
||||
: this(serverLogin, _ => transport)
|
||||
{
|
||||
}
|
||||
|
||||
internal WorldSession(
|
||||
IPEndPoint serverLogin,
|
||||
Func<IPEndPoint, IWorldSessionTransport> transportFactory)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(serverLogin);
|
||||
ArgumentNullException.ThrowIfNull(transportFactory);
|
||||
if (serverLogin.Port == ushort.MaxValue)
|
||||
throw new ArgumentOutOfRangeException(
|
||||
nameof(serverLogin),
|
||||
"The login endpoint must leave room for the adjacent connect port.");
|
||||
|
||||
_loginEndpoint = serverLogin;
|
||||
_connectEndpoint = new IPEndPoint(serverLogin.Address, serverLogin.Port + 1);
|
||||
_net = new NetClient(serverLogin);
|
||||
_net = transportFactory(serverLogin)
|
||||
?? throw new InvalidOperationException("The session transport factory returned null.");
|
||||
|
||||
// Phase I.6: SetTurbineChatChannels (0x0295) is a GameEvent
|
||||
// sub-opcode of 0xF7B0, not a top-level opcode. Route it through
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue