aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs75
1 files changed, 52 insertions, 23 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index 039379d..6e6b3ef 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -30,6 +30,7 @@ using System.Net;
30using System.Net.Sockets; 30using System.Net.Sockets;
31using System.Threading; 31using System.Threading;
32using log4net; 32using log4net;
33using OpenSim.Framework;
33 34
34namespace OpenMetaverse 35namespace OpenMetaverse
35{ 36{
@@ -58,17 +59,29 @@ 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
61 /// <summary>The all important shutdown flag</summary> 62 /// <summary>
62 private volatile bool m_shutdownFlag = true; 63 /// Pool to use for handling data. May be null if UsePools = false;
64 /// </summary>
65 protected OpenSim.Framework.Pool<UDPPacketBuffer> m_pool;
63 66
64 /// <summary>Returns true if the server is currently listening, otherwise false</summary> 67 /// <summary>
65 public bool IsRunning { get { return !m_shutdownFlag; } } 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
72 /// <summary>Returns true if the server is currently listening for inbound packets, otherwise false</summary>
73 public bool IsRunningInbound { get; private set; }
74
75 /// <summary>Returns true if the server is currently sending outbound packets, otherwise false</summary>
76 /// <remarks>If IsRunningOut = false, then any request to send a packet is simply dropped.</remarks>
77 public bool IsRunningOutbound { get; private set; }
66 78
67 /// <summary> 79 /// <summary>
68 /// Default constructor 80 /// Default constructor
69 /// </summary> 81 /// </summary>
70 /// <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>
71 /// <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>
72 public OpenSimUDPBase(IPAddress bindAddress, int port) 85 public OpenSimUDPBase(IPAddress bindAddress, int port)
73 { 86 {
74 m_localBindAddress = bindAddress; 87 m_localBindAddress = bindAddress;
@@ -76,7 +89,7 @@ namespace OpenMetaverse
76 } 89 }
77 90
78 /// <summary> 91 /// <summary>
79 /// Start the UDP server 92 /// Start inbound UDP packet handling.
80 /// </summary> 93 /// </summary>
81 /// <param name="recvBufferSize">The size of the receive buffer for 94 /// <param name="recvBufferSize">The size of the receive buffer for
82 /// the UDP socket. This value is passed up to the operating system 95 /// the UDP socket. This value is passed up to the operating system
@@ -91,11 +104,16 @@ namespace OpenMetaverse
91 /// manner (not throwing an exception when the remote side resets the 104 /// manner (not throwing an exception when the remote side resets the
92 /// connection). This call is ignored on Mono where the flag is not 105 /// connection). This call is ignored on Mono where the flag is not
93 /// necessary</remarks> 106 /// necessary</remarks>
94 public void Start(int recvBufferSize, bool asyncPacketHandling) 107 public void StartInbound(int recvBufferSize, bool asyncPacketHandling)
95 { 108 {
109 if (UsePools)
110 m_pool = new Pool<UDPPacketBuffer>(() => new UDPPacketBuffer(), 500);
111 else
112 m_pool = null;
113
96 m_asyncPacketHandling = asyncPacketHandling; 114 m_asyncPacketHandling = asyncPacketHandling;
97 115
98 if (m_shutdownFlag) 116 if (!IsRunningInbound)
99 { 117 {
100 const int SIO_UDP_CONNRESET = -1744830452; 118 const int SIO_UDP_CONNRESET = -1744830452;
101 119
@@ -127,8 +145,7 @@ namespace OpenMetaverse
127 145
128 m_udpSocket.Bind(ipep); 146 m_udpSocket.Bind(ipep);
129 147
130 // we're not shutting down, we're starting up 148 IsRunningInbound = true;
131 m_shutdownFlag = false;
132 149
133 // kick off an async receive. The Start() method will return, the 150 // kick off an async receive. The Start() method will return, the
134 // actual receives will occur asynchronously and will be caught in 151 // actual receives will occur asynchronously and will be caught in
@@ -138,28 +155,41 @@ namespace OpenMetaverse
138 } 155 }
139 156
140 /// <summary> 157 /// <summary>
141 /// Stops the UDP server 158 /// Start outbound UDP packet handling.
142 /// </summary> 159 /// </summary>
143 public void Stop() 160 public void StartOutbound()
144 { 161 {
145 if (!m_shutdownFlag) 162 IsRunningOutbound = true;
163 }
164
165 public void StopInbound()
166 {
167 if (IsRunningInbound)
146 { 168 {
147 // wait indefinitely for a writer lock. Once this is called, the .NET runtime 169 // wait indefinitely for a writer lock. Once this is called, the .NET runtime
148 // will deny any more reader locks, in effect blocking all other send/receive 170 // will deny any more reader locks, in effect blocking all other send/receive
149 // threads. Once we have the lock, we set shutdownFlag to inform the other 171 // threads. Once we have the lock, we set IsRunningInbound = false to inform the other
150 // threads that the socket is closed. 172 // threads that the socket is closed.
151 m_shutdownFlag = true; 173 IsRunningInbound = false;
152 m_udpSocket.Close(); 174 m_udpSocket.Close();
153 } 175 }
154 } 176 }
155 177
178 public void StopOutbound()
179 {
180 IsRunningOutbound = false;
181 }
182
156 private void AsyncBeginReceive() 183 private void AsyncBeginReceive()
157 { 184 {
158 // allocate a packet buffer 185 UDPPacketBuffer buf;
159 //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut(); 186
160 UDPPacketBuffer buf = new UDPPacketBuffer(); 187 if (UsePools)
188 buf = m_pool.GetObject();
189 else
190 buf = new UDPPacketBuffer();
161 191
162 if (!m_shutdownFlag) 192 if (IsRunningInbound)
163 { 193 {
164 try 194 try
165 { 195 {
@@ -212,7 +242,7 @@ namespace OpenMetaverse
212 { 242 {
213 // Asynchronous receive operations will complete here through the call 243 // Asynchronous receive operations will complete here through the call
214 // to AsyncBeginReceive 244 // to AsyncBeginReceive
215 if (!m_shutdownFlag) 245 if (IsRunningInbound)
216 { 246 {
217 // Asynchronous mode will start another receive before the 247 // Asynchronous mode will start another receive before the
218 // callback for this packet is even fired. Very parallel :-) 248 // callback for this packet is even fired. Very parallel :-)
@@ -221,8 +251,6 @@ namespace OpenMetaverse
221 251
222 // get the buffer that was created in AsyncBeginReceive 252 // get the buffer that was created in AsyncBeginReceive
223 // this is the received data 253 // this is the received data
224 //WrappedObject<UDPPacketBuffer> wrappedBuffer = (WrappedObject<UDPPacketBuffer>)iar.AsyncState;
225 //UDPPacketBuffer buffer = wrappedBuffer.Instance;
226 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; 254 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
227 255
228 try 256 try
@@ -239,7 +267,8 @@ namespace OpenMetaverse
239 catch (ObjectDisposedException) { } 267 catch (ObjectDisposedException) { }
240 finally 268 finally
241 { 269 {
242 //wrappedBuffer.Dispose(); 270 if (UsePools)
271 m_pool.ReturnObject(buffer);
243 272
244 // Synchronous mode waits until the packet callback completes 273 // Synchronous mode waits until the packet callback completes
245 // before starting the receive to fetch another packet 274 // before starting the receive to fetch another packet
@@ -252,7 +281,7 @@ namespace OpenMetaverse
252 281
253 public void AsyncBeginSend(UDPPacketBuffer buf) 282 public void AsyncBeginSend(UDPPacketBuffer buf)
254 { 283 {
255 if (!m_shutdownFlag) 284 if (IsRunningOutbound)
256 { 285 {
257 try 286 try
258 { 287 {