Allow the LLUDP server to run in either synchronous or asynchronous mode with a config setting, defaulting to synchronous mode

prioritization
John Hurliman 2009-10-14 16:48:27 -07:00
parent 82012ec4e3
commit 06990b074c
3 changed files with 36 additions and 7 deletions

View File

@ -113,6 +113,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// is passed up to the operating system and used in the system networking /// is passed up to the operating system and used in the system networking
/// stack. Use zero to leave this value as the default</summary> /// stack. Use zero to leave this value as the default</summary>
private int m_recvBufferSize; private int m_recvBufferSize;
/// <summary>Flag to process packets asynchronously or synchronously</summary>
private bool m_asyncPacketHandling;
/// <summary>The measured resolution of Environment.TickCount</summary> /// <summary>The measured resolution of Environment.TickCount</summary>
public float TickCountResolution { get { return m_tickCountResolution; } } public float TickCountResolution { get { return m_tickCountResolution; } }
@ -143,6 +145,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
IConfig config = configSource.Configs["ClientStack.LindenUDP"]; IConfig config = configSource.Configs["ClientStack.LindenUDP"];
if (config != null) if (config != null)
{ {
m_asyncPacketHandling = config.GetBoolean("async_packet_handling", false);
m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0); m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0);
sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0); sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0);
} }
@ -156,7 +159,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (m_scene == null) if (m_scene == null)
throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference"); throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference");
base.Start(m_recvBufferSize); m_log.Info("[LLUDPSERVER]: Starting the LLUDP server in " + (m_asyncPacketHandling ? "asynchronous" : "synchronous") + " mode");
base.Start(m_recvBufferSize, m_asyncPacketHandling);
// Start the incoming packet processing thread // Start the incoming packet processing thread
Thread incomingThread = new Thread(IncomingPacketHandler); Thread incomingThread = new Thread(IncomingPacketHandler);

View File

@ -62,6 +62,9 @@ namespace OpenMetaverse
/// <summary>UDP socket, used in either client or server mode</summary> /// <summary>UDP socket, used in either client or server mode</summary>
private Socket m_udpSocket; private Socket m_udpSocket;
/// <summary>Flag to process packets asynchronously or synchronously</summary>
private bool m_asyncPacketHandling;
/// <summary>The all important shutdown flag</summary> /// <summary>The all important shutdown flag</summary>
private volatile bool m_shutdownFlag = true; private volatile bool m_shutdownFlag = true;
@ -73,7 +76,6 @@ namespace OpenMetaverse
/// </summary> /// </summary>
/// <param name="bindAddress">Local IP address to bind the server to</param> /// <param name="bindAddress">Local IP address to bind the server to</param>
/// <param name="port">Port to listening for incoming UDP packets on</param> /// <param name="port">Port to listening for incoming UDP packets on</param>
///
public OpenSimUDPBase(IPAddress bindAddress, int port) public OpenSimUDPBase(IPAddress bindAddress, int port)
{ {
m_localBindAddress = bindAddress; m_localBindAddress = bindAddress;
@ -87,13 +89,19 @@ namespace OpenMetaverse
/// the UDP socket. This value is passed up to the operating system /// the UDP socket. This value is passed up to the operating system
/// and used in the system networking stack. Use zero to leave this /// and used in the system networking stack. Use zero to leave this
/// value as the default</param> /// value as the default</param>
/// <param name="asyncPacketHandling">Set this to true to start
/// receiving more packets while current packet handler callbacks are
/// still running. Setting this to false will complete each packet
/// callback before the next packet is processed</param>
/// <remarks>This method will attempt to set the SIO_UDP_CONNRESET flag /// <remarks>This method will attempt to set the SIO_UDP_CONNRESET flag
/// on the socket to get newer versions of Windows to behave in a sane /// on the socket to get newer versions of Windows to behave in a sane
/// manner (not throwing an exception when the remote side resets the /// manner (not throwing an exception when the remote side resets the
/// connection). This call is ignored on Mono where the flag is not /// connection). This call is ignored on Mono where the flag is not
/// necessary</remarks> /// necessary</remarks>
public void Start(int recvBufferSize) public void Start(int recvBufferSize, bool asyncPacketHandling)
{ {
m_asyncPacketHandling = asyncPacketHandling;
if (m_shutdownFlag) if (m_shutdownFlag)
{ {
const int SIO_UDP_CONNRESET = -1744830452; const int SIO_UDP_CONNRESET = -1744830452;
@ -209,7 +217,9 @@ namespace OpenMetaverse
// to AsyncBeginReceive // to AsyncBeginReceive
if (!m_shutdownFlag) if (!m_shutdownFlag)
{ {
// start another receive - this keeps the server going! // Asynchronous mode will start another receive before the
// callback for this packet is even fired. Very parallel :-)
if (m_asyncPacketHandling)
AsyncBeginReceive(); AsyncBeginReceive();
// get the buffer that was created in AsyncBeginReceive // get the buffer that was created in AsyncBeginReceive
@ -230,7 +240,15 @@ namespace OpenMetaverse
} }
catch (SocketException) { } catch (SocketException) { }
catch (ObjectDisposedException) { } catch (ObjectDisposedException) { }
//finally { wrappedBuffer.Dispose(); } finally
{
//wrappedBuffer.Dispose();
// Synchronous mode waits until the packet callback completes
// before starting the receive to fetch another packet
if (!m_asyncPacketHandling)
AsyncBeginReceive();
}
} }
} }

View File

@ -341,7 +341,13 @@
[ClientStack.LindenUDP] [ClientStack.LindenUDP]
; the client socket receive buffer size determines how many ; Set this to true to process incoming packets asynchronously. Networking is
; already separated from packet handling with a queue, so this will only
; affect whether networking internals such as packet decoding and
; acknowledgement accounting are done synchronously or asynchronously
async_packet_handling = false
; The client socket receive buffer size determines how many
; incoming requests we can process; the default on .NET is 8192 ; incoming requests we can process; the default on .NET is 8192
; which is about 2 4k-sized UDP datagrams. On mono this is ; which is about 2 4k-sized UDP datagrams. On mono this is
; whatever the underlying operating system has as default; for ; whatever the underlying operating system has as default; for