breaking: fix: kcp2k V1.16

- fix: SendUnreliable respects ArraySegment.Offset
- fix: potential bug with negative length (see PR #2)
- breaking: removed pause handling because it's not necessary for Mirror anymore
This commit is contained in:
vis2k 2022-01-06 20:47:07 +08:00
parent 7e0f649f59
commit 2cacb89fae
7 changed files with 18 additions and 97 deletions

View File

@ -162,35 +162,14 @@ public override void ClientSend(ArraySegment<byte> segment, int channelId)
// process incoming in early update
public override void ClientEarlyUpdate()
{
// scene change messages disable transports to stop them from
// processing while changing the scene.
// -> we need to check enabled here
// -> and in kcp's internal loops, see Awake() OnCheckEnabled setup!
// only process messages while transport is enabled.
// scene change messsages disable it to stop processing.
// (see also: https://github.com/vis2k/Mirror/pull/379)
if (enabled) client.TickIncoming();
}
// process outgoing in late update
public override void ClientLateUpdate() => client.TickOutgoing();
// scene change message will disable transports.
// kcp processes messages in an internal loop which should be
// stopped immediately after scene change (= after disabled)
// => kcp has tests to guaranteed that calling .Pause() during the
// receive loop stops the receive loop immediately, not after.
void OnEnable()
{
// unpause when enabled again
client?.Unpause();
server?.Unpause();
}
void OnDisable()
{
// pause immediately when not enabled anymore
client?.Pause();
server?.Pause();
}
// server
public override Uri ServerUri()
{
@ -211,10 +190,8 @@ public override void ServerSend(int connectionId, ArraySegment<byte> segment, in
public override void ServerStop() => server.Stop();
public override void ServerEarlyUpdate()
{
// scene change messages disable transports to stop them from
// processing while changing the scene.
// -> we need to check enabled here
// -> and in kcp's internal loops, see Awake() OnCheckEnabled setup!
// only process messages while transport is enabled.
// scene change messsages disable it to stop processing.
// (see also: https://github.com/vis2k/Mirror/pull/379)
if (enabled) server.TickIncoming();
}

View File

@ -1,3 +1,8 @@
V1.16 [2022-01-06]
- fix: SendUnreliable respects ArraySegment.Offset
- fix: potential bug with negative length (see PR #2)
- breaking: removed pause handling because it's not necessary for Mirror anymore
V1.15 [2021-12-11]
- feature: feature: MaxRetransmits aka dead_link now configurable
- dead_link disconnect message improved to show exact retransmit count

View File

@ -111,10 +111,5 @@ public void Tick()
TickIncoming();
TickOutgoing();
}
// pause/unpause to safely support mirror scene handling and to
// immediately pause the receive while loop if needed.
public void Pause() => connection?.Pause();
public void Unpause() => connection?.Unpause();
}
}

View File

@ -17,6 +17,7 @@ public static bool ResolveHostname(string hostname, out IPAddress[] addresses)
{
try
{
// NOTE: dns lookup is blocking. this can take a second.
addresses = Dns.GetHostAddresses(hostname);
return addresses.Length >= 1;
}

View File

@ -20,12 +20,6 @@ public abstract class KcpConnection
public Action<ArraySegment<byte>, KcpChannel> OnData;
public Action OnDisconnected;
// Mirror needs a way to stop the kcp message processing while loop
// immediately after a scene change message. Mirror can't process any
// other messages during a scene change.
// (could be useful for others too)
bool paused;
// If we don't receive anything these many milliseconds
// then consider us disconnected
public const int DEFAULT_TIMEOUT = 10000;
@ -315,19 +309,7 @@ void TickIncoming_Authenticated(uint time)
HandleChoked();
// process all received messages
//
// Mirror scene changing requires transports to immediately stop
// processing any more messages after a scene message was
// received. and since we are in a while loop here, we need this
// extra check.
//
// note while that this is mainly for Mirror, but might be
// useful in other applications too.
//
// note that we check it BEFORE ever calling ReceiveNext. otherwise
// we would silently eat the received message and never process it.
while (!paused &&
ReceiveNextReliable(out KcpHeader header, out ArraySegment<byte> message))
while (ReceiveNextReliable(out KcpHeader header, out ArraySegment<byte> message))
{
// message type FSM. no default so we never miss a case.
switch (header)
@ -498,16 +480,9 @@ public void RawInput(byte[] buffer, int msgLength)
// -> let's skip the magic and call OnData directly if
// the current state allows it.
if (state == KcpState.Authenticated)
{
// only process messages while not paused for Mirror
// scene switching etc.
// -> if an unreliable message comes in while
// paused, simply drop it. it's unreliable!
if (!paused)
{
ArraySegment<byte> message = new ArraySegment<byte>(buffer, 1, msgLength - 1);
OnData?.Invoke(message, KcpChannel.Unreliable);
}
// set last receive time to avoid timeout.
// -> we do this in ANY case even if not enabled.
@ -578,7 +553,7 @@ void SendUnreliable(ArraySegment<byte> message)
{
// copy channel header, data into raw send buffer, then send
rawSendBuffer[0] = (byte)KcpChannel.Unreliable;
Buffer.BlockCopy(message.Array, 0, rawSendBuffer, 1, message.Count);
Buffer.BlockCopy(message.Array, message.Offset, rawSendBuffer, 1, message.Count);
RawSend(rawSendBuffer, message.Count + 1);
}
// otherwise content is larger than MaxMessageSize. let user know!
@ -668,24 +643,5 @@ public void Disconnect()
// get remote endpoint
public EndPoint GetRemoteEndPoint() => remoteEndPoint;
// pause/unpause to safely support mirror scene handling and to
// immediately pause the receive while loop if needed.
public void Pause() => paused = true;
public void Unpause()
{
// unpause
paused = false;
// reset the timeout.
// we have likely been paused for > timeout seconds, but that
// doesn't mean we should disconnect. for example, Mirror pauses
// kcp during scene changes which could easily take > 10s timeout:
// see also: https://github.com/vis2k/kcp2k/issues/8
// => Unpause completely resets the timeout instead of restoring the
// time difference when we started pausing. it's more simple and
// it's a good idea to start counting from 0 after we unpaused!
lastReceiveTime = (uint)refTime.ElapsedMilliseconds;
}
}
}

View File

@ -323,19 +323,5 @@ public void Stop()
socket?.Close();
socket = null;
}
// pause/unpause to safely support mirror scene handling and to
// immediately pause the receive while loop if needed.
public void Pause()
{
foreach (KcpServerConnection connection in connections.Values)
connection.Pause();
}
public void Unpause()
{
foreach (KcpServerConnection connection in connections.Values)
connection.Unpause();
}
}
}

