Files
the-cycle/src/Prospect.Unreal/Net/UIpConnection.cs
T
2022-01-16 22:55:42 +01:00

132 lines
4.4 KiB
C#

using System.Net;
using System.Net.Sockets;
using Prospect.Unreal.Core;
using Prospect.Unreal.Exceptions;
using Prospect.Unreal.Net.Packets.Control;
namespace Prospect.Unreal.Net;
public class UIpConnection : UNetConnection
{
public const int IpHeaderSize = 20;
public const int UdpHeaderSize = IpHeaderSize + 8;
/// <summary>
/// Cached time of the first send socket error that will be used to compute disconnect delay.
/// </summary>
private double _socketErrorSendDelayStartTime;
/// <summary>
/// Cached time of the first recv socket error that will be used to compute disconnect delay.
/// </summary>
private double _socketErrorRecvDelayStartTime;
public UdpClient? Socket { get; private set; }
public override void InitBase(UNetDriver inDriver, UdpClient inSocket, FUrl inURL, EConnectionState inState, int inMaxPacket = 0, int inPacketOverhead = 0)
{
base.InitBase(inDriver, inSocket, inURL, inState,
(inMaxPacket == 0 || inMaxPacket > MaxPacketSize) ? MaxPacketSize : inMaxPacket,
inPacketOverhead == 0 ? UdpHeaderSize : inPacketOverhead);
Socket = inSocket;
}
public override void InitRemoteConnection(UNetDriver inDriver, UdpClient inSocket, FUrl inURL, IPEndPoint inRemoteAddr, EConnectionState inState, int inMaxPacket = 0, int inPacketOverhead = 0)
{
InitBase(inDriver, inSocket, inURL, inState,
(inMaxPacket == 0 || inMaxPacket > MaxPacketSize) ? MaxPacketSize : inMaxPacket,
inPacketOverhead == 0 ? UdpHeaderSize : inPacketOverhead);
RemoteAddr = inRemoteAddr;
Url.Host = RemoteAddr.Address;
// Initialize our send bunch
InitSendBuffer();
// This is for a client that needs to log in, setup ClientLoginState and ExpectedClientLoginMsgType to reflect that
SetClientLoginState(EClientLoginState.LoggingIn);
SetExpectedClientLoginMsgType(NMT.Hello); // TODO: NMT_HELLO
}
public override void InitLocalConnection(UNetDriver inDriver, UdpClient inSocket, FUrl inURL, EConnectionState inState, int inMaxPacket = 0, int inPacketOverhead = 0)
{
InitBase(inDriver, inSocket, inURL, inState,
// Use the default packet size/overhead unless overridden by a child class
(inMaxPacket == 0 || inMaxPacket > MaxPacketSize) ? MaxPacketSize : inMaxPacket,
inPacketOverhead == 0 ? inMaxPacket : inPacketOverhead);
//RemoteAddr = new IPEndPoint(inURL.Host, inURL.Port);
InitSendBuffer();
}
public override void LowLevelSend(byte[] data, int countBits, FOutPacketTraits traits)
{
// TODO: Improve according to UE4
var dataToSend = data;
// Process any packet modifiers
if (Handler != null && !Handler.GetRawSend())
{
var processedData = Handler.Outgoing(data, countBits, traits);
if (!processedData.Error)
{
dataToSend = processedData.Data;
countBits = processedData.CountBits;
}
else
{
countBits = 0;
}
}
var countBytes = FMath.DivideAndRoundUp(countBits, 8);
if (countBits > 0)
{
if (Socket == null)
{
throw new UnrealNetException();
}
// can't send remote addr if client is already set. receive is called before now too, so need to establish socket before then.
if (RemoteAddr.Address.GetAddressBytes().All(a => a == 0xff))
Socket.Send(dataToSend, countBytes);
else
Socket.Send(dataToSend, countBytes, RemoteAddr);
}
}
public override string LowLevelGetRemoteAddress(bool bAppendPort = false)
{
if (RemoteAddr != null)
{
// TODO: Remove port
return RemoteAddr.ToString();
}
return string.Empty;
}
public override string LowLevelDescribe()
{
throw new NotImplementedException();
}
public override void CleanUp()
{
throw new NotImplementedException();
}
public override void ReceivedRawPacket(FReceivedPacketView packetView)
{
_socketErrorRecvDelayStartTime = 0;
base.ReceivedRawPacket(packetView);
}
public override float GetTimeoutValue()
{
throw new NotImplementedException();
}
}