diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs | 75 |
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; | |||
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,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 | { |