void TickConnected(uint time) { // detect common events & ping HandleTimeout(time); HandleDeadLink(); HandlePing(time); HandleChoked(); kcp.Update(time); // any message received? if (ReceiveNext(out ArraySegment <byte> message)) { // handshake message? if (Utils.SegmentsEqual(message, Hello)) { Debug.Log("KCP: received handshake"); state = KcpState.Authenticated; OnAuthenticated?.Invoke(); } // otherwise it's random data from the internet, not // from a legitimate player. disconnect. else { Debug.LogWarning("KCP: received random data before handshake. Disconnecting the connection."); Disconnect(); } } }
// TODO respect check result. // for now let's call every update. public void Tick() { try { lastReceived = kcp.CurrentMS; if (open && kcp.CurrentMS < lastReceived + TIMEOUT) { kcp.Update(); int check = kcp.Check(); // call every 10 ms unless check says we can wait longer if (check < 10) { check = 10; } } } catch (SocketException) { // this is ok, the connection was closed open = false; } catch (ObjectDisposedException) { // fine, socket was closed, no more ticking needed open = false; } catch (Exception ex) { open = false; Debug.LogException(ex); } }
void TickConnected(uint time) { // detect common events & ping HandleTimeout(time); HandleDeadLink(); HandlePing(time); HandleChoked(); kcp.Update(time); // any reliable kcp message received? if (ReceiveNextReliable(out KcpHeader header, out ArraySegment <byte> message)) { // message type FSM. no default so we never miss a case. switch (header) { case KcpHeader.Handshake: { // we were waiting for a handshake. // it proves that the other end speaks our protocol. Log.Info("KCP: received handshake"); state = KcpState.Authenticated; OnAuthenticated?.Invoke(); break; } case KcpHeader.Ping: { // ping keeps kcp from timing out. do nothing. break; } case KcpHeader.Data: case KcpHeader.Disconnect: { // everything else is not allowed during handshake! Log.Warning($"KCP: received invalid header {header} while Connected. Disconnecting the connection."); Disconnect(); break; } } } }
public void TickOutgoing() { uint time = (uint)refTime.ElapsedMilliseconds; try { switch (state) { case KcpState.Connected: case KcpState.Authenticated: { // update flushes out messages kcp.Update(time); break; } case KcpState.Disconnected: { // do nothing while disconnected break; } } } catch (SocketException exception) { // this is ok, the connection was closed // pass error to user callback. no need to log it manually. OnError(ErrorCode.ConnectionClosed, $"KCP Connection: Disconnecting because {exception}. This is fine."); Disconnect(); } catch (ObjectDisposedException exception) { // fine, socket was closed // pass error to user callback. no need to log it manually. OnError(ErrorCode.ConnectionClosed, $"KCP Connection: Disconnecting because {exception}. This is fine."); Disconnect(); } catch (Exception exception) { // unexpected // pass error to user callback. no need to log it manually. OnError(ErrorCode.Unexpected, $"KCP Connection: unexpected exception: {exception}"); Disconnect(); } }
public void TickOutgoing() { uint time = (uint)refTime.ElapsedMilliseconds; try { switch (state) { case KcpState.Connected: case KcpState.Authenticated: { // update flushes out messages kcp.Update(time); break; } case KcpState.Disconnected: { // do nothing while disconnected break; } } } catch (SocketException exception) { // this is ok, the connection was closed Log.Info($"KCP Connection: Disconnecting because {exception}. This is fine."); Disconnect(); } catch (ObjectDisposedException exception) { // fine, socket was closed Log.Info($"KCP Connection: Disconnecting because {exception}. This is fine."); Disconnect(); } catch (Exception ex) { // unexpected Log.Error(ex.ToString()); Disconnect(); } }