Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed UDP hello message drop on azure environment w/ fixed tests #175

Merged
merged 2 commits into from
Jan 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions DarkRift.Client/BichannelClientConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public sealed class BichannelClientConnection : NetworkClientConnection, IDispos
/// The IP address of the remote client.
/// </summary>
public IPEndPoint RemoteUdpEndPoint { get; }

/// <summary>
/// Whether Nagel's algorithm should be disabled or not.
/// </summary>
Expand Down Expand Up @@ -113,7 +113,7 @@ public BichannelClientConnection(IPVersion ipVersion, IPAddress ipAddress, int p

tcpSocket = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp);
udpSocket = new Socket(tcpSocket.AddressFamily, SocketType.Dgram, ProtocolType.Udp);

NoDelay = noDelay;
}

Expand Down Expand Up @@ -172,6 +172,7 @@ public override void Connect()
: "Malformatted TCP auth token from server.";
throw new DarkRiftConnectionException(errorMessage, SocketError.ConnectionAborted);
}

if (protocolVersion > BichannelProtocolVersion)
{
tcpSocket.Shutdown(SocketShutdown.Both);
Expand All @@ -183,7 +184,7 @@ public override void Connect()
udpSocket.Send(buffer);

//Receive response from server to initiate the connection
int udpAcknowledgmentSize = protocolVersion >= 1 ? 8 : 1;
int udpAcknowledgmentSize = protocolVersion >= 1 ? 12 : 1;
byte[] udpBuffer = new byte[udpAcknowledgmentSize];
udpSocket.ReceiveTimeout = 5000;

Expand All @@ -198,23 +199,24 @@ public override void Connect()
}
finally
{
udpSocket.ReceiveTimeout = 0; //Reset to infinite
udpSocket.ReceiveTimeout = 0; //Reset to infinite
}

bool failedUdpReceive = receivedUdp != udpAcknowledgmentSize;
if (!failedUdpReceive)
{
if (protocolVersion != 0)
{
for (int i = 0; i < udpAcknowledgmentSize; ++i)
for (int i = 1; i < buffer.Length; i++)
{
if (udpBuffer[i] != buffer[i + 1])
if (udpBuffer[i - 1] != buffer[i])
{
failedUdpReceive = true;
break;
}
}
}

if (protocolVersion == 0)
{
if (udpBuffer[0] != 0)
Expand Down Expand Up @@ -722,7 +724,6 @@ private void UdpReceiveCompleted(object sender, SocketAsyncEventArgs e)
// Leave the loop
return;
}

} while (!completingAsync);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ protected struct PendingConnection
/// The UDP connections to the server.
/// </summary>
protected Dictionary<EndPoint, BichannelServerConnection> UdpConnections { get; } = new Dictionary<EndPoint, BichannelServerConnection>();

/// <summary>
/// The maximum size the client can ask a TCP body to be without being striked.
/// </summary>
Expand Down Expand Up @@ -194,7 +194,7 @@ protected void HandleTcpConnection(Socket acceptSocket)
try
{
//Send token via TCP
byte[] buffer = new byte[9]; //Version, Token * 8
byte[] buffer = new byte[9]; //Version, Token * 8
buffer[0] = (byte)BichannelProtocolVersion;
BigEndianHelper.WriteBytes(buffer, 1, token);
acceptSocket.Send(buffer);
Expand Down Expand Up @@ -313,20 +313,26 @@ protected void HandleUdpConnection(MessageBuffer buffer, EndPoint remoteEndPoint

// Send message back to client to say hi
// This MemoryBuffer is not supposed to be disposed here! It's disposed when the message is sent!
int numBytesOfHello = BichannelProtocolVersion >= 1? 8 : 1; // This used to be 1 which caused issues with some ISPs.
// HelloBuffer size is must be at least 12 bytes even when the actual token is shorter
// otherwise the message is dropped in some environments. namely ACI
int numBytesOfHello = BichannelProtocolVersion >= 1 ? 12 : 1; // This used to be 1 which caused issues with some ISPs.
MessageBuffer helloBuffer = MessageBuffer.Create(numBytesOfHello);
helloBuffer.Count = numBytesOfHello;

if (BichannelProtocolVersion >= 1)
{
for (int i = 0; i < numBytesOfHello; ++i)
// Copy TCP token
for (int i = 0; i < 8; i++)
helloBuffer.Buffer[i] = buffer.Buffer[i + 1];
// Zero remaining bytes (as we might want to use them somehow in the future)
for (int i = 8; i < numBytesOfHello; ++i)
helloBuffer.Buffer[i] = 0;
}
else
{
helloBuffer.Buffer[0] = 0;
}

connection.SendMessageUnreliable(helloBuffer);

//Inform everyone
Expand Down Expand Up @@ -360,7 +366,7 @@ internal void UnregisterUdpConnection(BichannelServerConnection connection)
lock (UdpConnections)
UdpConnections.Remove(connection.RemoteUdpEndPoint);
}

/// <summary>
/// Sends a buffer to the given endpoint using the UDP socket.
/// </summary>
Expand Down
6 changes: 4 additions & 2 deletions DarkRift.SystemTesting/PartialMessagingSteps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,14 @@ public void GivenTheHandshakeHasCompeleted()
udpSocket.Send(tcpBuffer);

// Receive punchthrough
byte[] udpBuffer = new byte[8];
byte[] udpBuffer = new byte[12];
int receivedUdp = udpSocket.Receive(udpBuffer);

Assert.AreEqual(8, receivedUdp);
Assert.AreEqual(12, receivedUdp);
for (int i = 0; i < 8; ++i)
Assert.AreEqual(tcpBuffer[i + 1], udpBuffer[i], $"Token byte {i} mismatch");
for (int i = 8; i < 12; ++i)
Assert.AreEqual(0, udpBuffer[i]);

// Stupid race condition to attach the MessageReceived handler
System.Threading.Thread.Sleep(100);
Expand Down