1
0
mirror of https://github.com/lidgren/lidgren-network-gen3.git synced 2026-05-06 02:11:06 +09:00

ConnectionLatencyUpdated message type added; WriteTime() ReadTime() added

This commit is contained in:
lidgren
2010-12-20 10:35:51 +00:00
parent 772d80835b
commit 330c5cf83e
11 changed files with 85 additions and 25 deletions

View File

@@ -183,7 +183,7 @@ namespace Lidgren.Network
m_peer.m_handshakes.Remove(m_remoteEndpoint); // TODO: make this more thread safe? we're on user thread m_peer.m_handshakes.Remove(m_remoteEndpoint); // TODO: make this more thread safe? we're on user thread
} }
internal void ReceivedHandshake(NetMessageType tp, int ptr, int payloadLength) internal void ReceivedHandshake(double now, NetMessageType tp, int ptr, int payloadLength)
{ {
m_peer.VerifyNetworkThread(); m_peer.VerifyNetworkThread();
@@ -211,6 +211,7 @@ namespace Lidgren.Network
{ {
// ok, let's not add connection just yet // ok, let's not add connection just yet
NetIncomingMessage appMsg = m_peer.CreateIncomingMessage(NetIncomingMessageType.ConnectionApproval, (m_remoteHailMessage == null ? 0 : m_remoteHailMessage.LengthBytes)); NetIncomingMessage appMsg = m_peer.CreateIncomingMessage(NetIncomingMessageType.ConnectionApproval, (m_remoteHailMessage == null ? 0 : m_remoteHailMessage.LengthBytes));
appMsg.m_receiveTime = now;
appMsg.m_senderConnection = this; appMsg.m_senderConnection = this;
appMsg.m_senderEndpoint = this.m_remoteEndpoint; appMsg.m_senderEndpoint = this.m_remoteEndpoint;
if (m_remoteHailMessage != null) if (m_remoteHailMessage != null)

View File

@@ -9,11 +9,19 @@ namespace Lidgren.Network
private float m_averageRoundtripTime; private float m_averageRoundtripTime;
private float m_timeoutDeadline = float.MaxValue; private float m_timeoutDeadline = float.MaxValue;
// local time value + m_remoteTimeOffset = remote time value
internal double m_remoteTimeOffset;
/// <summary> /// <summary>
/// Gets the current average roundtrip time in seconds /// Gets the current average roundtrip time in seconds
/// </summary> /// </summary>
public float AverageRoundtripTime { get { return m_averageRoundtripTime; } } public float AverageRoundtripTime { get { return m_averageRoundtripTime; } }
internal double GetLocalTime(double remoteTimeStamp)
{
return remoteTimeStamp - m_remoteTimeOffset;
}
internal void InitializePing() internal void InitializePing()
{ {
// randomize ping sent time (0.25 - 1.0 x ping interval) // randomize ping sent time (0.25 - 1.0 x ping interval)
@@ -27,11 +35,10 @@ namespace Lidgren.Network
m_peer.VerifyNetworkThread(); m_peer.VerifyNetworkThread();
m_sentPingNumber++; m_sentPingNumber++;
if (m_sentPingNumber >= 256)
m_sentPingNumber = 0;
m_sentPingTime = (float)NetTime.Now; m_sentPingTime = (float)NetTime.Now;
NetOutgoingMessage om = m_peer.CreateMessage(1); NetOutgoingMessage om = m_peer.CreateMessage(1);
om.Write((byte)m_sentPingNumber); om.Write((byte)m_sentPingNumber); // truncating to 0-255
om.m_messageType = NetMessageType.Ping; om.m_messageType = NetMessageType.Ping;
int len = om.Encode(m_peer.m_sendBuffer, 0, 0); int len = om.Encode(m_peer.m_sendBuffer, 0, 0);
@@ -45,20 +52,22 @@ namespace Lidgren.Network
{ {
m_peer.VerifyNetworkThread(); m_peer.VerifyNetworkThread();
NetOutgoingMessage om = m_peer.CreateMessage(1); NetOutgoingMessage om = m_peer.CreateMessage(5);
om.Write((byte)pingNumber); om.Write((byte)pingNumber);
om.Write((float)NetTime.Now); // we should update this value to reflect the exact point in time the packet is SENT
om.m_messageType = NetMessageType.Pong; om.m_messageType = NetMessageType.Pong;
int len = om.Encode(m_peer.m_sendBuffer, 0, 0); int len = om.Encode(m_peer.m_sendBuffer, 0, 0);
bool connectionReset; bool connectionReset;
m_peer.SendPacket(len, m_remoteEndpoint, 1, out connectionReset); m_peer.SendPacket(len, m_remoteEndpoint, 1, out connectionReset);
m_statistics.PacketSent(len, 1); m_statistics.PacketSent(len, 1);
} }
internal void ReceivedPong(float now, int pongNumber) internal void ReceivedPong(float now, int pongNumber, float remoteSendTime)
{ {
if (pongNumber != m_sentPingNumber) if ((byte)pongNumber != (byte)m_sentPingNumber)
{ {
m_peer.LogVerbose("Ping/Pong mismatch; dropped message?"); m_peer.LogVerbose("Ping/Pong mismatch; dropped message?");
return; return;
@@ -69,15 +78,20 @@ namespace Lidgren.Network
float rtt = now - m_sentPingTime; float rtt = now - m_sentPingTime;
NetException.Assert(rtt >= 0); NetException.Assert(rtt >= 0);
double diff = (remoteSendTime + (rtt / 2.0)) - now;
if (m_averageRoundtripTime < 0) if (m_averageRoundtripTime < 0)
{ {
m_remoteTimeOffset = diff;
m_averageRoundtripTime = rtt; // initial estimate m_averageRoundtripTime = rtt; // initial estimate
m_peer.LogDebug("Initiated average roundtrip time to " + NetTime.ToReadable(m_averageRoundtripTime)); m_peer.LogDebug("Initiated average roundtrip time to " + NetTime.ToReadable(m_averageRoundtripTime) + " Server time is: " + (now + diff));
} }
else else
{ {
m_averageRoundtripTime = (m_averageRoundtripTime * 0.7f) + (float)(rtt * 0.3f); m_averageRoundtripTime = (m_averageRoundtripTime * 0.7f) + (float)(rtt * 0.3f);
m_peer.LogVerbose("Updated average roundtrip time to " + NetTime.ToReadable(m_averageRoundtripTime));
m_remoteTimeOffset = ((m_remoteTimeOffset * (double)(m_sentPingNumber - 1)) + diff) / (double)m_sentPingNumber;
m_peer.LogVerbose("Updated average roundtrip time to " + NetTime.ToReadable(m_averageRoundtripTime) + ", server time to " + (now + m_remoteTimeOffset) + " (ie. diff " + m_remoteTimeOffset + ")");
} }
// update resend delay for all channels // update resend delay for all channels
@@ -89,7 +103,17 @@ namespace Lidgren.Network
rchan.m_resendDelay = resendDelay; rchan.m_resendDelay = resendDelay;
} }
m_peer.LogVerbose("Timeout deadline pushed to " + m_timeoutDeadline); // m_peer.LogVerbose("Timeout deadline pushed to " + m_timeoutDeadline);
// notify the application that average rtt changed
if (m_peer.m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.ConnectionLatencyUpdated))
{
NetIncomingMessage update = m_peer.CreateIncomingMessage(NetIncomingMessageType.ConnectionLatencyUpdated, 4);
update.m_senderConnection = this;
update.m_senderEndpoint = this.m_remoteEndpoint;
update.Write(rtt);
m_peer.ReleaseMessage(update);
}
} }
} }
} }

View File

@@ -26,7 +26,7 @@ namespace Lidgren.Network
internal void InitExpandMTU(double now) internal void InitExpandMTU(double now)
{ {
m_lastSentMTUAttemptTime = now + m_peerConfiguration.m_expandMTUFrequency + 1.0f; // wait a tiny bit before starting to expand mtu m_lastSentMTUAttemptTime = now + m_peerConfiguration.m_expandMTUFrequency + 1.5f + m_averageRoundtripTime; // wait a tiny bit before starting to expand mtu
m_largestSuccessfulMTU = 512; m_largestSuccessfulMTU = 512;
m_smallestFailedMTU = -1; m_smallestFailedMTU = -1;
m_currentMTU = m_peerConfiguration.MaximumTransmissionUnit; m_currentMTU = m_peerConfiguration.MaximumTransmissionUnit;

View File

@@ -138,10 +138,10 @@ namespace Lidgren.Network
{ {
if (now > m_sentPingTime + m_peer.m_configuration.m_pingInterval) if (now > m_sentPingTime + m_peer.m_configuration.m_pingInterval)
SendPing(); SendPing();
}
// handle expand mtu // handle expand mtu
MTUExpansionHeartbeat(now); MTUExpansionHeartbeat(now);
}
if (m_disconnectRequested) if (m_disconnectRequested)
{ {
@@ -352,8 +352,10 @@ namespace Lidgren.Network
SendPong(pingNr); SendPong(pingNr);
break; break;
case NetMessageType.Pong: case NetMessageType.Pong:
int pongNr = m_peer.m_receiveBuffer[ptr++]; NetIncomingMessage pmsg = m_peer.SetupReadHelperMessage(ptr, payloadLength);
ReceivedPong(now, pongNr); int pongNr = pmsg.ReadByte();
float remoteSendTime = pmsg.ReadSingle();
ReceivedPong(now, pongNr, remoteSendTime);
break; break;
case NetMessageType.ExpandMTURequest: case NetMessageType.ExpandMTURequest:
SendMTUSuccess(payloadLength); SendMTUSuccess(payloadLength);

View File

@@ -465,6 +465,20 @@ namespace Lidgren.Network
return new IPEndPoint(address, port); return new IPEndPoint(address, port);
} }
/// <summary>
/// Reads a value, in local time comparable to NetTime.Now, written using WriteTime()
/// Must have a connected sender
/// </summary>
public double ReadTime(bool highPrecision)
{
double remoteTime = (highPrecision ? ReadDouble() : (double)ReadSingle());
if (m_senderConnection == null)
throw new NetException("Cannot call ReadTime() on message without a connected sender (ie. unconnected messages)");
return remoteTime - m_senderConnection.m_remoteTimeOffset;
}
/// <summary> /// <summary>
/// Pads data with enough bits to reach a full byte. Decreases cpu usage for subsequent byte writes. /// Pads data with enough bits to reach a full byte. Decreases cpu usage for subsequent byte writes.
/// </summary> /// </summary>

View File

@@ -36,6 +36,7 @@ namespace Lidgren.Network
internal int m_sequenceNumber; internal int m_sequenceNumber;
internal NetMessageType m_receivedMessageType; internal NetMessageType m_receivedMessageType;
internal bool m_isFragment; internal bool m_isFragment;
internal double m_receiveTime;
/// <summary> /// <summary>
/// Gets the type of this incoming message /// Gets the type of this incoming message
@@ -62,6 +63,11 @@ namespace Lidgren.Network
/// </summary> /// </summary>
public NetConnection SenderConnection { get { return m_senderConnection; } } public NetConnection SenderConnection { get { return m_senderConnection; } }
/// <summary>
/// What local time the message was received from the network
/// </summary>
public double ReceiveTime { get { return m_receiveTime; } }
/// <summary> /// <summary>
/// Gets the length of the message payload in bytes /// Gets the length of the message payload in bytes
/// </summary> /// </summary>

View File

@@ -42,5 +42,6 @@ namespace Lidgren.Network
WarningMessage = 1 << 9, // Data (string) WarningMessage = 1 << 9, // Data (string)
ErrorMessage = 1 << 10, // Data (string) ErrorMessage = 1 << 10, // Data (string)
NatIntroductionSuccess = 1 << 11, // Data (as passed to master server) NatIntroductionSuccess = 1 << 11, // Data (as passed to master server)
ConnectionLatencyUpdated = 1 << 12, // Seconds as a Single
} }
} }

