public override void PostEvent(IScriptEvent e) { if (IsRunning && IsRunningAllowed && !IsAborting) { m_Events.Enqueue(e); Part.ObjectGroup.Scene.ScriptThreadPool.PostScript(this); } }
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); } } } }