diff options
Diffstat (limited to 'OpenSim')
-rw-r--r-- | OpenSim/Framework/IClientAPI.cs | 59 | ||||
-rw-r--r-- | OpenSim/Framework/Util.cs | 17 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 96 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | 64 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs | 6 |
5 files changed, 176 insertions, 66 deletions
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index f573c32..069987b 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs | |||
@@ -572,34 +572,69 @@ namespace OpenSim.Framework | |||
572 | 572 | ||
573 | public class IEntityUpdate | 573 | public class IEntityUpdate |
574 | { | 574 | { |
575 | public ISceneEntity Entity; | 575 | private ISceneEntity m_entity; |
576 | public uint Flags; | 576 | private uint m_flags; |
577 | private int m_updateTime; | ||
578 | |||
579 | public ISceneEntity Entity | ||
580 | { | ||
581 | get { return m_entity; } | ||
582 | } | ||
583 | |||
584 | public uint Flags | ||
585 | { | ||
586 | get { return m_flags; } | ||
587 | } | ||
588 | |||
589 | public int UpdateTime | ||
590 | { | ||
591 | get { return m_updateTime; } | ||
592 | } | ||
577 | 593 | ||
578 | public virtual void Update(IEntityUpdate update) | 594 | public virtual void Update(IEntityUpdate update) |
579 | { | 595 | { |
580 | this.Flags |= update.Flags; | 596 | m_flags |= update.Flags; |
597 | |||
598 | // Use the older of the updates as the updateTime | ||
599 | if (Util.EnvironmentTickCountCompare(UpdateTime, update.UpdateTime) > 0) | ||
600 | m_updateTime = update.UpdateTime; | ||
581 | } | 601 | } |
582 | 602 | ||
583 | public IEntityUpdate(ISceneEntity entity, uint flags) | 603 | public IEntityUpdate(ISceneEntity entity, uint flags) |
584 | { | 604 | { |
585 | Entity = entity; | 605 | m_entity = entity; |
586 | Flags = flags; | 606 | m_flags = flags; |
607 | m_updateTime = Util.EnvironmentTickCount(); | ||
608 | } | ||
609 | |||
610 | public IEntityUpdate(ISceneEntity entity, uint flags, Int32 updateTime) | ||
611 | { | ||
612 | m_entity = entity; | ||
613 | m_flags = flags; | ||
614 | m_updateTime = updateTime; | ||
587 | } | 615 | } |
588 | } | 616 | } |
589 | |||
590 | 617 | ||
591 | public class EntityUpdate : IEntityUpdate | 618 | public class EntityUpdate : IEntityUpdate |
592 | { | 619 | { |
593 | // public ISceneEntity Entity; | 620 | private float m_timeDilation; |
594 | // public PrimUpdateFlags Flags; | 621 | |
595 | public float TimeDilation; | 622 | public float TimeDilation |
623 | { | ||
624 | get { return m_timeDilation; } | ||
625 | } | ||
596 | 626 | ||
597 | public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, float timedilation) | 627 | public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, float timedilation) |
598 | : base(entity,(uint)flags) | 628 | : base(entity, (uint)flags) |
599 | { | 629 | { |
600 | //Entity = entity; | ||
601 | // Flags = flags; | 630 | // Flags = flags; |
602 | TimeDilation = timedilation; | 631 | m_timeDilation = timedilation; |
632 | } | ||
633 | |||
634 | public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, float timedilation, Int32 updateTime) | ||
635 | : base(entity,(uint)flags,updateTime) | ||
636 | { | ||
637 | m_timeDilation = timedilation; | ||
603 | } | 638 | } |
604 | } | 639 | } |
605 | 640 | ||
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 5a5046e..aaa2724 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs | |||
@@ -1537,6 +1537,23 @@ namespace OpenSim.Framework | |||
1537 | return (diff >= 0) ? diff : (diff + EnvironmentTickCountMask + 1); | 1537 | return (diff >= 0) ? diff : (diff + EnvironmentTickCountMask + 1); |
1538 | } | 1538 | } |
1539 | 1539 | ||
1540 | // Returns value of Tick Count A - TickCount B accounting for wrapping of TickCount | ||
1541 | // Assumes both tcA and tcB came from previous calls to Util.EnvironmentTickCount(). | ||
1542 | // A positive return value indicates A occured later than B | ||
1543 | public static Int32 EnvironmentTickCountCompare(Int32 tcA, Int32 tcB) | ||
1544 | { | ||
1545 | // A, B and TC are all between 0 and 0x3fffffff | ||
1546 | int tc = EnvironmentTickCount(); | ||
1547 | |||
1548 | if (tc - tcA >= 0) | ||
1549 | tcA += EnvironmentTickCountMask + 1; | ||
1550 | |||
1551 | if (tc - tcB >= 0) | ||
1552 | tcB += EnvironmentTickCountMask + 1; | ||
1553 | |||
1554 | return tcA - tcB; | ||
1555 | } | ||
1556 | |||
1540 | /// <summary> | 1557 | /// <summary> |
1541 | /// Prints the call stack at any given point. Useful for debugging. | 1558 | /// Prints the call stack at any given point. Useful for debugging. |
1542 | /// </summary> | 1559 | /// </summary> |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 1f7e66d..14c5d6c 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | |||
@@ -3561,6 +3561,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3561 | m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation)); | 3561 | m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation)); |
3562 | } | 3562 | } |
3563 | 3563 | ||
3564 | /// <summary> | ||
3565 | /// Requeue an EntityUpdate when it was not acknowledged by the client. | ||
3566 | /// We will update the priority and put it in the correct queue, merging update flags | ||
3567 | /// with any other updates that may be queued for the same entity. | ||
3568 | /// The original update time is used for the merged update. | ||
3569 | /// </summary> | ||
3570 | public void ResendPrimUpdate(EntityUpdate update) | ||
3571 | { | ||
3572 | // If the update exists in priority queue, it will be updated. | ||
3573 | // If it does not exist then it will be added with the current (rather than its original) priority | ||
3574 | uint priority = m_prioritizer.GetUpdatePriority(this, update.Entity); | ||
3575 | |||
3576 | lock (m_entityUpdates.SyncRoot) | ||
3577 | m_entityUpdates.Enqueue(priority, update); | ||
3578 | } | ||
3579 | |||
3580 | /// <summary> | ||
3581 | /// Requeue a list of EntityUpdates when they were not acknowledged by the client. | ||
3582 | /// We will update the priority and put it in the correct queue, merging update flags | ||
3583 | /// with any other updates that may be queued for the same entity. | ||
3584 | /// The original update time is used for the merged update. | ||
3585 | /// </summary> | ||
3586 | void ResendPrimUpdates(List<EntityUpdate> updates) | ||
3587 | { | ||
3588 | foreach (EntityUpdate update in updates) | ||
3589 | ResendPrimUpdate(update); | ||
3590 | } | ||
3591 | |||
3564 | private void ProcessEntityUpdates(int maxUpdates) | 3592 | private void ProcessEntityUpdates(int maxUpdates) |
3565 | { | 3593 | { |
3566 | OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>(); | 3594 | OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>(); |
@@ -3568,6 +3596,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3568 | OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); | 3596 | OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); |
3569 | OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); | 3597 | OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); |
3570 | 3598 | ||
3599 | OpenSim.Framework.Lazy<List<EntityUpdate>> objectUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); | ||
3600 | OpenSim.Framework.Lazy<List<EntityUpdate>> compressedUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); | ||
3601 | OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); | ||
3602 | OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); | ||
3603 | |||
3571 | // Check to see if this is a flush | 3604 | // Check to see if this is a flush |
3572 | if (maxUpdates <= 0) | 3605 | if (maxUpdates <= 0) |
3573 | { | 3606 | { |
@@ -3583,7 +3616,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3583 | float avgTimeDilation = 1.0f; | 3616 | float avgTimeDilation = 1.0f; |
3584 | IEntityUpdate iupdate; | 3617 | IEntityUpdate iupdate; |
3585 | Int32 timeinqueue; // this is just debugging code & can be dropped later | 3618 | Int32 timeinqueue; // this is just debugging code & can be dropped later |
3586 | 3619 | ||
3587 | while (updatesThisCall < maxUpdates) | 3620 | while (updatesThisCall < maxUpdates) |
3588 | { | 3621 | { |
3589 | lock (m_entityUpdates.SyncRoot) | 3622 | lock (m_entityUpdates.SyncRoot) |
@@ -3688,24 +3721,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3688 | if (update.Entity is ScenePresence) | 3721 | if (update.Entity is ScenePresence) |
3689 | { | 3722 | { |
3690 | objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity)); | 3723 | objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity)); |
3724 | objectUpdates.Value.Add(update); | ||
3691 | } | 3725 | } |
3692 | else | 3726 | else |
3693 | { | 3727 | { |
3694 | objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId)); | 3728 | objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId)); |
3729 | objectUpdates.Value.Add(update); | ||
3695 | } | 3730 | } |
3696 | } | 3731 | } |
3697 | else if (!canUseImproved) | 3732 | else if (!canUseImproved) |
3698 | { | 3733 | { |
3699 | compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags)); | 3734 | compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags)); |
3735 | compressedUpdates.Value.Add(update); | ||
3700 | } | 3736 | } |
3701 | else | 3737 | else |
3702 | { | 3738 | { |
3703 | if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) | 3739 | if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) |
3740 | { | ||
3704 | // Self updates go into a special list | 3741 | // Self updates go into a special list |
3705 | terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); | 3742 | terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); |
3743 | terseAgentUpdates.Value.Add(update); | ||
3744 | } | ||
3706 | else | 3745 | else |
3746 | { | ||
3707 | // Everything else goes here | 3747 | // Everything else goes here |
3708 | terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); | 3748 | terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); |
3749 | terseUpdates.Value.Add(update); | ||
3750 | } | ||
3709 | } | 3751 | } |
3710 | 3752 | ||
3711 | #endregion Block Construction | 3753 | #endregion Block Construction |
@@ -3713,28 +3755,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3713 | 3755 | ||
3714 | 3756 | ||
3715 | #region Packet Sending | 3757 | #region Packet Sending |
3716 | |||
3717 | //const float TIME_DILATION = 1.0f; | ||
3718 | |||
3719 | |||
3720 | ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f); | 3758 | ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f); |
3721 | 3759 | ||
3722 | if (terseAgentUpdateBlocks.IsValueCreated) | 3760 | if (terseAgentUpdateBlocks.IsValueCreated) |
3723 | { | 3761 | { |
3724 | List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; | 3762 | List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; |
3725 | 3763 | ||
3726 | ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); | 3764 | ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); |
3727 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; | 3765 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; |
3728 | packet.RegionData.TimeDilation = timeDilation; | 3766 | packet.RegionData.TimeDilation = timeDilation; |
3729 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; | 3767 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; |
3730 | 3768 | ||
3731 | for (int i = 0; i < blocks.Count; i++) | 3769 | for (int i = 0; i < blocks.Count; i++) |
3732 | packet.ObjectData[i] = blocks[i]; | 3770 | packet.ObjectData[i] = blocks[i]; |
3733 | 3771 | // If any of the packets created from this call go unacknowledged, all of the updates will be resent | |
3734 | 3772 | OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate() { ResendPrimUpdates(terseAgentUpdates.Value); }); | |
3735 | OutPacket(packet, ThrottleOutPacketType.Unknown, true); | ||
3736 | } | 3773 | } |
3737 | 3774 | ||
3738 | if (objectUpdateBlocks.IsValueCreated) | 3775 | if (objectUpdateBlocks.IsValueCreated) |
3739 | { | 3776 | { |
3740 | List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value; | 3777 | List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value; |
@@ -3746,8 +3783,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3746 | 3783 | ||
3747 | for (int i = 0; i < blocks.Count; i++) | 3784 | for (int i = 0; i < blocks.Count; i++) |
3748 | packet.ObjectData[i] = blocks[i]; | 3785 | packet.ObjectData[i] = blocks[i]; |
3749 | 3786 | // If any of the packets created from this call go unacknowledged, all of the updates will be resent | |
3750 | OutPacket(packet, ThrottleOutPacketType.Task, true); | 3787 | OutPacket(packet, ThrottleOutPacketType.Task, true, delegate() { ResendPrimUpdates(objectUpdates.Value); }); |
3751 | } | 3788 | } |
3752 | 3789 | ||
3753 | if (compressedUpdateBlocks.IsValueCreated) | 3790 | if (compressedUpdateBlocks.IsValueCreated) |
@@ -3761,10 +3798,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3761 | 3798 | ||
3762 | for (int i = 0; i < blocks.Count; i++) | 3799 | for (int i = 0; i < blocks.Count; i++) |
3763 | packet.ObjectData[i] = blocks[i]; | 3800 | packet.ObjectData[i] = blocks[i]; |
3764 | 3801 | // If any of the packets created from this call go unacknowledged, all of the updates will be resent | |
3765 | OutPacket(packet, ThrottleOutPacketType.Task, true); | 3802 | OutPacket(packet, ThrottleOutPacketType.Task, true, delegate() { ResendPrimUpdates(compressedUpdates.Value); }); |
3766 | } | 3803 | } |
3767 | 3804 | ||
3768 | if (terseUpdateBlocks.IsValueCreated) | 3805 | if (terseUpdateBlocks.IsValueCreated) |
3769 | { | 3806 | { |
3770 | List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; | 3807 | List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; |
@@ -3776,8 +3813,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3776 | 3813 | ||
3777 | for (int i = 0; i < blocks.Count; i++) | 3814 | for (int i = 0; i < blocks.Count; i++) |
3778 | packet.ObjectData[i] = blocks[i]; | 3815 | packet.ObjectData[i] = blocks[i]; |
3779 | 3816 | // If any of the packets created from this call go unacknowledged, all of the updates will be resent | |
3780 | OutPacket(packet, ThrottleOutPacketType.Task, true); | 3817 | OutPacket(packet, ThrottleOutPacketType.Task, true, delegate() { ResendPrimUpdates(terseUpdates.Value); }); |
3781 | } | 3818 | } |
3782 | } | 3819 | } |
3783 | 3820 | ||
@@ -3969,7 +4006,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3969 | { | 4006 | { |
3970 | SendFamilyProps = SendFamilyProps || update.SendFamilyProps; | 4007 | SendFamilyProps = SendFamilyProps || update.SendFamilyProps; |
3971 | SendObjectProps = SendObjectProps || update.SendObjectProps; | 4008 | SendObjectProps = SendObjectProps || update.SendObjectProps; |
3972 | Flags |= update.Flags; | 4009 | // other properties may need to be updated by base class |
4010 | base.Update(update); | ||
3973 | } | 4011 | } |
3974 | } | 4012 | } |
3975 | 4013 | ||
@@ -11363,6 +11401,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
11363 | /// handles splitting manually</param> | 11401 | /// handles splitting manually</param> |
11364 | protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting) | 11402 | protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting) |
11365 | { | 11403 | { |
11404 | OutPacket(packet, throttlePacketType, doAutomaticSplitting, null); | ||
11405 | } | ||
11406 | |||
11407 | /// <summary> | ||
11408 | /// This is the starting point for sending a simulator packet out to the client | ||
11409 | /// </summary> | ||
11410 | /// <param name="packet">Packet to send</param> | ||
11411 | /// <param name="throttlePacketType">Throttling category for the packet</param> | ||
11412 | /// <param name="doAutomaticSplitting">True to automatically split oversized | ||
11413 | /// packets (the default), or false to disable splitting if the calling code | ||
11414 | /// handles splitting manually</param> | ||
11415 | /// <param name="method">The method to be called in the event this packet is reliable | ||
11416 | /// and unacknowledged. The server will provide normal resend capability if you do not | ||
11417 | /// provide your own method.</param> | ||
11418 | protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method) | ||
11419 | { | ||
11366 | if (m_debugPacketLevel > 0) | 11420 | if (m_debugPacketLevel > 0) |
11367 | { | 11421 | { |
11368 | bool logPacket = true; | 11422 | bool logPacket = true; |
@@ -11388,7 +11442,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
11388 | m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type); | 11442 | m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type); |
11389 | } | 11443 | } |
11390 | 11444 | ||
11391 | m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting); | 11445 | m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting, method); |
11392 | } | 11446 | } |
11393 | 11447 | ||
11394 | public bool AddMoney(int debit) | 11448 | public bool AddMoney(int debit) |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index d08b25f..0848979 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | |||
@@ -297,7 +297,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
297 | delegate(IClientAPI client) | 297 | delegate(IClientAPI client) |
298 | { | 298 | { |
299 | if (client is LLClientView) | 299 | if (client is LLClientView) |
300 | SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category); | 300 | SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null); |
301 | } | 301 | } |
302 | ); | 302 | ); |
303 | } | 303 | } |
@@ -309,7 +309,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
309 | delegate(IClientAPI client) | 309 | delegate(IClientAPI client) |
310 | { | 310 | { |
311 | if (client is LLClientView) | 311 | if (client is LLClientView) |
312 | SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category); | 312 | SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null); |
313 | } | 313 | } |
314 | ); | 314 | ); |
315 | } | 315 | } |
@@ -322,7 +322,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
322 | /// <param name="packet"></param> | 322 | /// <param name="packet"></param> |
323 | /// <param name="category"></param> | 323 | /// <param name="category"></param> |
324 | /// <param name="allowSplitting"></param> | 324 | /// <param name="allowSplitting"></param> |
325 | public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting) | 325 | public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting, UnackedPacketMethod method) |
326 | { | 326 | { |
327 | // CoarseLocationUpdate packets cannot be split in an automated way | 327 | // CoarseLocationUpdate packets cannot be split in an automated way |
328 | if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) | 328 | if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) |
@@ -339,13 +339,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
339 | for (int i = 0; i < packetCount; i++) | 339 | for (int i = 0; i < packetCount; i++) |
340 | { | 340 | { |
341 | byte[] data = datas[i]; | 341 | byte[] data = datas[i]; |
342 | SendPacketData(udpClient, data, packet.Type, category); | 342 | SendPacketData(udpClient, data, packet.Type, category, method); |
343 | } | 343 | } |
344 | } | 344 | } |
345 | else | 345 | else |
346 | { | 346 | { |
347 | byte[] data = packet.ToBytes(); | 347 | byte[] data = packet.ToBytes(); |
348 | SendPacketData(udpClient, data, packet.Type, category); | 348 | SendPacketData(udpClient, data, packet.Type, category, method); |
349 | } | 349 | } |
350 | } | 350 | } |
351 | 351 | ||
@@ -356,7 +356,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
356 | /// <param name="data"></param> | 356 | /// <param name="data"></param> |
357 | /// <param name="type"></param> | 357 | /// <param name="type"></param> |
358 | /// <param name="category"></param> | 358 | /// <param name="category"></param> |
359 | public void SendPacketData(LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category) | 359 | public void SendPacketData(LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category, UnackedPacketMethod method) |
360 | { | 360 | { |
361 | int dataLength = data.Length; | 361 | int dataLength = data.Length; |
362 | bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0; | 362 | bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0; |
@@ -411,7 +411,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
411 | 411 | ||
412 | #region Queue or Send | 412 | #region Queue or Send |
413 | 413 | ||
414 | OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category); | 414 | OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); |
415 | // If we were not provided a method for handling unacked, use the UDPServer default method | ||
416 | outgoingPacket.UnackedMethod = ((method == null) ? delegate() { ResendUnacked(outgoingPacket); } : method); | ||
415 | 417 | ||
416 | // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will | 418 | // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will |
417 | // continue to display the deleted object until relog. Therefore, we need to always queue a kill object | 419 | // continue to display the deleted object until relog. Therefore, we need to always queue a kill object |
@@ -445,7 +447,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
445 | packet.Header.Reliable = false; | 447 | packet.Header.Reliable = false; |
446 | packet.Packets = blocks.ToArray(); | 448 | packet.Packets = blocks.ToArray(); |
447 | 449 | ||
448 | SendPacket(udpClient, packet, ThrottleOutPacketType.Unknown, true); | 450 | SendPacket(udpClient, packet, ThrottleOutPacketType.Unknown, true, null); |
449 | } | 451 | } |
450 | } | 452 | } |
451 | 453 | ||
@@ -458,17 +460,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
458 | // We *could* get OldestUnacked, but it would hurt performance and not provide any benefit | 460 | // We *could* get OldestUnacked, but it would hurt performance and not provide any benefit |
459 | pc.PingID.OldestUnacked = 0; | 461 | pc.PingID.OldestUnacked = 0; |
460 | 462 | ||
461 | SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false); | 463 | SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false, null); |
462 | } | 464 | } |
463 | 465 | ||
464 | public void CompletePing(LLUDPClient udpClient, byte pingID) | 466 | public void CompletePing(LLUDPClient udpClient, byte pingID) |
465 | { | 467 | { |
466 | CompletePingCheckPacket completePing = new CompletePingCheckPacket(); | 468 | CompletePingCheckPacket completePing = new CompletePingCheckPacket(); |
467 | completePing.PingID.PingID = pingID; | 469 | completePing.PingID.PingID = pingID; |
468 | SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false); | 470 | SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false, null); |
469 | } | 471 | } |
470 | 472 | ||
471 | public void ResendUnacked(LLUDPClient udpClient) | 473 | public void HandleUnacked(LLUDPClient udpClient) |
472 | { | 474 | { |
473 | if (!udpClient.IsConnected) | 475 | if (!udpClient.IsConnected) |
474 | return; | 476 | return; |
@@ -488,31 +490,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
488 | 490 | ||
489 | if (expiredPackets != null) | 491 | if (expiredPackets != null) |
490 | { | 492 | { |
491 | //m_log.Debug("[LLUDPSERVER]: Resending " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO); | 493 | //m_log.Debug("[LLUDPSERVER]: Handling " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO); |
492 | |||
493 | // Exponential backoff of the retransmission timeout | 494 | // Exponential backoff of the retransmission timeout |
494 | udpClient.BackoffRTO(); | 495 | udpClient.BackoffRTO(); |
496 | for (int i = 0; i < expiredPackets.Count; ++i) | ||
497 | expiredPackets[i].UnackedMethod(); | ||
498 | } | ||
499 | } | ||
495 | 500 | ||
496 | // Resend packets | 501 | public void ResendUnacked(OutgoingPacket outgoingPacket) |
497 | for (int i = 0; i < expiredPackets.Count; i++) | 502 | { |
498 | { | 503 | //m_log.DebugFormat("[LLUDPSERVER]: Resending packet #{0} (attempt {1}), {2}ms have passed", |
499 | OutgoingPacket outgoingPacket = expiredPackets[i]; | 504 | // outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount); |
500 | |||
501 | //m_log.DebugFormat("[LLUDPSERVER]: Resending packet #{0} (attempt {1}), {2}ms have passed", | ||
502 | // outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount); | ||
503 | 505 | ||
504 | // Set the resent flag | 506 | // Set the resent flag |
505 | outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT); | 507 | outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT); |
506 | outgoingPacket.Category = ThrottleOutPacketType.Resend; | 508 | outgoingPacket.Category = ThrottleOutPacketType.Resend; |
507 | 509 | ||
508 | // Bump up the resend count on this packet | 510 | // Bump up the resend count on this packet |
509 | Interlocked.Increment(ref outgoingPacket.ResendCount); | 511 | Interlocked.Increment(ref outgoingPacket.ResendCount); |
510 | 512 | ||
511 | // Requeue or resend the packet | 513 | // Requeue or resend the packet |
512 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false)) | 514 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false)) |
513 | SendPacketFinal(outgoingPacket); | 515 | SendPacketFinal(outgoingPacket); |
514 | } | ||
515 | } | ||
516 | } | 516 | } |
517 | 517 | ||
518 | public void Flush(LLUDPClient udpClient) | 518 | public void Flush(LLUDPClient udpClient) |
@@ -1096,7 +1096,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1096 | if (udpClient.IsConnected) | 1096 | if (udpClient.IsConnected) |
1097 | { | 1097 | { |
1098 | if (m_resendUnacked) | 1098 | if (m_resendUnacked) |
1099 | ResendUnacked(udpClient); | 1099 | HandleUnacked(udpClient); |
1100 | 1100 | ||
1101 | if (m_sendAcks) | 1101 | if (m_sendAcks) |
1102 | SendAcks(udpClient); | 1102 | SendAcks(udpClient); |
@@ -1152,7 +1152,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1152 | nticksUnack++; | 1152 | nticksUnack++; |
1153 | watch2.Start(); | 1153 | watch2.Start(); |
1154 | 1154 | ||
1155 | ResendUnacked(udpClient); | 1155 | HandleUnacked(udpClient); |
1156 | 1156 | ||
1157 | watch2.Stop(); | 1157 | watch2.Stop(); |
1158 | avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack); | 1158 | avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack); |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs index 1a1a1cb..f4f024b 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs | |||
@@ -31,6 +31,7 @@ using OpenMetaverse; | |||
31 | 31 | ||
32 | namespace OpenSim.Region.ClientStack.LindenUDP | 32 | namespace OpenSim.Region.ClientStack.LindenUDP |
33 | { | 33 | { |
34 | public delegate void UnackedPacketMethod(); | ||
34 | /// <summary> | 35 | /// <summary> |
35 | /// Holds a reference to the <seealso cref="LLUDPClient"/> this packet is | 36 | /// Holds a reference to the <seealso cref="LLUDPClient"/> this packet is |
36 | /// destined for, along with the serialized packet data, sequence number | 37 | /// destined for, along with the serialized packet data, sequence number |
@@ -52,6 +53,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
52 | public int TickCount; | 53 | public int TickCount; |
53 | /// <summary>Category this packet belongs to</summary> | 54 | /// <summary>Category this packet belongs to</summary> |
54 | public ThrottleOutPacketType Category; | 55 | public ThrottleOutPacketType Category; |
56 | /// <summary>The delegate to be called if this packet is determined to be unacknowledged</summary> | ||
57 | public UnackedPacketMethod UnackedMethod; | ||
55 | 58 | ||
56 | /// <summary> | 59 | /// <summary> |
57 | /// Default constructor | 60 | /// Default constructor |
@@ -60,11 +63,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
60 | /// <param name="buffer">Serialized packet data. If the flags or sequence number | 63 | /// <param name="buffer">Serialized packet data. If the flags or sequence number |
61 | /// need to be updated, they will be injected directly into this binary buffer</param> | 64 | /// need to be updated, they will be injected directly into this binary buffer</param> |
62 | /// <param name="category">Throttling category for this packet</param> | 65 | /// <param name="category">Throttling category for this packet</param> |
63 | public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer, ThrottleOutPacketType category) | 66 | public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method) |
64 | { | 67 | { |
65 | Client = client; | 68 | Client = client; |
66 | Buffer = buffer; | 69 | Buffer = buffer; |
67 | Category = category; | 70 | Category = category; |
71 | UnackedMethod = method; | ||
68 | } | 72 | } |
69 | } | 73 | } |
70 | } | 74 | } |