aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs116
1 files changed, 23 insertions, 93 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index 8bd3461..cfe7c9d 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -30,8 +30,6 @@ using System.Net;
30using System.Net.Sockets; 30using System.Net.Sockets;
31using System.Threading; 31using System.Threading;
32using log4net; 32using log4net;
33using OpenSim.Framework;
34using OpenSim.Framework.Monitoring;
35 33
36namespace OpenMetaverse 34namespace OpenMetaverse
37{ 35{
@@ -60,31 +58,17 @@ namespace OpenMetaverse
60 /// <summary>Flag to process packets asynchronously or synchronously</summary> 58 /// <summary>Flag to process packets asynchronously or synchronously</summary>
61 private bool m_asyncPacketHandling; 59 private bool m_asyncPacketHandling;
62 60
63 /// <summary> 61 /// <summary>The all important shutdown flag</summary>
64 /// Pool to use for handling data. May be null if UsePools = false; 62 private volatile bool m_shutdownFlag = true;
65 /// </summary>
66 protected OpenSim.Framework.Pool<UDPPacketBuffer> m_pool;
67
68 /// <summary>
69 /// Are we to use object pool(s) to reduce memory churn when receiving data?
70 /// </summary>
71 public bool UsePools { get; protected set; }
72
73 /// <summary>Returns true if the server is currently listening for inbound packets, otherwise false</summary>
74 public bool IsRunningInbound { get; private set; }
75 63
76 /// <summary>Returns true if the server is currently sending outbound packets, otherwise false</summary> 64 /// <summary>Returns true if the server is currently listening, otherwise false</summary>
77 /// <remarks>If IsRunningOut = false, then any request to send a packet is simply dropped.</remarks> 65 public bool IsRunning { get { return !m_shutdownFlag; } }
78 public bool IsRunningOutbound { get; private set; }
79
80 private Stat m_poolCountStat;
81 66
82 /// <summary> 67 /// <summary>
83 /// Default constructor 68 /// Default constructor
84 /// </summary> 69 /// </summary>
85 /// <param name="bindAddress">Local IP address to bind the server to</param> 70 /// <param name="bindAddress">Local IP address to bind the server to</param>
86 /// <param name="port">Port to listening for incoming UDP packets on</param> 71 /// <param name="port">Port to listening for incoming UDP packets on</param>
87 /// /// <param name="usePool">Are we to use an object pool to get objects for handing inbound data?</param>
88 public OpenSimUDPBase(IPAddress bindAddress, int port) 72 public OpenSimUDPBase(IPAddress bindAddress, int port)
89 { 73 {
90 m_localBindAddress = bindAddress; 74 m_localBindAddress = bindAddress;
@@ -92,7 +76,7 @@ namespace OpenMetaverse
92 } 76 }
93 77
94 /// <summary> 78 /// <summary>
95 /// Start inbound UDP packet handling. 79 /// Start the UDP server
96 /// </summary> 80 /// </summary>
97 /// <param name="recvBufferSize">The size of the receive buffer for 81 /// <param name="recvBufferSize">The size of the receive buffer for
98 /// the UDP socket. This value is passed up to the operating system 82 /// the UDP socket. This value is passed up to the operating system
@@ -107,11 +91,11 @@ namespace OpenMetaverse
107 /// manner (not throwing an exception when the remote side resets the 91 /// manner (not throwing an exception when the remote side resets the
108 /// connection). This call is ignored on Mono where the flag is not 92 /// connection). This call is ignored on Mono where the flag is not
109 /// necessary</remarks> 93 /// necessary</remarks>
110 public void StartInbound(int recvBufferSize, bool asyncPacketHandling) 94 public void Start(int recvBufferSize, bool asyncPacketHandling)
111 { 95 {
112 m_asyncPacketHandling = asyncPacketHandling; 96 m_asyncPacketHandling = asyncPacketHandling;
113 97
114 if (!IsRunningInbound) 98 if (m_shutdownFlag)
115 { 99 {
116 const int SIO_UDP_CONNRESET = -1744830452; 100 const int SIO_UDP_CONNRESET = -1744830452;
117 101
@@ -139,7 +123,8 @@ namespace OpenMetaverse
139 123
140 m_udpSocket.Bind(ipep); 124 m_udpSocket.Bind(ipep);
141 125
142 IsRunningInbound = true; 126 // we're not shutting down, we're starting up
127 m_shutdownFlag = false;
143 128
144 // kick off an async receive. The Start() method will return, the 129 // kick off an async receive. The Start() method will return, the
145 // actual receives will occur asynchronously and will be caught in 130 // actual receives will occur asynchronously and will be caught in
@@ -149,84 +134,28 @@ namespace OpenMetaverse
149 } 134 }
150 135
151 /// <summary> 136 /// <summary>
152 /// Start outbound UDP packet handling. 137 /// Stops the UDP server
153 /// </summary> 138 /// </summary>
154 public void StartOutbound() 139 public void Stop()
155 {
156 IsRunningOutbound = true;
157 }
158
159 public void StopInbound()
160 { 140 {
161 if (IsRunningInbound) 141 if (!m_shutdownFlag)
162 { 142 {
163 // wait indefinitely for a writer lock. Once this is called, the .NET runtime 143 // wait indefinitely for a writer lock. Once this is called, the .NET runtime
164 // will deny any more reader locks, in effect blocking all other send/receive 144 // will deny any more reader locks, in effect blocking all other send/receive
165 // threads. Once we have the lock, we set IsRunningInbound = false to inform the other 145 // threads. Once we have the lock, we set shutdownFlag to inform the other
166 // threads that the socket is closed. 146 // threads that the socket is closed.
167 IsRunningInbound = false; 147 m_shutdownFlag = true;
168 m_udpSocket.Close(); 148 m_udpSocket.Close();
169 } 149 }
170 } 150 }
171 151
172 public void StopOutbound()
173 {
174 IsRunningOutbound = false;
175 }
176
177 protected virtual bool EnablePools()
178 {
179 if (!UsePools)
180 {
181 m_pool = new Pool<UDPPacketBuffer>(() => new UDPPacketBuffer(), 500);
182
183 m_poolCountStat
184 = new Stat(
185 "UDPPacketBufferPoolCount",
186 "Objects within the UDPPacketBuffer pool",
187 "The number of objects currently stored within the UDPPacketBuffer pool",
188 "",
189 "clientstack",
190 "packetpool",
191 StatType.Pull,
192 stat => stat.Value = m_pool.Count,
193 StatVerbosity.Debug);
194
195 StatsManager.RegisterStat(m_poolCountStat);
196
197 UsePools = true;
198
199 return true;
200 }
201
202 return false;
203 }
204
205 protected virtual bool DisablePools()
206 {
207 if (UsePools)
208 {
209 UsePools = false;
210 StatsManager.DeregisterStat(m_poolCountStat);
211
212 // We won't null out the pool to avoid a race condition with code that may be in the middle of using it.
213
214 return true;
215 }
216
217 return false;
218 }
219
220 private void AsyncBeginReceive() 152 private void AsyncBeginReceive()
221 { 153 {
222 UDPPacketBuffer buf; 154 // allocate a packet buffer
223 155 //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut();
224 if (UsePools) 156 UDPPacketBuffer buf = new UDPPacketBuffer();
225 buf = m_pool.GetObject();
226 else
227 buf = new UDPPacketBuffer();
228 157
229 if (IsRunningInbound) 158 if (!m_shutdownFlag)
230 { 159 {
231 try 160 try
232 { 161 {
@@ -279,7 +208,7 @@ namespace OpenMetaverse
279 { 208 {
280 // Asynchronous receive operations will complete here through the call 209 // Asynchronous receive operations will complete here through the call
281 // to AsyncBeginReceive 210 // to AsyncBeginReceive
282 if (IsRunningInbound) 211 if (!m_shutdownFlag)
283 { 212 {
284 // Asynchronous mode will start another receive before the 213 // Asynchronous mode will start another receive before the
285 // callback for this packet is even fired. Very parallel :-) 214 // callback for this packet is even fired. Very parallel :-)
@@ -288,6 +217,8 @@ namespace OpenMetaverse
288 217
289 // get the buffer that was created in AsyncBeginReceive 218 // get the buffer that was created in AsyncBeginReceive
290 // this is the received data 219 // this is the received data
220 //WrappedObject<UDPPacketBuffer> wrappedBuffer = (WrappedObject<UDPPacketBuffer>)iar.AsyncState;
221 //UDPPacketBuffer buffer = wrappedBuffer.Instance;
291 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; 222 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
292 223
293 try 224 try
@@ -304,8 +235,7 @@ namespace OpenMetaverse
304 catch (ObjectDisposedException) { } 235 catch (ObjectDisposedException) { }
305 finally 236 finally
306 { 237 {
307 if (UsePools) 238 //wrappedBuffer.Dispose();
308 m_pool.ReturnObject(buffer);
309 239
310 // Synchronous mode waits until the packet callback completes 240 // Synchronous mode waits until the packet callback completes
311 // before starting the receive to fetch another packet 241 // before starting the receive to fetch another packet
@@ -318,7 +248,7 @@ namespace OpenMetaverse
318 248
319 public void AsyncBeginSend(UDPPacketBuffer buf) 249 public void AsyncBeginSend(UDPPacketBuffer buf)
320 { 250 {
321 if (IsRunningOutbound) 251 if (!m_shutdownFlag)
322 { 252 {
323 try 253 try
324 { 254 {