diff options
author | Melanie | 2012-10-17 00:03:02 +0100 |
---|---|---|
committer | Melanie | 2012-10-17 00:03:02 +0100 |
commit | ad60a29c9303e68717ccc057988a36da0990b0ae (patch) | |
tree | a4e965250d291476b1449bd0e949e5e204cf0446 /OpenSim/Region | |
parent | Merge branch 'master' into careminster (diff) | |
parent | Add optional pool for the UDPPacketBuffer objects that handle all incoming UD... (diff) | |
download | opensim-SC-ad60a29c9303e68717ccc057988a36da0990b0ae.zip opensim-SC-ad60a29c9303e68717ccc057988a36da0990b0ae.tar.gz opensim-SC-ad60a29c9303e68717ccc057988a36da0990b0ae.tar.bz2 opensim-SC-ad60a29c9303e68717ccc057988a36da0990b0ae.tar.xz |
Merge branch 'master' into careminster
Conflicts:
OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
Diffstat (limited to 'OpenSim/Region')
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 54 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs | 31 |
2 files changed, 55 insertions, 30 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 1d304db..7820caf 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -192,7 +192,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
192 | /// </summary> | 192 | /// </summary> |
193 | private IClientAPI m_currentIncomingClient; | 193 | private IClientAPI m_currentIncomingClient; |
194 | 194 | ||
195 | public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) | 195 | public LLUDPServer( |
196 | IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, | ||
197 | IConfigSource configSource, AgentCircuitManager circuitManager) | ||
196 | : base(listenIP, (int)port) | 198 | : base(listenIP, (int)port) |
197 | { | 199 | { |
198 | #region Environment.TickCount Measurement | 200 | #region Environment.TickCount Measurement |
@@ -246,6 +248,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
246 | { | 248 | { |
247 | PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); | 249 | PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); |
248 | PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); | 250 | PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); |
251 | UsePools = packetConfig.GetBoolean("RecycleBaseUDPPackets", false); | ||
249 | } | 252 | } |
250 | 253 | ||
251 | #region BinaryStats | 254 | #region BinaryStats |
@@ -288,8 +291,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
288 | private void StartInbound() | 291 | private void StartInbound() |
289 | { | 292 | { |
290 | m_log.InfoFormat( | 293 | m_log.InfoFormat( |
291 | "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode", | 294 | "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode with UsePools = {1}", |
292 | m_asyncPacketHandling ? "asynchronous" : "synchronous"); | 295 | m_asyncPacketHandling ? "asynchronous" : "synchronous", UsePools); |
293 | 296 | ||
294 | base.StartInbound(m_recvBufferSize, m_asyncPacketHandling); | 297 | base.StartInbound(m_recvBufferSize, m_asyncPacketHandling); |
295 | 298 | ||
@@ -304,7 +307,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
304 | Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); | 307 | Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); |
305 | } | 308 | } |
306 | 309 | ||
307 | private void StartOutbound() | 310 | private new void StartOutbound() |
308 | { | 311 | { |
309 | m_log.Info("[LLUDPSERVER]: Starting outbound packet processing for the LLUDP server"); | 312 | m_log.Info("[LLUDPSERVER]: Starting outbound packet processing for the LLUDP server"); |
310 | 313 | ||
@@ -321,7 +324,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
321 | Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); | 324 | Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); |
322 | } | 325 | } |
323 | 326 | ||
324 | public new void Stop() | 327 | public void Stop() |
325 | { | 328 | { |
326 | m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); | 329 | m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); |
327 | base.StopOutbound(); | 330 | base.StopOutbound(); |
@@ -810,7 +813,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
810 | LLUDPClient udpClient = null; | 813 | LLUDPClient udpClient = null; |
811 | Packet packet = null; | 814 | Packet packet = null; |
812 | int packetEnd = buffer.DataLength - 1; | 815 | int packetEnd = buffer.DataLength - 1; |
813 | IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint; | 816 | IPEndPoint endPoint = (IPEndPoint)buffer.RemoteEndPoint; |
814 | 817 | ||
815 | #region Decoding | 818 | #region Decoding |
816 | 819 | ||
@@ -820,7 +823,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
820 | // "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}", | 823 | // "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}", |
821 | // buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); | 824 | // buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); |
822 | 825 | ||
823 | return; // Drop undersizd packet | 826 | return; // Drop undersized packet |
824 | } | 827 | } |
825 | 828 | ||
826 | int headerLen = 7; | 829 | int headerLen = 7; |
@@ -846,6 +849,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
846 | // packet = Packet.BuildPacket(buffer.Data, ref packetEnd, | 849 | // packet = Packet.BuildPacket(buffer.Data, ref packetEnd, |
847 | // // Only allocate a buffer for zerodecoding if the packet is zerocoded | 850 | // // Only allocate a buffer for zerodecoding if the packet is zerocoded |
848 | // ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); | 851 | // ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); |
852 | // If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we | ||
853 | // assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all | ||
854 | // bytes are copied out). | ||
849 | packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd, | 855 | packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd, |
850 | // Only allocate a buffer for zerodecoding if the packet is zerocoded | 856 | // Only allocate a buffer for zerodecoding if the packet is zerocoded |
851 | ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); | 857 | ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); |
@@ -887,7 +893,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
887 | 893 | ||
888 | // If there is already a client for this endpoint, don't process UseCircuitCode | 894 | // If there is already a client for this endpoint, don't process UseCircuitCode |
889 | IClientAPI client = null; | 895 | IClientAPI client = null; |
890 | if (!m_scene.TryGetClient(address, out client)) | 896 | if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) |
891 | { | 897 | { |
892 | // UseCircuitCode handling | 898 | // UseCircuitCode handling |
893 | if (packet.Type == PacketType.UseCircuitCode) | 899 | if (packet.Type == PacketType.UseCircuitCode) |
@@ -895,13 +901,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
895 | // And if there is a UseCircuitCode pending, also drop it | 901 | // And if there is a UseCircuitCode pending, also drop it |
896 | lock (m_pendingCache) | 902 | lock (m_pendingCache) |
897 | { | 903 | { |
898 | if (m_pendingCache.Contains(address)) | 904 | if (m_pendingCache.Contains(endPoint)) |
899 | return; | 905 | return; |
900 | 906 | ||
901 | m_pendingCache.AddOrUpdate(address, new Queue<UDPPacketBuffer>(), 60); | 907 | m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60); |
902 | } | 908 | } |
903 | 909 | ||
904 | object[] array = new object[] { buffer, packet }; | 910 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the |
911 | // buffer. | ||
912 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | ||
905 | 913 | ||
906 | Util.FireAndForget(HandleUseCircuitCode, array); | 914 | Util.FireAndForget(HandleUseCircuitCode, array); |
907 | 915 | ||
@@ -913,7 +921,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
913 | lock (m_pendingCache) | 921 | lock (m_pendingCache) |
914 | { | 922 | { |
915 | Queue<UDPPacketBuffer> queue; | 923 | Queue<UDPPacketBuffer> queue; |
916 | if (m_pendingCache.TryGetValue(address, out queue)) | 924 | if (m_pendingCache.TryGetValue(endPoint, out queue)) |
917 | { | 925 | { |
918 | //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type); | 926 | //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type); |
919 | queue.Enqueue(buffer); | 927 | queue.Enqueue(buffer); |
@@ -1128,21 +1136,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1128 | 1136 | ||
1129 | private void HandleUseCircuitCode(object o) | 1137 | private void HandleUseCircuitCode(object o) |
1130 | { | 1138 | { |
1131 | IPEndPoint remoteEndPoint = null; | 1139 | IPEndPoint endPoint = null; |
1132 | IClientAPI client = null; | 1140 | IClientAPI client = null; |
1133 | 1141 | ||
1134 | try | 1142 | try |
1135 | { | 1143 | { |
1136 | // DateTime startTime = DateTime.Now; | 1144 | // DateTime startTime = DateTime.Now; |
1137 | object[] array = (object[])o; | 1145 | object[] array = (object[])o; |
1138 | UDPPacketBuffer buffer = (UDPPacketBuffer)array[0]; | 1146 | endPoint = (IPEndPoint)array[0]; |
1139 | UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; | 1147 | UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; |
1140 | 1148 | ||
1141 | m_log.DebugFormat( | 1149 | m_log.DebugFormat( |
1142 | "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", | 1150 | "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", |
1143 | uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, buffer.RemoteEndPoint); | 1151 | uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, endPoint); |
1144 | |||
1145 | remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint; | ||
1146 | 1152 | ||
1147 | AuthenticateResponse sessionInfo; | 1153 | AuthenticateResponse sessionInfo; |
1148 | if (IsClientAuthorized(uccp, out sessionInfo)) | 1154 | if (IsClientAuthorized(uccp, out sessionInfo)) |
@@ -1153,13 +1159,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1153 | uccp.CircuitCode.Code, | 1159 | uccp.CircuitCode.Code, |
1154 | uccp.CircuitCode.ID, | 1160 | uccp.CircuitCode.ID, |
1155 | uccp.CircuitCode.SessionID, | 1161 | uccp.CircuitCode.SessionID, |
1156 | remoteEndPoint, | 1162 | endPoint, |
1157 | sessionInfo); | 1163 | sessionInfo); |
1158 | 1164 | ||
1159 | // Send ack straight away to let the viewer know that the connection is active. | 1165 | // Send ack straight away to let the viewer know that the connection is active. |
1160 | // The client will be null if it already exists (e.g. if on a region crossing the client sends a use | 1166 | // The client will be null if it already exists (e.g. if on a region crossing the client sends a use |
1161 | // circuit code to the existing child agent. This is not particularly obvious. | 1167 | // circuit code to the existing child agent. This is not particularly obvious. |
1162 | SendAckImmediate(remoteEndPoint, uccp.Header.Sequence); | 1168 | SendAckImmediate(endPoint, uccp.Header.Sequence); |
1163 | 1169 | ||
1164 | // We only want to send initial data to new clients, not ones which are being converted from child to root. | 1170 | // We only want to send initial data to new clients, not ones which are being converted from child to root. |
1165 | if (client != null) | 1171 | if (client != null) |
@@ -1173,12 +1179,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1173 | 1179 | ||
1174 | lock (m_pendingCache) | 1180 | lock (m_pendingCache) |
1175 | { | 1181 | { |
1176 | if (!m_pendingCache.TryGetValue(remoteEndPoint, out queue)) | 1182 | if (!m_pendingCache.TryGetValue(endPoint, out queue)) |
1177 | { | 1183 | { |
1178 | m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present"); | 1184 | m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present"); |
1179 | return; | 1185 | return; |
1180 | } | 1186 | } |
1181 | m_pendingCache.Remove(remoteEndPoint); | 1187 | m_pendingCache.Remove(endPoint); |
1182 | } | 1188 | } |
1183 | 1189 | ||
1184 | m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count); | 1190 | m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count); |
@@ -1196,9 +1202,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1196 | // Don't create clients for unauthorized requesters. | 1202 | // Don't create clients for unauthorized requesters. |
1197 | m_log.WarnFormat( | 1203 | m_log.WarnFormat( |
1198 | "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", | 1204 | "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", |
1199 | uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint); | 1205 | uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); |
1200 | lock (m_pendingCache) | 1206 | lock (m_pendingCache) |
1201 | m_pendingCache.Remove(remoteEndPoint); | 1207 | m_pendingCache.Remove(endPoint); |
1202 | } | 1208 | } |
1203 | 1209 | ||
1204 | // m_log.DebugFormat( | 1210 | // m_log.DebugFormat( |
@@ -1210,7 +1216,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1210 | { | 1216 | { |
1211 | m_log.ErrorFormat( | 1217 | m_log.ErrorFormat( |
1212 | "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}", | 1218 | "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}", |
1213 | remoteEndPoint != null ? remoteEndPoint.ToString() : "n/a", | 1219 | endPoint != null ? endPoint.ToString() : "n/a", |
1214 | client != null ? client.Name : "unknown", | 1220 | client != null ? client.Name : "unknown", |
1215 | client != null ? client.AgentId.ToString() : "unknown", | 1221 | client != null ? client.AgentId.ToString() : "unknown", |
1216 | e.Message, | 1222 | e.Message, |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs index 82775fd..e7d8a30 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs | |||
@@ -30,6 +30,7 @@ using System.Net; | |||
30 | using System.Net.Sockets; | 30 | using System.Net.Sockets; |
31 | using System.Threading; | 31 | using System.Threading; |
32 | using log4net; | 32 | using log4net; |
33 | using OpenSim.Framework; | ||
33 | 34 | ||
34 | namespace OpenMetaverse | 35 | namespace OpenMetaverse |
35 | { | 36 | { |
@@ -58,6 +59,16 @@ namespace OpenMetaverse | |||
58 | /// <summary>Flag to process packets asynchronously or synchronously</summary> | 59 | /// <summary>Flag to process packets asynchronously or synchronously</summary> |
59 | private bool m_asyncPacketHandling; | 60 | private bool m_asyncPacketHandling; |
60 | 61 | ||
62 | /// <summary> | ||
63 | /// Pool to use for handling data. May be null if UsePools = false; | ||
64 | /// </summary> | ||
65 | protected OpenSim.Framework.Pool<UDPPacketBuffer> m_pool; | ||
66 | |||
67 | /// <summary> | ||
68 | /// Are we to use object pool(s) to reduce memory churn when receiving data? | ||
69 | /// </summary> | ||
70 | public bool UsePools { get; protected set; } | ||
71 | |||
61 | /// <summary>Returns true if the server is currently listening for inbound packets, otherwise false</summary> | 72 | /// <summary>Returns true if the server is currently listening for inbound packets, otherwise false</summary> |
62 | public bool IsRunningInbound { get; private set; } | 73 | public bool IsRunningInbound { get; private set; } |
63 | 74 | ||
@@ -70,6 +81,7 @@ namespace OpenMetaverse | |||
70 | /// </summary> | 81 | /// </summary> |
71 | /// <param name="bindAddress">Local IP address to bind the server to</param> | 82 | /// <param name="bindAddress">Local IP address to bind the server to</param> |
72 | /// <param name="port">Port to listening for incoming UDP packets on</param> | 83 | /// <param name="port">Port to listening for incoming UDP packets on</param> |
84 | /// /// <param name="usePool">Are we to use an object pool to get objects for handing inbound data?</param> | ||
73 | public OpenSimUDPBase(IPAddress bindAddress, int port) | 85 | public OpenSimUDPBase(IPAddress bindAddress, int port) |
74 | { | 86 | { |
75 | m_localBindAddress = bindAddress; | 87 | m_localBindAddress = bindAddress; |
@@ -94,6 +106,11 @@ namespace OpenMetaverse | |||
94 | /// necessary</remarks> | 106 | /// necessary</remarks> |
95 | public void StartInbound(int recvBufferSize, bool asyncPacketHandling) | 107 | public void StartInbound(int recvBufferSize, bool asyncPacketHandling) |
96 | { | 108 | { |
109 | if (UsePools) | ||
110 | m_pool = new Pool<UDPPacketBuffer>(() => new UDPPacketBuffer(), 500); | ||
111 | else | ||
112 | m_pool = null; | ||
113 | |||
97 | m_asyncPacketHandling = asyncPacketHandling; | 114 | m_asyncPacketHandling = asyncPacketHandling; |
98 | 115 | ||
99 | if (!IsRunningInbound) | 116 | if (!IsRunningInbound) |
@@ -161,9 +178,12 @@ namespace OpenMetaverse | |||
161 | 178 | ||
162 | private void AsyncBeginReceive() | 179 | private void AsyncBeginReceive() |
163 | { | 180 | { |
164 | // allocate a packet buffer | 181 | UDPPacketBuffer buf; |
165 | //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut(); | 182 | |
166 | UDPPacketBuffer buf = new UDPPacketBuffer(); | 183 | if (UsePools) |
184 | buf = m_pool.GetObject(); | ||
185 | else | ||
186 | buf = new UDPPacketBuffer(); | ||
167 | 187 | ||
168 | if (IsRunningInbound) | 188 | if (IsRunningInbound) |
169 | { | 189 | { |
@@ -227,8 +247,6 @@ namespace OpenMetaverse | |||
227 | 247 | ||
228 | // get the buffer that was created in AsyncBeginReceive | 248 | // get the buffer that was created in AsyncBeginReceive |
229 | // this is the received data | 249 | // this is the received data |
230 | //WrappedObject<UDPPacketBuffer> wrappedBuffer = (WrappedObject<UDPPacketBuffer>)iar.AsyncState; | ||
231 | //UDPPacketBuffer buffer = wrappedBuffer.Instance; | ||
232 | UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; | 250 | UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; |
233 | 251 | ||
234 | try | 252 | try |
@@ -245,7 +263,8 @@ namespace OpenMetaverse | |||
245 | catch (ObjectDisposedException) { } | 263 | catch (ObjectDisposedException) { } |
246 | finally | 264 | finally |
247 | { | 265 | { |
248 | //wrappedBuffer.Dispose(); | 266 | if (UsePools) |
267 | m_pool.ReturnObject(buffer); | ||
249 | 268 | ||
250 | // Synchronous mode waits until the packet callback completes | 269 | // Synchronous mode waits until the packet callback completes |
251 | // before starting the receive to fetch another packet | 270 | // before starting the receive to fetch another packet |