diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs')
-rwxr-xr-x[-rw-r--r--] | OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 350 |
1 files changed, 163 insertions, 187 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 35d29a5..2300800 100644..100755 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -256,6 +256,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
256 | 256 | ||
257 | /// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary> | 257 | /// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary> |
258 | public const int MTU = 1400; | 258 | public const int MTU = 1400; |
259 | public const int MAXPAYLOAD = 1250; | ||
259 | 260 | ||
260 | /// <summary>Number of forced client logouts due to no receipt of packets before timeout.</summary> | 261 | /// <summary>Number of forced client logouts due to no receipt of packets before timeout.</summary> |
261 | public int ClientLogoutsDueToNoReceives { get; protected set; } | 262 | public int ClientLogoutsDueToNoReceives { get; protected set; } |
@@ -274,10 +275,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
274 | /// <summary>The measured resolution of Environment.TickCount</summary> | 275 | /// <summary>The measured resolution of Environment.TickCount</summary> |
275 | public readonly float TickCountResolution; | 276 | public readonly float TickCountResolution; |
276 | 277 | ||
277 | /// <summary>Number of prim updates to put on the queue each time the | ||
278 | /// OnQueueEmpty event is triggered for updates</summary> | ||
279 | public readonly int PrimUpdatesPerCallback; | ||
280 | |||
281 | /// <summary>Number of texture packets to put on the queue each time the | 278 | /// <summary>Number of texture packets to put on the queue each time the |
282 | /// OnQueueEmpty event is triggered for textures</summary> | 279 | /// OnQueueEmpty event is triggered for textures</summary> |
283 | public readonly int TextureSendLimit; | 280 | public readonly int TextureSendLimit; |
@@ -344,18 +341,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
344 | 341 | ||
345 | protected ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); | 342 | protected ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); |
346 | 343 | ||
347 | protected Pool<IncomingPacket> m_incomingPacketPool; | ||
348 | |||
349 | /// <summary> | ||
350 | /// Stat for number of packets in the main pool awaiting use. | ||
351 | /// </summary> | ||
352 | protected Stat m_poolCountStat; | ||
353 | |||
354 | /// <summary> | ||
355 | /// Stat for number of packets in the inbound packet pool awaiting use. | ||
356 | /// </summary> | ||
357 | protected Stat m_incomingPacketPoolStat; | ||
358 | |||
359 | protected int m_defaultRTO = 0; | 344 | protected int m_defaultRTO = 0; |
360 | protected int m_maxRTO = 0; | 345 | protected int m_maxRTO = 0; |
361 | protected int m_ackTimeout = 0; | 346 | protected int m_ackTimeout = 0; |
@@ -452,7 +437,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
452 | m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0); | 437 | m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0); |
453 | sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0); | 438 | sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0); |
454 | 439 | ||
455 | PrimUpdatesPerCallback = config.GetInt("PrimUpdatesPerCallback", 100); | ||
456 | TextureSendLimit = config.GetInt("TextureSendLimit", 20); | 440 | TextureSendLimit = config.GetInt("TextureSendLimit", 20); |
457 | 441 | ||
458 | m_defaultRTO = config.GetInt("DefaultRTO", 0); | 442 | m_defaultRTO = config.GetInt("DefaultRTO", 0); |
@@ -463,7 +447,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
463 | } | 447 | } |
464 | else | 448 | else |
465 | { | 449 | { |
466 | PrimUpdatesPerCallback = 100; | ||
467 | TextureSendLimit = 20; | 450 | TextureSendLimit = 20; |
468 | m_ackTimeout = 1000 * 60; // 1 minute | 451 | m_ackTimeout = 1000 * 60; // 1 minute |
469 | m_pausedAckTimeout = 1000 * 300; // 5 minutes | 452 | m_pausedAckTimeout = 1000 * 300; // 5 minutes |
@@ -498,7 +481,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
498 | 481 | ||
499 | // if (usePools) | 482 | // if (usePools) |
500 | // EnablePools(); | 483 | // EnablePools(); |
501 | base.DisablePools(); | ||
502 | } | 484 | } |
503 | 485 | ||
504 | public void Start() | 486 | public void Start() |
@@ -554,83 +536,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
554 | OqrEngine.Stop(); | 536 | OqrEngine.Stop(); |
555 | } | 537 | } |
556 | 538 | ||
557 | public override bool EnablePools() | ||
558 | { | ||
559 | if (!UsePools) | ||
560 | { | ||
561 | base.EnablePools(); | ||
562 | |||
563 | m_incomingPacketPool = new Pool<IncomingPacket>(() => new IncomingPacket(), 500); | ||
564 | |||
565 | return true; | ||
566 | } | ||
567 | |||
568 | return false; | ||
569 | } | ||
570 | |||
571 | public override bool DisablePools() | ||
572 | { | ||
573 | if (UsePools) | ||
574 | { | ||
575 | base.DisablePools(); | ||
576 | |||
577 | StatsManager.DeregisterStat(m_incomingPacketPoolStat); | ||
578 | |||
579 | // We won't null out the pool to avoid a race condition with code that may be in the middle of using it. | ||
580 | |||
581 | return true; | ||
582 | } | ||
583 | |||
584 | return false; | ||
585 | } | ||
586 | |||
587 | /// <summary> | ||
588 | /// This is a seperate method so that it can be called once we have an m_scene to distinguish different scene | ||
589 | /// stats. | ||
590 | /// </summary> | ||
591 | protected internal void EnablePoolStats() | ||
592 | { | ||
593 | m_poolCountStat | ||
594 | = new Stat( | ||
595 | "UDPPacketBufferPoolCount", | ||
596 | "Objects within the UDPPacketBuffer pool", | ||
597 | "The number of objects currently stored within the UDPPacketBuffer pool", | ||
598 | "", | ||
599 | "clientstack", | ||
600 | Scene.Name, | ||
601 | StatType.Pull, | ||
602 | stat => stat.Value = Pool.Count, | ||
603 | StatVerbosity.Debug); | ||
604 | |||
605 | StatsManager.RegisterStat(m_poolCountStat); | ||
606 | |||
607 | m_incomingPacketPoolStat | ||
608 | = new Stat( | ||
609 | "IncomingPacketPoolCount", | ||
610 | "Objects within incoming packet pool", | ||
611 | "The number of objects currently stored within the incoming packet pool", | ||
612 | "", | ||
613 | "clientstack", | ||
614 | Scene.Name, | ||
615 | StatType.Pull, | ||
616 | stat => stat.Value = m_incomingPacketPool.Count, | ||
617 | StatVerbosity.Debug); | ||
618 | |||
619 | StatsManager.RegisterStat(m_incomingPacketPoolStat); | ||
620 | } | ||
621 | |||
622 | /// <summary> | ||
623 | /// Disables pool stats. | ||
624 | /// </summary> | ||
625 | protected internal void DisablePoolStats() | ||
626 | { | ||
627 | StatsManager.DeregisterStat(m_poolCountStat); | ||
628 | m_poolCountStat = null; | ||
629 | |||
630 | StatsManager.DeregisterStat(m_incomingPacketPoolStat); | ||
631 | m_incomingPacketPoolStat = null; | ||
632 | } | ||
633 | |||
634 | /// <summary> | 539 | /// <summary> |
635 | /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging. | 540 | /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging. |
636 | /// </summary> | 541 | /// </summary> |
@@ -658,8 +563,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
658 | string.Format("Incoming Packet Async Handling Engine ({0})", Scene.Name), | 563 | string.Format("Incoming Packet Async Handling Engine ({0})", Scene.Name), |
659 | "INCOMING PACKET ASYNC HANDLING ENGINE"); | 564 | "INCOMING PACKET ASYNC HANDLING ENGINE"); |
660 | */ | 565 | */ |
661 | OqrEngine | 566 | OqrEngine = new JobEngine( |
662 | = new JobEngine( | ||
663 | string.Format("Outgoing Queue Refill Engine ({0})", Scene.Name), | 567 | string.Format("Outgoing Queue Refill Engine ({0})", Scene.Name), |
664 | "OUTGOING QUEUE REFILL ENGINE"); | 568 | "OUTGOING QUEUE REFILL ENGINE"); |
665 | 569 | ||
@@ -769,15 +673,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
769 | stat => stat.Value = OqrEngine.JobsWaiting, | 673 | stat => stat.Value = OqrEngine.JobsWaiting, |
770 | StatVerbosity.Debug)); | 674 | StatVerbosity.Debug)); |
771 | 675 | ||
772 | // We delay enabling pool stats to AddScene() instead of Initialize() so that we can distinguish pool stats by | 676 | StatsManager.RegisterStat( |
773 | // scene name | 677 | new Stat( |
774 | if (UsePools) | 678 | "UDPBuffersPoolCount", |
775 | EnablePoolStats(); | 679 | "Buffers in the UDP buffers pool", |
776 | 680 | "The number of buffers currently stored within the UDP buffers pool", | |
681 | "", | ||
682 | "clientstack", | ||
683 | Scene.Name, | ||
684 | StatType.Pull, | ||
685 | stat => stat.Value = m_udpBuffersPoolPtr + 1, | ||
686 | StatVerbosity.Debug)); | ||
777 | 687 | ||
778 | LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this); | 688 | LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this); |
779 | commands.Register(); | 689 | commands.Register(); |
780 | |||
781 | } | 690 | } |
782 | 691 | ||
783 | public bool HandlesRegion(Location x) | 692 | public bool HandlesRegion(Location x) |
@@ -939,9 +848,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
939 | // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting | 848 | // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting |
940 | // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here | 849 | // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here |
941 | // to accomodate for both common scenarios and provide ample room for ACK appending in both | 850 | // to accomodate for both common scenarios and provide ample room for ACK appending in both |
942 | int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200; | 851 | //int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200; |
943 | 852 | ||
944 | UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize); | 853 | //UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize); |
854 | UDPPacketBuffer buffer = GetNewUDPBuffer(udpClient.RemoteEndPoint); | ||
945 | 855 | ||
946 | // Zerocode if needed | 856 | // Zerocode if needed |
947 | if (doZerocode) | 857 | if (doZerocode) |
@@ -971,7 +881,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
971 | // If the packet data wasn't already copied during zerocoding, copy it now | 881 | // If the packet data wasn't already copied during zerocoding, copy it now |
972 | if (doCopy) | 882 | if (doCopy) |
973 | { | 883 | { |
974 | if (dataLength <= buffer.Data.Length) | 884 | //if (dataLength <= buffer.Data.Length) |
885 | if (dataLength <= LLUDPServer.MTU) | ||
975 | { | 886 | { |
976 | Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); | 887 | Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); |
977 | } | 888 | } |
@@ -979,7 +890,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
979 | { | 890 | { |
980 | m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" + | 891 | m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" + |
981 | type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length); | 892 | type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length); |
982 | buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, dataLength); | 893 | // buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, dataLength); |
894 | buffer = GetNewUDPBuffer(udpClient.RemoteEndPoint); | ||
983 | Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); | 895 | Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); |
984 | } | 896 | } |
985 | } | 897 | } |
@@ -1017,6 +929,89 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1017 | #endregion Queue or Send | 929 | #endregion Queue or Send |
1018 | } | 930 | } |
1019 | 931 | ||
932 | public unsafe UDPPacketBuffer ZeroEncode(UDPPacketBuffer input) | ||
933 | { | ||
934 | UDPPacketBuffer zb = GetNewUDPBuffer(null); | ||
935 | int srclen = input.DataLength; | ||
936 | byte[] src = input.Data; | ||
937 | byte[] dest = zb.Data; | ||
938 | |||
939 | int zerolen = 6; | ||
940 | byte zerocount = 0; | ||
941 | |||
942 | for (int i = zerolen; i < srclen; i++) | ||
943 | { | ||
944 | if (src[i] == 0x00) | ||
945 | { | ||
946 | zerocount++; | ||
947 | if (zerocount == 0) | ||
948 | { | ||
949 | dest[zerolen++] = 0x00; | ||
950 | dest[zerolen++] = 0xff; | ||
951 | zerocount++; | ||
952 | } | ||
953 | } | ||
954 | else | ||
955 | { | ||
956 | if (zerocount != 0) | ||
957 | { | ||
958 | dest[zerolen++] = 0x00; | ||
959 | dest[zerolen++] = zerocount; | ||
960 | zerocount = 0; | ||
961 | } | ||
962 | |||
963 | dest[zerolen++] = src[i]; | ||
964 | } | ||
965 | } | ||
966 | |||
967 | if (zerocount != 0) | ||
968 | { | ||
969 | dest[zerolen++] = 0x00; | ||
970 | dest[zerolen++] = zerocount; | ||
971 | } | ||
972 | |||
973 | if(zerolen >= srclen) | ||
974 | { | ||
975 | FreeUDPBuffer(zb); | ||
976 | |||
977 | src[0] &= unchecked((byte)~Helpers.MSG_ZEROCODED); | ||
978 | return input; | ||
979 | } | ||
980 | |||
981 | Buffer.BlockCopy(src, 0, dest, 0, 6); | ||
982 | |||
983 | zb.RemoteEndPoint = input.RemoteEndPoint; | ||
984 | zb.DataLength = zerolen; | ||
985 | |||
986 | FreeUDPBuffer(input); | ||
987 | |||
988 | return zb; | ||
989 | } | ||
990 | |||
991 | public void SendUDPPacket( | ||
992 | LLUDPClient udpClient, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method, bool forcequeue, bool zerocode) | ||
993 | { | ||
994 | bool highPriority = false; | ||
995 | |||
996 | if(zerocode) | ||
997 | buffer = ZeroEncode(buffer); | ||
998 | |||
999 | if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0) | ||
1000 | { | ||
1001 | category = (ThrottleOutPacketType)((int)category & 127); | ||
1002 | highPriority = true; | ||
1003 | } | ||
1004 | |||
1005 | OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); | ||
1006 | |||
1007 | // If we were not provided a method for handling unacked, use the UDPServer default method | ||
1008 | if ((outgoingPacket.Buffer.Data[0] & Helpers.MSG_RELIABLE) != 0) | ||
1009 | outgoingPacket.UnackedMethod = ((method == null) ? delegate (OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method); | ||
1010 | |||
1011 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, forcequeue, highPriority)) | ||
1012 | SendPacketFinal(outgoingPacket); | ||
1013 | } | ||
1014 | |||
1020 | public void SendAcks(LLUDPClient udpClient) | 1015 | public void SendAcks(LLUDPClient udpClient) |
1021 | { | 1016 | { |
1022 | uint ack; | 1017 | uint ack; |
@@ -1066,7 +1061,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1066 | { | 1061 | { |
1067 | LLUDPClient udpClient = client.UDPClient; | 1062 | LLUDPClient udpClient = client.UDPClient; |
1068 | 1063 | ||
1069 | if (!udpClient.IsConnected) | 1064 | if (!client.IsActive || !udpClient.IsConnected) |
1070 | return; | 1065 | return; |
1071 | 1066 | ||
1072 | // Disconnect an agent if no packets are received for some time | 1067 | // Disconnect an agent if no packets are received for some time |
@@ -1136,14 +1131,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1136 | internal void SendPacketFinal(OutgoingPacket outgoingPacket) | 1131 | internal void SendPacketFinal(OutgoingPacket outgoingPacket) |
1137 | { | 1132 | { |
1138 | UDPPacketBuffer buffer = outgoingPacket.Buffer; | 1133 | UDPPacketBuffer buffer = outgoingPacket.Buffer; |
1134 | if(buffer == null) // canceled packet | ||
1135 | return; | ||
1136 | LLUDPClient udpClient = outgoingPacket.Client; | ||
1137 | if (!udpClient.IsConnected) | ||
1138 | return; | ||
1139 | |||
1139 | byte flags = buffer.Data[0]; | 1140 | byte flags = buffer.Data[0]; |
1140 | bool isResend = (flags & Helpers.MSG_RESENT) != 0; | 1141 | bool isResend = (flags & Helpers.MSG_RESENT) != 0; |
1141 | bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0; | 1142 | bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0; |
1142 | bool isZerocoded = (flags & Helpers.MSG_ZEROCODED) != 0; | 1143 | bool isZerocoded = (flags & Helpers.MSG_ZEROCODED) != 0; |
1143 | LLUDPClient udpClient = outgoingPacket.Client; | ||
1144 | |||
1145 | if (!udpClient.IsConnected) | ||
1146 | return; | ||
1147 | 1144 | ||
1148 | int dataLength = buffer.DataLength; | 1145 | int dataLength = buffer.DataLength; |
1149 | 1146 | ||
@@ -1154,7 +1151,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1154 | // no more ACKs to append | 1151 | // no more ACKs to append |
1155 | int ackCount = 0; | 1152 | int ackCount = 0; |
1156 | uint ack; | 1153 | uint ack; |
1157 | while (dataLength + 5 < buffer.Data.Length && ackCount < 256 && udpClient.PendingAcks.Dequeue(out ack)) | 1154 | while (dataLength + 5 < MTU && ackCount < 256 && udpClient.PendingAcks.Dequeue(out ack)) |
1158 | { | 1155 | { |
1159 | Utils.UIntToBytesBig(ack, buffer.Data, dataLength); | 1156 | Utils.UIntToBytesBig(ack, buffer.Data, dataLength); |
1160 | dataLength += 4; | 1157 | dataLength += 4; |
@@ -1168,22 +1165,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1168 | // Set the appended ACKs flag on this packet | 1165 | // Set the appended ACKs flag on this packet |
1169 | buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS); | 1166 | buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS); |
1170 | } | 1167 | } |
1168 | buffer.DataLength = dataLength; | ||
1171 | } | 1169 | } |
1172 | 1170 | ||
1173 | buffer.DataLength = dataLength; | ||
1174 | |||
1175 | if (!isResend) | 1171 | if (!isResend) |
1176 | { | 1172 | { |
1177 | // Not a resend, assign a new sequence number | 1173 | // Not a resend, assign a new sequence number |
1178 | uint sequenceNumber = (uint)Interlocked.Increment(ref udpClient.CurrentSequence); | 1174 | uint sequenceNumber = (uint)Interlocked.Increment(ref udpClient.CurrentSequence); |
1179 | Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); | 1175 | Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); |
1180 | outgoingPacket.SequenceNumber = sequenceNumber; | 1176 | outgoingPacket.SequenceNumber = sequenceNumber; |
1181 | |||
1182 | if (isReliable) | ||
1183 | { | ||
1184 | // Add this packet to the list of ACK responses we are waiting on from the server | ||
1185 | udpClient.NeedAcks.Add(outgoingPacket); | ||
1186 | } | ||
1187 | } | 1177 | } |
1188 | else | 1178 | else |
1189 | { | 1179 | { |
@@ -1196,9 +1186,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1196 | PacketsSentCount++; | 1186 | PacketsSentCount++; |
1197 | 1187 | ||
1198 | SyncSend(buffer); | 1188 | SyncSend(buffer); |
1189 | |||
1199 | // Keep track of when this packet was sent out (right now) | 1190 | // Keep track of when this packet was sent out (right now) |
1200 | outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue; | 1191 | outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue; |
1201 | 1192 | ||
1193 | if (outgoingPacket.UnackedMethod == null) | ||
1194 | FreeUDPBuffer(buffer); | ||
1195 | else if(!isResend) | ||
1196 | { | ||
1197 | // Add this packet to the list of ACK responses we are waiting on from the server | ||
1198 | udpClient.NeedAcks.Add(outgoingPacket); | ||
1199 | } | ||
1200 | |||
1202 | if (udpClient.DebugDataOutLevel > 0) | 1201 | if (udpClient.DebugDataOutLevel > 0) |
1203 | m_log.DebugFormat( | 1202 | m_log.DebugFormat( |
1204 | "[LLUDPSERVER]: Sending packet #{0} (rel: {1}, res: {2}) to {3} from {4}", | 1203 | "[LLUDPSERVER]: Sending packet #{0} (rel: {1}, res: {2}) to {3} from {4}", |
@@ -1240,7 +1239,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1240 | // buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); | 1239 | // buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); |
1241 | 1240 | ||
1242 | RecordMalformedInboundPacket(endPoint); | 1241 | RecordMalformedInboundPacket(endPoint); |
1243 | 1242 | FreeUDPBuffer(buffer); | |
1244 | return; // Drop undersized packet | 1243 | return; // Drop undersized packet |
1245 | } | 1244 | } |
1246 | 1245 | ||
@@ -1260,21 +1259,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1260 | // buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); | 1259 | // buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); |
1261 | 1260 | ||
1262 | RecordMalformedInboundPacket(endPoint); | 1261 | RecordMalformedInboundPacket(endPoint); |
1263 | 1262 | FreeUDPBuffer(buffer); | |
1264 | return; // Malformed header | 1263 | return; // Malformed header |
1265 | } | 1264 | } |
1266 | 1265 | ||
1267 | try | 1266 | try |
1268 | { | 1267 | { |
1269 | // packet = Packet.BuildPacket(buffer.Data, ref packetEnd, | 1268 | // get a buffer for zero decode using the udp buffers pool |
1270 | // // Only allocate a buffer for zerodecoding if the packet is zerocoded | 1269 | UDPPacketBuffer zerodecodebufferholder = null; |
1271 | // ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); | 1270 | byte[] zerodecodebuffer = null; |
1271 | // only if needed | ||
1272 | if (((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0)) | ||
1273 | { | ||
1274 | zerodecodebufferholder = GetNewUDPBuffer(null); | ||
1275 | zerodecodebuffer = zerodecodebufferholder.Data; | ||
1276 | } | ||
1277 | |||
1278 | packet = Packet.BuildPacket(buffer.Data, ref packetEnd, zerodecodebuffer); | ||
1272 | // If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we | 1279 | // If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we |
1273 | // assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all | 1280 | // assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all |
1274 | // bytes are copied out). | 1281 | // bytes are copied out). |
1275 | packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd, | 1282 | // packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd, zerodecodebuffer); |
1276 | // Only allocate a buffer for zerodecoding if the packet is zerocoded | 1283 | if(zerodecodebufferholder != null) |
1277 | ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); | 1284 | FreeUDPBuffer(zerodecodebufferholder); |
1278 | } | 1285 | } |
1279 | catch (Exception e) | 1286 | catch (Exception e) |
1280 | { | 1287 | { |
@@ -1292,7 +1299,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1292 | } | 1299 | } |
1293 | 1300 | ||
1294 | RecordMalformedInboundPacket(endPoint); | 1301 | RecordMalformedInboundPacket(endPoint); |
1295 | 1302 | FreeUDPBuffer(buffer); | |
1296 | return; | 1303 | return; |
1297 | } | 1304 | } |
1298 | 1305 | ||
@@ -1311,17 +1318,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1311 | lock (m_pendingCache) | 1318 | lock (m_pendingCache) |
1312 | { | 1319 | { |
1313 | if (m_pendingCache.Contains(endPoint)) | 1320 | if (m_pendingCache.Contains(endPoint)) |
1321 | { | ||
1322 | FreeUDPBuffer(buffer); | ||
1314 | return; | 1323 | return; |
1324 | } | ||
1315 | 1325 | ||
1316 | m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60); | 1326 | m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60); |
1317 | } | 1327 | } |
1318 | 1328 | ||
1319 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the | 1329 | Util.FireAndForget(HandleUseCircuitCode, new object[] { endPoint, packet }); |
1320 | // buffer. | 1330 | FreeUDPBuffer(buffer); |
1321 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | ||
1322 | |||
1323 | Util.FireAndForget(HandleUseCircuitCode, array); | ||
1324 | |||
1325 | return; | 1331 | return; |
1326 | } | 1332 | } |
1327 | } | 1333 | } |
@@ -1336,24 +1342,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1336 | queue.Enqueue(buffer); | 1342 | queue.Enqueue(buffer); |
1337 | return; | 1343 | return; |
1338 | } | 1344 | } |
1339 | |||
1340 | /* | ||
1341 | else if (packet.Type == PacketType.CompleteAgentMovement) | ||
1342 | { | ||
1343 | // Send ack straight away to let the viewer know that we got it. | ||
1344 | SendAckImmediate(endPoint, packet.Header.Sequence); | ||
1345 | |||
1346 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the | ||
1347 | // buffer. | ||
1348 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | ||
1349 | |||
1350 | Util.FireAndForget(HandleCompleteMovementIntoRegion, array); | ||
1351 | |||
1352 | return; | ||
1353 | } | ||
1354 | */ | ||
1355 | } | 1345 | } |
1356 | 1346 | ||
1347 | FreeUDPBuffer(buffer); | ||
1348 | |||
1357 | // Determine which agent this packet came from | 1349 | // Determine which agent this packet came from |
1358 | if (client == null || !(client is LLClientView)) | 1350 | if (client == null || !(client is LLClientView)) |
1359 | { | 1351 | { |
@@ -1471,10 +1463,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1471 | LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); | 1463 | LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); |
1472 | #endregion BinaryStats | 1464 | #endregion BinaryStats |
1473 | 1465 | ||
1474 | |||
1475 | //AgentUpdate removed from here | ||
1476 | |||
1477 | |||
1478 | #region Ping Check Handling | 1466 | #region Ping Check Handling |
1479 | 1467 | ||
1480 | if (packet.Type == PacketType.StartPingCheck) | 1468 | if (packet.Type == PacketType.StartPingCheck) |
@@ -1506,17 +1494,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1506 | 1494 | ||
1507 | IncomingPacket incomingPacket; | 1495 | IncomingPacket incomingPacket; |
1508 | 1496 | ||
1509 | // Inbox insertion | 1497 | incomingPacket = new IncomingPacket((LLClientView)client, packet); |
1510 | if (UsePools) | ||
1511 | { | ||
1512 | incomingPacket = m_incomingPacketPool.GetObject(); | ||
1513 | incomingPacket.Client = (LLClientView)client; | ||
1514 | incomingPacket.Packet = packet; | ||
1515 | } | ||
1516 | else | ||
1517 | { | ||
1518 | incomingPacket = new IncomingPacket((LLClientView)client, packet); | ||
1519 | } | ||
1520 | 1498 | ||
1521 | // if (incomingPacket.Packet.Type == PacketType.AgentUpdate || | 1499 | // if (incomingPacket.Packet.Type == PacketType.AgentUpdate || |
1522 | // incomingPacket.Packet.Type == PacketType.ChatFromViewer) | 1500 | // incomingPacket.Packet.Type == PacketType.ChatFromViewer) |
@@ -1525,7 +1503,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1525 | // else | 1503 | // else |
1526 | // packetInbox.Enqueue(incomingPacket); | 1504 | // packetInbox.Enqueue(incomingPacket); |
1527 | packetInbox.Add(incomingPacket); | 1505 | packetInbox.Add(incomingPacket); |
1528 | |||
1529 | } | 1506 | } |
1530 | 1507 | ||
1531 | #region BinaryStats | 1508 | #region BinaryStats |
@@ -1685,7 +1662,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1685 | { | 1662 | { |
1686 | m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present"); | 1663 | m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present"); |
1687 | return; | 1664 | return; |
1688 | |||
1689 | } | 1665 | } |
1690 | m_pendingCache.Remove(endPoint); | 1666 | m_pendingCache.Remove(endPoint); |
1691 | } | 1667 | } |
@@ -1881,13 +1857,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1881 | byte[] packetData = ack.ToBytes(); | 1857 | byte[] packetData = ack.ToBytes(); |
1882 | int length = packetData.Length; | 1858 | int length = packetData.Length; |
1883 | 1859 | ||
1884 | UDPPacketBuffer buffer = new UDPPacketBuffer(remoteEndpoint, length); | 1860 | UDPPacketBuffer buffer = GetNewUDPBuffer(remoteEndpoint); |
1885 | buffer.DataLength = length; | 1861 | buffer.DataLength = length; |
1886 | 1862 | ||
1887 | Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length); | 1863 | Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length); |
1888 | 1864 | ||
1889 | // AsyncBeginSend(buffer); | 1865 | // AsyncBeginSend(buffer); |
1890 | SyncSend(buffer); | 1866 | SyncSend(buffer); |
1867 | FreeUDPBuffer(buffer); | ||
1891 | } | 1868 | } |
1892 | 1869 | ||
1893 | protected bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo) | 1870 | protected bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo) |
@@ -1982,21 +1959,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1982 | Scene.ThreadAlive(1); | 1959 | Scene.ThreadAlive(1); |
1983 | try | 1960 | try |
1984 | { | 1961 | { |
1985 | packetInbox.TryTake(out incomingPacket, 250); | 1962 | packetInbox.TryTake(out incomingPacket, 4500); |
1986 | 1963 | ||
1987 | if (incomingPacket != null && IsRunningInbound) | 1964 | if (incomingPacket != null && IsRunningInbound) |
1988 | { | 1965 | { |
1989 | ProcessInPacket(incomingPacket); | 1966 | ProcessInPacket(incomingPacket); |
1990 | |||
1991 | if (UsePools) | ||
1992 | { | ||
1993 | incomingPacket.Client = null; | ||
1994 | m_incomingPacketPool.ReturnObject(incomingPacket); | ||
1995 | } | ||
1996 | incomingPacket = null; | 1967 | incomingPacket = null; |
1997 | } | 1968 | } |
1998 | } | 1969 | } |
1999 | catch(Exception ex) | 1970 | catch (ThreadAbortException) |
1971 | { | ||
1972 | Thread.ResetAbort(); | ||
1973 | } | ||
1974 | catch (Exception ex) | ||
2000 | { | 1975 | { |
2001 | m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex); | 1976 | m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex); |
2002 | } | 1977 | } |
@@ -2025,7 +2000,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2025 | { | 2000 | { |
2026 | Scene.ThreadAlive(2); | 2001 | Scene.ThreadAlive(2); |
2027 | 2002 | ||
2028 | |||
2029 | try | 2003 | try |
2030 | { | 2004 | { |
2031 | m_packetSent = false; | 2005 | m_packetSent = false; |
@@ -2080,7 +2054,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2080 | } | 2054 | } |
2081 | else if (!m_packetSent) | 2055 | else if (!m_packetSent) |
2082 | // Thread.Sleep((int)TickCountResolution); outch this is bad on linux | 2056 | // Thread.Sleep((int)TickCountResolution); outch this is bad on linux |
2083 | Thread.Sleep(15); // match the 16ms of windows7, dont ask 16 or win may decide to do 32ms. | 2057 | Thread.Sleep(15); // match the 16ms of windows, dont ask 16 or win may decide to do 32ms. |
2084 | 2058 | ||
2085 | Watchdog.UpdateThread(); | 2059 | Watchdog.UpdateThread(); |
2086 | } | 2060 | } |
@@ -2104,14 +2078,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2104 | 2078 | ||
2105 | if (udpClient.IsConnected) | 2079 | if (udpClient.IsConnected) |
2106 | { | 2080 | { |
2107 | if (m_resendUnacked) | 2081 | if (client.IsActive && m_resendUnacked) |
2108 | HandleUnacked(llClient); | 2082 | HandleUnacked(llClient); |
2109 | 2083 | ||
2110 | if (m_sendAcks) | 2084 | if (client.IsActive) |
2111 | SendAcks(udpClient); | 2085 | { |
2086 | if (m_sendAcks) | ||
2087 | SendAcks(udpClient); | ||
2112 | 2088 | ||
2113 | if (m_sendPing) | 2089 | if (m_sendPing) |
2114 | SendPing(udpClient); | 2090 | SendPing(udpClient); |
2091 | } | ||
2115 | 2092 | ||
2116 | // Dequeue any outgoing packets that are within the throttle limits | 2093 | // Dequeue any outgoing packets that are within the throttle limits |
2117 | if (udpClient.DequeueOutgoing()) | 2094 | if (udpClient.DequeueOutgoing()) |
@@ -2124,7 +2101,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2124 | m_log.Error( | 2101 | m_log.Error( |
2125 | string.Format("[LLUDPSERVER]: OutgoingPacketHandler iteration for {0} threw ", client.Name), ex); | 2102 | string.Format("[LLUDPSERVER]: OutgoingPacketHandler iteration for {0} threw ", client.Name), ex); |
2126 | } | 2103 | } |
2127 | client = null; | ||
2128 | } | 2104 | } |
2129 | 2105 | ||
2130 | #region Emergency Monitoring | 2106 | #region Emergency Monitoring |