View File

@@ -534,6 +534,17 @@ namespace Lidgren.Network
Write((ushort)endPoint.Port); Write((ushort)endPoint.Port);
} }
/// <summary>
/// Writes the local time to a message; readable (and convertable to local time) by the remote host using ReadTime()
/// </summary>
public void WriteTime(double localTime, bool highPrecision)
{
if (highPrecision)
Write(localTime);
else
Write((float)localTime);
}
/// <summary> /// <summary>
/// Pads data with enough bits to reach a full byte. Decreases cpu usage for subsequent byte writes. /// Pads data with enough bits to reach a full byte. Decreases cpu usage for subsequent byte writes.
/// </summary> /// </summary>

View File

@@ -124,7 +124,7 @@ namespace Lidgren.Network
Buffer.BlockCopy(im.m_data, ptr, info.Data, offset, im.LengthBytes - ptr); Buffer.BlockCopy(im.m_data, ptr, info.Data, offset, im.LengthBytes - ptr);
int cnt = info.ReceivedChunks.Count(); int cnt = info.ReceivedChunks.Count();
//Console.WriteLine("Found fragment #" + chunkNumber + " in group " + group + " offset " + offset + " of total bits " + totalBits + " (total chunks done " + cnt + ")"); //LogVerbose("Found fragment #" + chunkNumber + " in group " + group + " offset " + offset + " of total bits " + totalBits + " (total chunks done " + cnt + ")");
LogVerbose("Received fragment " + chunkNumber + " of " + totalNumChunks + " (" + cnt + " chunks received)"); LogVerbose("Received fragment " + chunkNumber + " of " + totalNumChunks + " (" + cnt + " chunks received)");

