Exemple #1
0
        // tick: processes up to 'limit' messages for each connection
        // => limit parameter to avoid deadlocks / too long freezes if server or
        //    client is too slow to process network load
        // => Mirror & DOTSNET need to have a process limit anyway.
        //    might as well do it here and make life easier.
        // => returns amount of remaining messages to process, so the caller
        //    can call tick again as many times as needed (or up to a limit)
        //
        // Tick() may process multiple messages, but Mirror needs a way to stop
        // processing immediately if a scene change messages arrives. Mirror
        // can't process any other messages during a scene change.
        // (could be useful for others too)
        // => make sure to allocate the lambda only once in transports
        public int Tick(int processLimit, Func <bool> checkEnabled = null)
        {
            // only if pipe was created yet (after start())
            if (receivePipe == null)
            {
                return(0);
            }

            // process up to 'processLimit' messages for this connection
            for (int i = 0; i < processLimit; ++i)
            {
                // check enabled in case a Mirror scene message arrived
                if (checkEnabled != null && !checkEnabled())
                {
                    break;
                }

                // peek first. allows us to process the first queued entry while
                // still keeping the pooled byte[] alive by not removing anything.
                if (receivePipe.TryPeek(out int connectionId, out EventType eventType, out ArraySegment <byte> message))
                {
                    switch (eventType)
                    {
                    case EventType.Connected:
                        OnConnected?.Invoke(connectionId);
                        break;

                    case EventType.Data:
                        OnData?.Invoke(connectionId, message);
                        break;

                    case EventType.Disconnected:
                        OnDisconnected?.Invoke(connectionId);
                        // remove disconnected connection now that the final
                        // disconnected message was processed.
                        clients.TryRemove(connectionId, out ConnectionState _);
                        break;
                    }

                    // IMPORTANT: now dequeue and return it to pool AFTER we are
                    //            done processing the event.
                    receivePipe.TryDequeue();
                }
Exemple #2
0
        public int Tick(int processLimit, Func <bool> checkEnabled = null)
        {
            int remaining = 0;

            // for each connection
            // checks enabled in case a Mirror scene message arrived
            foreach (KeyValuePair <int, ConnectionState> kvp in clients)
            {
                MagnificentReceivePipe receivePipe = kvp.Value.receivePipe;

                // need a processLimit copy just for this connection so that
                // we can count the Connected message as a processed one.
                // => otherwise decreasing the limit in Connected event would
                //    decrease the limit for everyone!
                int connectionProcessLimit = processLimit;

                // always process connect FIRST before anything else
                if (connectionProcessLimit > 0)
                {
                    if (receivePipe.CheckConnected())
                    {
                        OnConnected?.Invoke(kvp.Key);
                        // it counts as a processed message
                        --connectionProcessLimit;
                    }
                }

                // process up to 'processLimit' messages for this connection
                // checks enabled in case a Mirror scene message arrived
                for (int i = 0; i < connectionProcessLimit; ++i)
                {
                    // check enabled in case a Mirror scene message arrived
                    if (checkEnabled != null && !checkEnabled())
                    {
                        break;
                    }

                    // peek first. allows us to process the first queued entry while
                    // still keeping the pooled byte[] alive by not removing anything.
                    if (receivePipe.TryPeek(out ArraySegment <byte> message))
                    {
                        OnData?.Invoke(kvp.Key, message);

                        // IMPORTANT: now dequeue and return it to pool AFTER we are
                        //            done processing the event.
                        receivePipe.TryDequeue();
                    }

                    // AFTER PROCESSING, add remaining ones to our counter
                    remaining += receivePipe.Count;
                }

                // always process disconnect AFTER anything else
                // (should never process data messages after disconnect message)
                if (connectionProcessLimit > 0)
                {
                    if (receivePipe.CheckDisconnected())
                    {
                        OnDisconnected?.Invoke(kvp.Key);
                        connectionsToRemove.Add(kvp.Key);
                    }
                }
            }

            // remove all disconnected connections now that we processed the
            // final disconnect message.
            foreach (int connectionId in connectionsToRemove)
            {
                clients.TryRemove(connectionId, out ConnectionState _);
            }
            connectionsToRemove.Clear();

            return(remaining);
        }