public void TickServer(float dt, byte[] recvBuffer, ref NetIOMetrics reliableChannelMetrics, ref NetIOMetrics unreliableChannelMetrics) { if (hostSocketID != -1) { TickSocket(hostConnections, hostCallbacks, hostSocketID, hostReliableChannelID, hostUnreliableChannelID, recvBuffer, ref reliableChannelMetrics, ref unreliableChannelMetrics); } }
public void TickClient(float dt, byte[] recvBuffer, ref NetIOMetrics reliableChannelMetrics, ref NetIOMetrics unreliableChannelMetrics) { Perf.Begin("LocalGameNetDriver.TickClient"); if (clientSend != null) { if (clientSend.connectPending) { clientSend.connectPending = false; clientSend.callbacks.OnConnect(clientSend); } if ((clientSend != null) && (serverSendOfs > 0)) { RecvMessages(serverSendBuffer, serverSendOfs, recvBuffer, clientSend, ref reliableChannelMetrics, ref unreliableChannelMetrics); serverSendOfs = 0; } if ((clientSend != null) && clientSend.disconnectPending) { clientSend.Dispose(); clientSend = null; } } Perf.End(); }
public void TickClient(float dt, byte[] recvBuffer, ref NetIOMetrics reliableChannelMetrics, ref NetIOMetrics unreliableChannelMetrics) { if (clientSocketID != -1) { TickSocket(clientConnections, clientCallbacks, clientSocketID, clientReliableChannelID, clientUnreliableChannelID, recvBuffer, ref reliableChannelMetrics, ref unreliableChannelMetrics); } }
void ReplicateActors(float dt, ref NetIOMetrics reliableMetrics, ref NetIOMetrics unreliableMetrics) { for (int i = 0; i < connectionList.Count;) { var channel = connectionList[i]; if (channel.owningPlayer != null) { channel.ReplicateActors(dt); } channel.connection.driverConnection.GetIOMetrics(ref reliableMetrics, ref unreliableMetrics, true); #if UNITY_EDITOR if (!channel.didHandshake && (channel.handshakeTime > 10f)) { #else if (channel.timedOut || (!channel.didHandshake && (channel.handshakeTime > 10f))) { #endif DisconnectClient(channel.connection, null, EDisconnectReason.TimedOut, channel.timedOut ? channel.timeSinceLastPong + "s" : null); } else { ++i; } } }
public void GetIOMetrics(ref NetIOMetrics reliableMetrics, ref NetIOMetrics unreliableMetrics, bool clear) { reliableMetrics += this.reliableMetrics; unreliableMetrics += new NetIOMetrics(); if (clear) { this.reliableMetrics = new NetIOMetrics(); } }
public virtual void LateUpdate(float dt, ref NetIOMetrics reliableMetrics, ref NetIOMetrics unreliableMetrics) { if (!isTraveling) { LateTickActors(); ReplicateActors(dt, ref reliableMetrics, ref unreliableMetrics); } TickPendingConnections(ref reliableMetrics, ref unreliableMetrics); }
public static NetIOMetrics operator +(NetIOMetrics a, NetIOMetrics b) { var r = new NetIOMetrics(); r.bytesRecv = a.bytesRecv + b.bytesRecv; r.bytesSent = a.bytesSent + b.bytesSent; r.numPacketsRecv = a.numPacketsRecv + b.numPacketsRecv; r.numPacketsSent = a.numPacketsSent + b.numPacketsSent; return(r); }
public void Tick(float dt, MonoBehaviour loadingContext, ref NetIOMetrics reliableMetrics, ref NetIOMetrics unreliableMetrics) { if (!isTraveling) { UpdateTime(Mathf.Min(dt * Time.timeScale, 1 / 3f), dt); } TickWorldStreaming(); netDriver.TickClient(Mathf.Min(dt, 1 / 3f), netMessageBytes, ref reliableMetrics, ref unreliableMetrics); if (_serverConnection != null) { if (isTraveling || _wasTraveling) { TickTravel(loadingContext); if (!isTraveling) { if (_serverConnection != null) { _serverConnection.ResetTimeout(); } FinishTravel(); OnLevelStart(); GC.Collect(); } if (_serverConnection != null) { _serverConnection.ResetTimeoutForTravel(); } } else { TickActors(loadingContext); #if !UNITY_EDITOR if ((_serverConnection != null) && _serverConnection.timedOut) { Debug.LogError("Server connection timed out"); _serverConnection.connection.driverConnection.Dispose(); _serverConnection = null; } #endif } if (_serverConnection != null) { _serverConnection.Ping(dt); _serverConnection.connection.driverConnection.GetIOMetrics(ref reliableMetrics, ref unreliableMetrics, true); } _wasTraveling = isTraveling; } }
public void GetIOMetrics(ref NetIOMetrics reliableMetrics, ref NetIOMetrics unreliableMetrics, bool clear) { reliableMetrics += _reliableMetrics; unreliableMetrics += _unreliableMetrics; if (clear) { _reliableMetrics = new NetIOMetrics(); _unreliableMetrics = new NetIOMetrics(); } }
public override void LateUpdate(float dt, ref NetIOMetrics reliableMetrics, ref NetIOMetrics unreliableMetrics) { try { base.LateUpdate(dt, ref reliableMetrics, ref unreliableMetrics); } catch (Exception e) { Debug.LogException(e); Debug.LogError("Exception occurred in Server::LateUpdate() terminating game server."); if (!GameManager.instance.prewarm) { GameManager.instance.telemetry.ExitGame(); } } }
public void TickClient(float dt, byte[] recvBuffer, ref NetIOMetrics reliableChannelMetrics, ref NetIOMetrics unreliableChannelMetrics) { Perf.Begin("SocketNetDriver.TickClient"); if (_serverConnection != null) { bool wasReset = false; bool isDisposed = false; try { wasReset = _serverConnection.sockets[0].Poll(0, SelectMode.SelectRead); } catch (Exception) { isDisposed = true; } if (isDisposed || (wasReset && (_serverConnection.sockets[0].Available == 0))) { Debug.LogError("Server connection was reset."); _serverConnection.Dispose(); // don't set _serverConnection to null so NetDriverConnection's can be cleaned up correctly. Perf.End(); return; } Recv(_serverConnection, _clientCallbacks, _serverConnection.sockets[0], recvBuffer, ref reliableChannelMetrics, false); if (_serverConnection != null) { Recv(_serverConnection, _clientCallbacks, _serverConnection.sockets[1], recvBuffer, ref unreliableChannelMetrics, true); } if (_serverConnection != null) { if (!_serverConnection.didHandshake && (_serverConnection.channelID != -1)) { _sendUdpControlTimeout -= dt; if (_sendUdpControlTimeout <= 0f) { _sendUdpControlTimeout = UDP_CONTROL_RESEND_TIMEOUT; SendUdpControl(_serverConnection); } } } } Perf.End(); }
void TickPendingConnections(ref NetIOMetrics reliableMetrics, ref NetIOMetrics unreliableMetrics) { for (int i = 0; i < connectionList.Count;) { var channel = connectionList[i]; channel.connection.driverConnection.GetIOMetrics(ref reliableMetrics, ref unreliableMetrics, true); if (channel.didHandshake) { if (channel.pendingConnect) { channel.pendingConnect = false; channel.ResetTimeoutForTravel(); // tell client to travel if (isTraveling) { channel.connection.SendReliable(NetMsgs.ClientTravel.New(travelLevel, null)); } else if (currentLevel != null) { channel.connection.SendReliable(NetMsgs.ClientTravel.New(currentLevel, null)); } } else if (channel.owningPlayer == null) { var result = TickPendingConnection(channel); if (result == EClientConnectResult.Disconnected) { continue; } } } ++i; } }
public void Tick(float dt, MonoBehaviour loadingContext, ref NetIOMetrics reliableMetrics, ref NetIOMetrics unreliableMetrics) { var scaledDt = Mathf.Min(dt * Time.timeScale, 1 / 3f); UpdateTime(scaledDt, dt); TickWorldStreaming(); netDriver.TickServer(Mathf.Min(dt, 1 / 3f), netMessageBytes, ref reliableMetrics, ref unreliableMetrics); if (isTraveling) { TickTravel(loadingContext); if (!isTraveling) { FinishTravel(); OnLevelStart(); GC.Collect(); } } else { TickActors(loadingContext); } }
void Recv(SocketNetDriverConnection connection, INetDriverCallbacks callbacks, Socket socket, byte[] buffer, ref NetIOMetrics metrics, bool isDatagram) { Perf.Begin("SocketNetDriver.Recv"); if (isDatagram) { while (connection.isValid && (socket.Available > 0)) { int r; try { r = socket.Receive(buffer, 0, World.MAX_UNRELIABLE_MESSAGE_SIZE, SocketFlags.None); if (r <= 0) { throw new SocketException((int)SocketError.SocketError); } metrics.bytesRecv += r; ++metrics.numPacketsRecv; } catch (Exception e) { Debug.LogException(e); callbacks.OnInvalidMessageReceived(connection); continue; } if (!connection.didHandshake) { // client may receive a UDP packet before receiving control ACK // so discard the packet until we process the ACK. continue; } callbacks.OnMessageReceived(connection, buffer, r); } } else { while (connection.isValid && (socket.Available > 0)) { if (connection.pendingRecvSize <= 0) { if (socket.Available < 2) { break; } // read from socket. if (socket.Receive(connection.pendingBytes, 0, 2, SocketFlags.None) != 2) { throw new SocketException((int)SocketError.SocketError); } connection.pendingRecvSize = ((int)connection.pendingBytes[0]) | (((int)connection.pendingBytes[1]) << 8); connection.pendingBytesReceived = 0; if (connection.pendingRecvSize > connection.pendingBytes.Length) { callbacks.OnInvalidMessageReceived(connection); continue; } } { // read from socket. var numBytesToRead = Mathf.Min(socket.Available, connection.pendingRecvSize - connection.pendingBytesReceived); if (numBytesToRead > 0) { if (socket.Receive(connection.pendingBytes, connection.pendingBytesReceived, numBytesToRead, SocketFlags.None) != numBytesToRead) { throw new SocketException((int)SocketError.SocketError); } connection.pendingBytesReceived += numBytesToRead; } } Assert.IsTrue(connection.pendingBytesReceived <= connection.pendingRecvSize); if (connection.pendingBytesReceived >= connection.pendingRecvSize) { if (!connection.didHandshake) { if (callbacks == _clientCallbacks) { if (connection.channelID == -1) { var id = RecvControl(connection.pendingBytes, connection.pendingRecvSize); if (id == -1) { connection.Dispose(); break; } connection.channelID = id; _sendUdpControlTimeout = UDP_CONTROL_RESEND_TIMEOUT; SendUdpControl(connection); } else if (connection.pendingBytes[0] == (byte)EControlCode.AckChannelID) { connection.didHandshake = true; callbacks.OnConnect(connection); } else { // invalid response connection.Dispose(); break; } } else { connection.Dispose(); break; } connection.pendingRecvSize = 0; connection.pendingBytesReceived = 0; continue; } Array.Copy(connection.pendingBytes, buffer, connection.pendingRecvSize); var r = connection.pendingRecvSize; connection.pendingBytesReceived = 0; connection.pendingRecvSize = 0; metrics.bytesRecv += r; ++metrics.numPacketsRecv; callbacks.OnMessageReceived(connection, buffer, r); continue; } // not enough data ready break; } } Perf.End(); }
void RecvMessages(byte[] src, int srcLen, byte[] dst, LocalGameNetDriverConnection conn, ref NetIOMetrics reliableChannelMetrics, ref NetIOMetrics unreliableChannelMetrics) { Perf.Begin("LocalGameNetDriver.RecvMessages"); for (int i = 0; i < srcLen - 4;) { if (!conn.isValid) { break; } int msgLen = System.BitConverter.ToInt32(src, i); i += 4; Assert.IsTrue(msgLen > 0); if (msgLen > 0) { System.Array.Copy(src, i, dst, 0, msgLen); try { Perf.Begin("LocalGameNetDriver.RecvMessages.Callbacks.OnMessageReceived"); conn.callbacks.OnMessageReceived(conn, dst, msgLen); Perf.End(); } catch (System.Exception e) { Debug.LogException(e); } } else { conn.callbacks.OnInvalidMessageReceived(conn); } i += msgLen; // increment before callback in-case there is an exception reliableChannelMetrics.bytesRecv += msgLen; ++reliableChannelMetrics.numPacketsRecv; } Perf.End(); }
void TickSocket(IntHashtable <UnityNetDriverConnection> connections, INetDriverCallbacks callbacks, int socketID, int reliableChannelID, int unreliableChannelID, byte[] recvBuffer, ref NetIOMetrics reliableChannelMetrics, ref NetIOMetrics unreliableChannelMetrics) { int connectionID; int recvSize; int channelID; byte error; while (true) { NetworkEventType eventType = NetworkTransport.ReceiveFromHost(socketID, out connectionID, out channelID, recvBuffer, recvBuffer.Length, out recvSize, out error); switch (eventType) { case NetworkEventType.ConnectEvent: { var conn = GetConnection(connections, connectionID); if (conn == null) { conn = CreateConnection(connections, callbacks, socketID, connectionID, reliableChannelID, unreliableChannelID); } callbacks.OnConnect(conn); } break; case NetworkEventType.DisconnectEvent: { var conn = GetConnection(connections, connectionID); if (conn == null) { conn = CreateConnection(connections, callbacks, socketID, connectionID, reliableChannelID, unreliableChannelID); } conn.callbacks = null; callbacks.OnDisconnect(conn); RemoveConnection(connections, connectionID); } break; case NetworkEventType.DataEvent: { var conn = GetConnection(connections, connectionID); if (conn != null) { if (channelID == reliableChannelID) { reliableChannelMetrics.bytesRecv += recvSize; ++reliableChannelMetrics.numPacketsRecv; } else { unreliableChannelMetrics.bytesRecv += recvSize; ++unreliableChannelMetrics.numPacketsRecv; } if (error == (byte)NetworkError.MessageToLong) { callbacks.OnInvalidMessageReceived(conn); } else { callbacks.OnMessageReceived(conn, recvBuffer, recvSize); } } } break; default: return; } } }
public void TickServer(float dt, byte[] recvBuffer, ref NetIOMetrics reliableChannelMetrics, ref NetIOMetrics unreliableChannelMetrics) { Perf.Begin("SocketNetDriver.TickServer"); for (;;) { Socket newSocket; try { newSocket = _serverSock[0].Accept(); } catch (SocketException) { break; } if (_tcpConnections.ContainsKey(newSocket.RemoteEndPoint)) { Debug.LogError("Connection attempt from already connected client!"); newSocket.Close(); continue; } var clientSocks = new Socket[2]; clientSocks[0] = newSocket; clientSocks[1] = _serverSock[1]; newSocket.Blocking = false; //newSocket.NoDelay = true; newSocket.SendBufferSize = World.MAX_RELIABLE_MESSAGE_SIZE * 8; newSocket.SendTimeout = 500; var newConn = new SocketNetDriverConnection(this, clientSocks, nextChannelID++); _tcpConnections.Add(newSocket.RemoteEndPoint, newConn); SendTcpControl(newConn); } for (int i = 0; i < _tcpConnections.Values.Count;) { var c = _tcpConnections.Values[i]; bool wasReset = false; bool isDisposed = false; try { wasReset = c.sockets[0].Poll(0, SelectMode.SelectRead); } catch (Exception) { isDisposed = true; } if (isDisposed || (wasReset && (c.sockets[0].Available == 0))) { c.Dispose(); continue; } Recv(c, _serverCallbacks, c.sockets[0], recvBuffer, ref reliableChannelMetrics, false); if (c.isValid && !c.didHandshake) { c.handshakeTime += dt; if (c.handshakeTime > UDP_CONTROL_DISCONNECT_TIMEOUT) { // handshake failed Debug.LogError("Disconnecting " + c.tcpEndpoint.ToString() + ": udp handshake timed out"); c.Dispose(); } } if (c.isValid) { ++i; } } RecvFrom(_serverCallbacks, _serverSock[1], recvBuffer, ref unreliableChannelMetrics); Perf.End(); }
void RecvFrom(INetDriverCallbacks callbacks, Socket socket, byte[] buffer, ref NetIOMetrics metrics) { Perf.Begin("SocketNetDriver.RecvFrom"); while (socket.Available > 0) { int r; try { r = socket.ReceiveFrom(buffer, 0, World.MAX_UNRELIABLE_MESSAGE_SIZE, SocketFlags.None, ref _recvEndPoint); } catch (Exception e) { Debug.LogException(e); SocketNetDriverConnection conn; if (_udpConnections.TryGetValue(_recvEndPoint, out conn)) { callbacks.OnInvalidMessageReceived(conn); } continue; } if (r <= 0) { throw new SocketException((int)SocketError.SocketError); } metrics.bytesRecv += r; ++metrics.numPacketsRecv; SocketNetDriverConnection connection; if (_udpConnections.TryGetValue(_recvEndPoint, out connection)) { if (connection.isValid) { if (r > 3) { // currently NetMsgs are always more than 3 bytes, and this guarantees that we don't // try to process a duplicated control udp control message. callbacks.OnMessageReceived(connection, buffer, r); } } } else { // is this a control code? var id = RecvControl(buffer, r); if (id != -1) { for (int i = 0; i < _tcpConnections.Values.Count; ++i) { var c = _tcpConnections.Values[i]; if (c.channelID == id) { if (_udpConnections.Values.Contains(c)) { Debug.LogWarning("UDP control message received for registered channel."); } else { c.udpEndpoint = new IPEndPoint(((IPEndPoint)_recvEndPoint).Address, ((IPEndPoint)_recvEndPoint).Port); _udpConnections.Add(c.udpEndpoint, c); SendTcpControlAck(c); c.didHandshake = true; callbacks.OnConnect(c); break; } } } } } } Perf.End(); }