diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs | 101 |
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; | |||
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; | ||
34 | using OpenSim.Framework.Monitoring; | ||
33 | 35 | ||
34 | namespace OpenMetaverse | 36 | namespace 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 |