public override void PostEvent(IScriptEvent e)
 {
     if (IsRunning && IsRunningAllowed && !IsAborting)
     {
         m_Events.Enqueue(e);
         Part.ObjectGroup.Scene.ScriptThreadPool.PostScript(this);
     }
 }
Esempio n. 2
0
        public void PacketReceived(EndPoint ep, UDPPacket pck, List <UInt32> acknumbers)
        {
            /* no need for returning packets here since we are obliqued never to pass them around.
             * We just decode them here to actual messages
             */
            MessageType mType = pck.ReadMessageType();

            m_LastReceivedPacketAtTime = Environment.TickCount;

            Interlocked.Increment(ref m_PacketsReceived);

            /* do we have some acks from the packet's end? */
            if (acknumbers != null)
            {
                int  unackedReleasedCount = 0;
                bool ackedObjects         = false;
                bool ackedSomethingElse   = false;
                foreach (UInt32 ackno in acknumbers)
                {
                    UDPPacket p_acked = null;
                    lock (m_UnackedPacketsHash)
                    {
                        if (m_UnackedPacketsHash.Contains(ackno))
                        {
                            p_acked = m_UnackedPacketsHash[ackno];
                            m_UnackedPacketsHash.Remove(ackno);
                        }
                    }

                    if (p_acked != null)
                    {
                        unackedReleasedCount += p_acked.DataLength;
                        Interlocked.Decrement(ref m_AckThrottlingCount[(int)p_acked.OutQueue]);
                        if (p_acked.OutQueue == Message.QueueOutType.Object)
                        {
                            m_TxObjectPool.Enqueue(p_acked);
                            ackedObjects = true;
                        }
                        else
                        {
                            ackedSomethingElse = true;
                        }
                        if (p_acked.AckMessage != null)
                        {
                            try
                            {
                                p_acked.AckMessage.OnSendComplete(true);
                            }
                            catch (Exception e)
                            {
                                m_Log.WarnFormat("OnSendCompletion: Exception {0} at {1}", e.ToString(), e.StackTrace);
                            }
                        }
                    }

                    if (ackedSomethingElse)
                    {
                        m_TxQueue.Enqueue(new AcksReceived());
                    }
                    if (ackedObjects)
                    {
                        CheckForNewDataToSend();
                    }

                    lock (m_LogoutReplyLock)
                    {
                        if (ackno == m_LogoutReplySeqNo && m_LogoutReplySent)
                        {
                            LogMsgOnLogoutCompletion();
                            TerminateCircuit();
                            return;
                        }
                    }
                }
                lock (m_UnackedBytesLock)
                {
                    m_UnackedBytes -= unackedReleasedCount;
                }
            }

            if (pck.IsReliable)
            {
                /* we have to ack */
                switch (mType)
                {
                case MessageType.CompleteAgentMovement:
                    /* Immediate ack */
                    SendCircuitPacket(UDPPacket.PacketAckImmediate(pck.SequenceNumber));
                    break;

                default:
                    m_AckList.Enqueue(pck.SequenceNumber);
                    break;
                }
            }

            /* we know the message type now, so we have to decode it when possible */
            switch (mType)
            {
            case MessageType.PacketAck:
                /* we decode it here, no need to pass it anywhere else */
                int  unackedReleasedCount = 0;
                bool ackedObjects         = false;
                bool ackedSomethingElse   = false;
                uint cnt = pck.ReadUInt8();
                for (uint i = 0; i < cnt; ++i)
                {
                    uint      ackno   = pck.ReadUInt32();
                    UDPPacket p_acked = null;
                    lock (m_UnackedPacketsHash)
                    {
                        if (m_UnackedPacketsHash.Contains(ackno))
                        {
                            p_acked = m_UnackedPacketsHash[ackno];
                            m_UnackedPacketsHash.Remove(ackno);
                        }
                    }
                    if (p_acked != null)
                    {
                        unackedReleasedCount += p_acked.DataLength;
                        Interlocked.Decrement(ref m_AckThrottlingCount[(int)p_acked.OutQueue]);
                        if (p_acked.OutQueue == Message.QueueOutType.Object)
                        {
                            m_TxObjectPool.Enqueue(p_acked);
                            ackedObjects = true;
                        }
                        else
                        {
                            ackedSomethingElse = true;
                        }

                        if (p_acked.AckMessage != null)
                        {
                            try
                            {
                                p_acked.AckMessage.OnSendComplete(true);
                            }
                            catch (Exception e)
                            {
                                m_Log.WarnFormat("OnSendCompletion: Exception {0} at {1}", e.ToString(), e.StackTrace);
                            }
                        }
                    }

                    lock (m_LogoutReplyLock)
                    {
                        if (ackno == m_LogoutReplySeqNo && m_LogoutReplySent)
                        {
                            LogMsgOnLogoutCompletion();
                            TerminateCircuit();
                            return;
                        }
                    }
                }

                if (ackedSomethingElse)
                {
                    m_TxQueue.Enqueue(new AcksReceived());
                }
                if (ackedObjects)
                {
                    CheckForNewDataToSend();
                }

                lock (m_UnackedBytesLock)
                {
                    m_UnackedBytes -= unackedReleasedCount;
                }
                break;

            case MessageType.StartPingCheck:
                byte pingID = pck.ReadUInt8();
                pck.ReadUInt32();

                var newpck = new UDPPacket();
                newpck.WriteMessageNumber(MessageType.CompletePingCheck);
                newpck.WriteUInt8(pingID);
                SendCircuitPacket(newpck);
                /* check for unacks */
                try
                {
                    foreach (uint keyval in m_UnackedPacketsHash.Keys)
                    {
                        UDPPacket Value;
                        lock (m_UnackedPacketsHash)
                        {
                            if (!m_UnackedPacketsHash.Contains(keyval))
                            {
                                continue;
                            }
                            Value = m_UnackedPacketsHash[keyval];
                        }
                        if (Environment.TickCount - Value.TransferredAtTime > 1000)
                        {
                            if (Value.ResentCount < 5)
                            {
                                Value.TransferredAtTime = Environment.TickCount;
                                Value.IsResent          = true;
                                Server.SendPacketTo(Value, RemoteEndPoint);
                            }
                            ++Value.ResentCount;
                        }
                    }
                }
                catch
                {
                    /* no action required */
                }
                break;

            case MessageType.CompletePingCheck:
                byte ackPingID = pck.ReadUInt8();
                long timesent;
                if (m_PingSendTicks.Remove(ackPingID, out timesent))
                {
                    LastMeasuredLatencyMsecs = (int)PingTimeSource.TicksToMsecs(PingTimeSource.TicksElapsed(PingTimeSource.TickCount, timesent)) / 2;
                }
                break;

            default:
                bool isnewpacket = true;

                if (pck.IsReliable)
                {
                    lock (m_ResentAge)
                    {
                        uint seqNo = pck.SequenceNumber;

                        isnewpacket = !m_ResentDetectSet.Contains(seqNo) || !pck.IsResent;
                        if (isnewpacket)
                        {
                            m_ResentAge.Add(new ResendAge {
                                SeqNo = seqNo, TickCount = Environment.TickCount
                            });
                            m_ResentDetectSet.Add(seqNo);
                        }
                    }
                }

                if (isnewpacket)
                {
                    OnCircuitSpecificPacketReceived(mType, pck);
                }
                break;
            }

            lock (m_ResentAge)
            {
                if (m_ResentAge.Count > 0)
                {
                    ResendAge age    = m_ResentAge[0];
                    int       actAge = Environment.TickCount - age.TickCount;
                    if (actAge > 30000)
                    {
                        m_ResentDetectSet.Remove(age.SeqNo);
                        m_ResentAge.RemoveAt(0);
                    }
                }
            }
        }