Files
ShrinkNetwork/Runtime/Transport/Loopback/ShrinkLoopbackTransport.cs
T

86 lines
2.9 KiB
C#

#nullable enable
using System;
using System.Collections.Generic;
using System.Threading;
using Cysharp.Threading.Tasks;
namespace ShrinkNetwork
{
public sealed class ShrinkLoopbackTransport : IShrinkNetworkMemoryTransport, IShrinkNetworkSessionControlTransport
{
private readonly HashSet<long> _openedSessions = new();
private ShrinkLoopbackTransport? _peer;
public bool IsStarted { get; private set; }
public event Action<ShrinkNetworkTransportEvent>? OnEvent;
public void LinkPeer(ShrinkLoopbackTransport peer)
{
_peer = peer;
if (peer._peer != this)
peer.LinkPeer(this);
}
public void Start()
{
IsStarted = true;
}
public void Stop()
{
IsStarted = false;
}
public void OpenSession(long sessionId, string remoteAddress = "loopback")
{
_openedSessions.Add(sessionId);
_peer?._openedSessions.Add(sessionId);
OnEvent?.Invoke(ShrinkNetworkTransportEvent.Connected(sessionId, remoteAddress));
_peer?.OnEvent?.Invoke(ShrinkNetworkTransportEvent.Connected(sessionId, remoteAddress));
}
public void CloseSession(long sessionId, string remoteAddress = "loopback")
{
_openedSessions.Remove(sessionId);
_peer?._openedSessions.Remove(sessionId);
OnEvent?.Invoke(ShrinkNetworkTransportEvent.Disconnected(sessionId, remoteAddress));
_peer?.OnEvent?.Invoke(ShrinkNetworkTransportEvent.Disconnected(sessionId, remoteAddress));
}
public bool DisconnectSession(long sessionId, string? reason = null)
{
if (!_openedSessions.Contains(sessionId))
return false;
CloseSession(sessionId);
return true;
}
public void Send(long sessionId, byte[] packetData)
{
SendAsync(sessionId, packetData).Forget();
}
public UniTask SendAsync(long sessionId, byte[] packetData)
{
if (!IsStarted)
throw new InvalidOperationException("Transport has not been started.");
if (_peer == null)
throw new InvalidOperationException("Peer transport is not linked.");
if (!_openedSessions.Contains(sessionId))
throw new InvalidOperationException($"Session {sessionId} is not open.");
_peer.OnEvent?.Invoke(ShrinkNetworkTransportEvent.Packet(sessionId, packetData));
return UniTask.CompletedTask;
}
public UniTask SendAsync(long sessionId, ReadOnlyMemory<byte> packetData, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
// Receivers may enqueue the event beyond this call; transfer a dedicated copy.
return SendAsync(sessionId, packetData.ToArray());
}
}
}