Skip to content

Commit

Permalink
Updates
Browse files Browse the repository at this point in the history
  • Loading branch information
HakanL committed Dec 12, 2024
1 parent e835521 commit 86e2bef
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 50 deletions.
2 changes: 1 addition & 1 deletion src/Haukcode.KiNet/Haukcode.KiNet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Haukcode.Network" Version="1.0.12" />
<PackageReference Include="Haukcode.Network" Version="1.0.16" />
<PackageReference Include="System.Net.NetworkInformation" Version="4.3.0" />
<PackageReference Include="System.Private.Uri" Version="4.3.2" />
<PackageReference Include="System.Reactive" Version="6.0.1" />
Expand Down
70 changes: 21 additions & 49 deletions src/Haukcode.KiNet/KiNetClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ public class KiNetClient : Client<KiNetClient.SendData, ReceiveDataPacket>

public class SendData : HighPerfComm.SendData
{
public IPEndPoint Destination { get; set; } = null!;
public IPEndPoint Destination { get; set; }

public SendData(IPEndPoint destination)
{
Destination = destination;
}
}

private const int ReceiveBufferSize = 20480;
Expand All @@ -36,45 +41,22 @@ public class SendData : HighPerfComm.SendData
private readonly IPEndPoint localEndPoint;

public KiNetClient(IPAddress localAddress, IPAddress localSubnetMask, IPAddress? bindAddress = null)
: base(() => new SendData(), 1000)
: base(1000)

Check failure on line 44 in src/Haukcode.KiNet/KiNetClient.cs

View workflow job for this annotation

GitHub Actions / build

There is no argument given that corresponds to the required parameter 'packetSize' of 'Client<KiNetClient.SendData, ReceiveDataPacket>.Client(Func<KiNetClient.SendData>, int)'

Check failure on line 44 in src/Haukcode.KiNet/KiNetClient.cs

View workflow job for this annotation

GitHub Actions / build

There is no argument given that corresponds to the required parameter 'packetSize' of 'Client<KiNetClient.SendData, ReceiveDataPacket>.Client(Func<KiNetClient.SendData>, int)'
{
this.packetSubject = new Subject<ReceiveDataPacket>();

this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
this.socket.ReceiveBufferSize = ReceiveBufferSize;
this.socket.SendBufferSize = SendBufferSize;

// Set the SIO_UDP_CONNRESET ioctl to true for this UDP socket. If this UDP socket
// ever sends a UDP packet to a remote destination that exists but there is
// no socket to receive the packet, an ICMP port unreachable message is returned
// to the sender. By default, when this is received the next operation on the
// UDP socket that send the packet will receive a SocketException. The native
// (Winsock) error that is received is WSAECONNRESET (10054). Since we don't want
// to wrap each UDP socket operation in a try/except, we'll disable this error
// for the socket with this ioctl call.
try
{
uint IOC_IN = 0x80000000;
uint IOC_VENDOR = 0x18000000;
uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;

byte[] optionInValue = { Convert.ToByte(false) };
byte[] optionOutValue = new byte[4];
this.socket.IOControl((int)SIO_UDP_CONNRESET, optionInValue, optionOutValue);
}
catch
{
Debug.WriteLine("Unable to set SIO_UDP_CONNRESET, maybe not supported.");
}
Haukcode.Network.Utils.SetSocketOptions(this.socket);

this.socket.ExclusiveAddressUse = false;
this.socket.EnableBroadcast = true;
this.socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

this.localEndPoint = new IPEndPoint(localAddress, DefaultPort);
this.broadcastEndPoint = new IPEndPoint(GetBroadcastAddress(localAddress, localSubnetMask), this.localEndPoint.Port);
this.broadcastEndPoint = new IPEndPoint(Haukcode.Network.Utils.GetBroadcastAddress(localAddress, localSubnetMask), this.localEndPoint.Port);

// Linux wants Any to get multicast/broadcast packets
// Linux wants Any to get multicast/broadcast packets (including unicast)
this.socket.Bind(new IPEndPoint(bindAddress ?? localAddress, this.localEndPoint.Port));

this.socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
Expand All @@ -88,22 +70,6 @@ public KiNetClient(IPAddress localAddress, IPAddress localSubnetMask, IPAddress?
/// </summary>
public IObservable<ReceiveDataPacket> OnPacket => this.packetSubject.AsObservable();

private static IPAddress GetBroadcastAddress(IPAddress address, IPAddress subnetMask)
{
byte[] ipAdressBytes = address.GetAddressBytes();
byte[] subnetMaskBytes = subnetMask.GetAddressBytes();

if (ipAdressBytes.Length != subnetMaskBytes.Length)
throw new ArgumentException("Lengths of IP address and subnet mask do not match.");

byte[] broadcastAddress = new byte[ipAdressBytes.Length];
for (int i = 0; i < broadcastAddress.Length; i++)
{
broadcastAddress[i] = (byte)(ipAdressBytes[i] | (subnetMaskBytes[i] ^ 255));
}
return new IPAddress(broadcastAddress);
}

/// <summary>
/// Unicast send data
/// </summary>
Expand Down Expand Up @@ -143,8 +109,10 @@ public async Task QueuePacket(BasePacket packet, IPAddress? destination = null,
{
packet.Sequence = Interlocked.Increment(ref this.sequenceCounter);

await base.QueuePacket(packet.Length, important, (newSendData, memory) =>
await base.QueuePacket(packet.Length, important, () =>

Check failure on line 112 in src/Haukcode.KiNet/KiNetClient.cs

View workflow job for this annotation

GitHub Actions / build

No overload for method 'QueuePacket' takes 4 arguments

Check failure on line 112 in src/Haukcode.KiNet/KiNetClient.cs

View workflow job for this annotation

GitHub Actions / build

No overload for method 'QueuePacket' takes 4 arguments
{
IPEndPoint? sendDataDestination = null;

if (destination != null)
{
if (!this.endPointCache.TryGetValue(destination, out var ipEndPoint))
Expand All @@ -153,11 +121,15 @@ await base.QueuePacket(packet.Length, important, (newSendData, memory) =>
this.endPointCache.Add(destination, ipEndPoint);
}

newSendData.Destination = ipEndPoint;
// Only works for when subnet mask is /24 or less
if (ipEndPoint.Address.GetAddressBytes().Last() == 255)
sendDataDestination = null;
else
sendDataDestination = ipEndPoint;
}

return packet.WriteToBuffer(memory);
});
return new SendData(sendDataDestination ?? this.broadcastEndPoint);
}, packet.WriteToBuffer);
}

public void WarmUpSockets(IEnumerable<ushort> universeIds)
Expand All @@ -184,7 +156,7 @@ protected override void Dispose(bool disposing)

protected override ValueTask<int> SendPacketAsync(SendData sendData, ReadOnlyMemory<byte> payload)
{
return this.socket.SendToAsync(payload, SocketFlags.None, sendData.Destination ?? this.broadcastEndPoint);
return this.socket.SendToAsync(payload, SocketFlags.None, sendData.Destination);
}

protected override async ValueTask<(int ReceivedBytes, SocketReceiveMessageFromResult Result)> ReceiveData(Memory<byte> memory, CancellationToken cancelToken)
Expand Down

0 comments on commit 86e2bef

Please sign in to comment.