Exemple #1
0
 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);
     }
 }
Exemple #2
0
    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();
    }
Exemple #3
0
 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;
                }
            }
        }
Exemple #5
0
    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);
    }
Exemple #8
0
        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;
            }
        }
Exemple #9
0
    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();
    }
Exemple #15
0
    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();
    }
Exemple #16
0
    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();
    }