/// <summary>
/// Class to hold packet data
/// </summary>
- class Packet : IRecyclable, IDisposable
+ public class Packet : IRecyclable, IDisposable
{
/// <summary>
/// Object pool for this event.
/// </summary>
- static readonly ObjectPool<Packet> objectPool = new ObjectPool<Packet>(() => new Packet());
+ public static readonly ObjectPool<Packet> PacketPool = new ObjectPool<Packet>(() => new Packet());
/// <summary>
/// Returns an instance of this object from the pool.
/// <returns></returns>
internal static Packet GetObject()
{
- return objectPool.GetObject();
+ return PacketPool.GetObject();
}
public ushort Id;
}
}
- objectPool.PutObject(this);
+ PacketPool.PutObject(this);
}
/// <summary>
if (p.Id != id) return;
// Backoff retry frequency to avoid congestion
- p.LastTimeout = (int)Math.Min(p.LastTimeout * 1.5f, this.disconnectTimeout / 2f);
+ p.LastTimeout = (int)Math.Min(p.LastTimeout * 1.25f, 2000);
p.Timer.Change(p.LastTimeout, Timeout.Infinite);
}
Trace.WriteLine("Resend.");
},
- resendTimeout > 0 ? resendTimeout : (int)Math.Max(100, Math.Min(AveragePingMs * 4, 1500)),
+ resendTimeout > 0 ? resendTimeout : (int)Math.Max(500, Math.Min(AveragePingMs * 4, 2000)),
ackCallback
);
}
lock (PingLock)
{
- this.AveragePingMs = Math.Max(10, this.AveragePingMs * .7f + rt * .3f);
+ this.AveragePingMs = Math.Max(50, this.AveragePingMs * .7f + rt * .3f);
}
}
/// The socket listening for connections.
/// </summary>
Socket listener;
-
+
+ private Action<string> Logger;
+
/// <summary>
/// The connections we currently hold
/// </summary>
/// <param name="port">The port to listen on.</param>
/// <param name="mode">The <see cref="IPMode"/> to listen with.</param>
[Obsolete("Temporary constructor in beta only, use NetworkEndPoint constructor instead.")]
- public UdpConnectionListener(IPAddress IPAddress, int port, IPMode mode = IPMode.IPv4)
+ public UdpConnectionListener(IPAddress IPAddress, int port, Action<string> logger, IPMode mode = IPMode.IPv4)
: this (new NetworkEndPoint(IPAddress, port, mode))
{
-
+ this.Logger = logger;
}
/// <summary>
message.Recycle();
return;
}
-
+
//Begin receiving again
StartListeningForData();
- bool aware;
- bool isHello = message.Buffer[0] == (byte)UdpSendOption.Hello
- && message.Length >= MinConnectionLength;
+ bool aware = true;
+ bool hasHelloByte = message.Buffer[0] == (byte)UdpSendOption.Hello;
+ bool isHello = hasHelloByte && message.Length >= MinConnectionLength;
//If we're aware of this connection use the one already
//If this is a new client then connect with them!
UdpServerConnection connection;
- if (!(aware = this.allConnections.TryGetValue(remoteEndPoint, out connection)))
+ if (!this.allConnections.TryGetValue(remoteEndPoint, out connection))
{
lock (this.allConnections)
{
- if (!(aware = this.allConnections.TryGetValue(remoteEndPoint, out connection)))
+ aware = this.allConnections.TryGetValue(remoteEndPoint, out connection);
+ if (!aware)
{
//Check for malformed connection attempts
if (!isHello)
}
connection = new UdpServerConnection(this, remoteEndPoint, this.IPMode);
- this.allConnections.TryAdd(remoteEndPoint, connection);
+ if (!this.allConnections.TryAdd(remoteEndPoint, connection))
+ {
+ throw new Exception();
+ }
}
}
}
- //Inform the connection of the buffer (new connections need to send an ack back to client)
- connection.HandleReceive(message, bytesReceived);
+ var stopwatch = System.Diagnostics.Stopwatch.StartNew();
+ try
+ {
+ //Inform the connection of the buffer (new connections need to send an ack back to client)
+ connection.HandleReceive(message, bytesReceived);
+ }
+ finally
+ {
+ var el = stopwatch.ElapsedMilliseconds;
+ if (el > 5)
+ {
+ this.Logger?.Invoke($"Long Packet {el}ms = {string.Join(" ", message.Buffer.Take(bytesReceived))}");
+ }
+ }
//If it's a new connection invoke the NewConnection event.
if (!aware)
{
// Skip header and hello byte;
- message.Offset = 4;
+ message.Offset = 4;
message.Length = bytesReceived - 4;
message.Position = 0;
InvokeNewConnection(message, connection);
}
- else if (isHello)
+ else if (isHello || (!isHello && hasHelloByte))
{
message.Recycle();
}
/// <param name="endPoint">The endpoint of the virtual connection.</param>
internal void RemoveConnectionTo(EndPoint endPoint)
{
- this.allConnections.TryRemove(endPoint, out var conn);
+ lock (this.allConnections)
+ {
+ this.allConnections.TryRemove(endPoint, out var conn);
+ }
}
/// <inheritdoc />