View File

@@ -43,9 +43,6 @@ namespace Lidgren.Network
{ {
NetException.Assert(msg.m_incomingMessageType != NetIncomingMessageType.Error); NetException.Assert(msg.m_incomingMessageType != NetIncomingMessageType.Error);
if (msg.MessageType == NetIncomingMessageType.UnconnectedData)
Console.WriteLine("x");
if (msg.m_isFragment) if (msg.m_isFragment)
{ {
HandleReleasedFragment(msg); HandleReleasedFragment(msg);
@@ -306,6 +303,7 @@ namespace Lidgren.Network
NetConnection sender = null; NetConnection sender = null;
m_connectionLookup.TryGetValue(ipsender, out sender); m_connectionLookup.TryGetValue(ipsender, out sender);
double receiveTime = NetTime.Now;
// //
// parse packet into messages // parse packet into messages
// //
@@ -344,7 +342,7 @@ namespace Lidgren.Network
if (sender != null) if (sender != null)
sender.ReceivedLibraryMessage(tp, ptr, payloadByteLength); sender.ReceivedLibraryMessage(tp, ptr, payloadByteLength);
else else
ReceivedUnconnectedLibraryMessage(ipsender, tp, ptr, payloadByteLength); ReceivedUnconnectedLibraryMessage(receiveTime, ipsender, tp, ptr, payloadByteLength);
} }
else else
{ {
@@ -353,6 +351,7 @@ namespace Lidgren.Network
NetIncomingMessage msg = CreateIncomingMessage(NetIncomingMessageType.Data, payloadByteLength); NetIncomingMessage msg = CreateIncomingMessage(NetIncomingMessageType.Data, payloadByteLength);
msg.m_isFragment = isFragment; msg.m_isFragment = isFragment;
msg.m_receiveTime = receiveTime;
msg.m_sequenceNumber = sequenceNumber; msg.m_sequenceNumber = sequenceNumber;
msg.m_receivedMessageType = tp; msg.m_receivedMessageType = tp;
msg.m_senderConnection = sender; msg.m_senderConnection = sender;
@@ -390,12 +389,12 @@ namespace Lidgren.Network
} }
} }
private void ReceivedUnconnectedLibraryMessage(IPEndPoint senderEndpoint, NetMessageType tp, int ptr, int payloadByteLength) private void ReceivedUnconnectedLibraryMessage(double now, IPEndPoint senderEndpoint, NetMessageType tp, int ptr, int payloadByteLength)
{ {
NetConnection shake; NetConnection shake;
if (m_handshakes.TryGetValue(senderEndpoint, out shake)) if (m_handshakes.TryGetValue(senderEndpoint, out shake))
{ {
shake.ReceivedHandshake(tp, ptr, payloadByteLength); shake.ReceivedHandshake(now, tp, ptr, payloadByteLength);
return; return;
} }
@@ -410,6 +409,7 @@ namespace Lidgren.Network
NetIncomingMessage dm = CreateIncomingMessage(NetIncomingMessageType.DiscoveryRequest, payloadByteLength); NetIncomingMessage dm = CreateIncomingMessage(NetIncomingMessageType.DiscoveryRequest, payloadByteLength);
if (payloadByteLength > 0) if (payloadByteLength > 0)
Buffer.BlockCopy(m_receiveBuffer, ptr, dm.m_data, 0, payloadByteLength); Buffer.BlockCopy(m_receiveBuffer, ptr, dm.m_data, 0, payloadByteLength);
dm.m_receiveTime = now;
dm.m_bitLength = payloadByteLength * 8; dm.m_bitLength = payloadByteLength * 8;
dm.m_senderEndpoint = senderEndpoint; dm.m_senderEndpoint = senderEndpoint;
ReleaseMessage(dm); ReleaseMessage(dm);
@@ -422,6 +422,7 @@ namespace Lidgren.Network
NetIncomingMessage dr = CreateIncomingMessage(NetIncomingMessageType.DiscoveryResponse, payloadByteLength); NetIncomingMessage dr = CreateIncomingMessage(NetIncomingMessageType.DiscoveryResponse, payloadByteLength);
if (payloadByteLength > 0) if (payloadByteLength > 0)
Buffer.BlockCopy(m_receiveBuffer, ptr, dr.m_data, 0, payloadByteLength); Buffer.BlockCopy(m_receiveBuffer, ptr, dr.m_data, 0, payloadByteLength);
dr.m_receiveTime = now;
dr.m_bitLength = payloadByteLength * 8; dr.m_bitLength = payloadByteLength * 8;
dr.m_senderEndpoint = senderEndpoint; dr.m_senderEndpoint = senderEndpoint;
ReleaseMessage(dr); ReleaseMessage(dr);
@@ -460,7 +461,7 @@ namespace Lidgren.Network
// Ok, start handshake! // Ok, start handshake!
NetConnection conn = new NetConnection(this, senderEndpoint); NetConnection conn = new NetConnection(this, senderEndpoint);
m_handshakes.Add(senderEndpoint, conn); m_handshakes.Add(senderEndpoint, conn);
conn.ReceivedHandshake(tp, ptr, payloadByteLength); conn.ReceivedHandshake(now, tp, ptr, payloadByteLength);
return; return;
} }

View File

@@ -67,7 +67,7 @@ namespace Lidgren.Network
// //
// default values // default values
// //
m_disabledTypes = NetIncomingMessageType.ConnectionApproval | NetIncomingMessageType.UnconnectedData | NetIncomingMessageType.VerboseDebugMessage; m_disabledTypes = NetIncomingMessageType.ConnectionApproval | NetIncomingMessageType.UnconnectedData | NetIncomingMessageType.VerboseDebugMessage | NetIncomingMessageType.ConnectionLatencyUpdated;
m_networkThreadName = "Lidgren network thread"; m_networkThreadName = "Lidgren network thread";
m_localAddress = IPAddress.Any; m_localAddress = IPAddress.Any;
m_port = 0; m_port = 0;