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