View File

@ -27,7 +27,7 @@ public class Kcp
public const int INTERVAL = 100;
public const int OVERHEAD = 24;
public const int FRG_MAX = byte.MaxValue; // kcp encodes 'frg' as byte. so we can only ever send up to 255 fragments.
public const int DEADLINK = 20; // default maximum amount of 'xmit' retransmissions until a message is considered lost
public const int DEADLINK = 20; // default maximum amount of 'xmit' retransmissions until a segment is considered lost
public const int THRESH_INIT = 2;
public const int THRESH_MIN = 2;
public const int PROBE_INIT = 7000; // 7 secs to probe window size
@ -65,7 +65,7 @@ internal struct AckItem
internal bool updated;
internal uint ts_probe; // timestamp probe
internal uint probe_wait;
internal uint dead_link; // maximum amount of 'xmit' retransmissions until a message is considered lost
internal uint dead_link; // maximum amount of 'xmit' retransmissions until a segment is considered lost
internal uint incr;
internal uint current; // current time (milliseconds). set by Update.
@ -535,7 +535,8 @@ public int Input(byte[] data, int offset, int size)
size -= OVERHEAD;
// enough remaining to read 'len' bytes of the actual payload?
if (size < len || len < 0) return -2;
// note: original kcp casts uint len to int for <0 check.
if (size < len || (int)len < 0) return -2;
if (cmd != CMD_PUSH && cmd != CMD_ACK &&
cmd != CMD_WASK && cmd != CMD_WINS)