diff --git a/Server/Network/Listener.cs b/Server/Network/Listener.cs index f4a9dfcb7..314894867 100644 --- a/Server/Network/Listener.cs +++ b/Server/Network/Listener.cs @@ -66,7 +66,7 @@ namespace Server.Network #if Framework_4_0 m_EventArgs = new SocketAsyncEventArgs(); m_EventArgs.Completed += new EventHandler( Accept_Completion ); - ThreadPool.QueueUserWorkItem( delegate { Accept_Start(); } ); + Accept_Start(); #else m_OnAccept = new AsyncCallback( OnAccept ); try { diff --git a/Server/Network/NetState.cs b/Server/Network/NetState.cs index 6ef8cc7d2..7e62837f9 100644 --- a/Server/Network/NetState.cs +++ b/Server/Network/NetState.cs @@ -50,7 +50,13 @@ namespace Server.Network { private SendQueue m_SendQueue; private bool m_Seeded; private bool m_Running; + +#if Framework_4_0 + private SocketAsyncEventArgs m_ReceiveEventArgs, m_SendEventArgs; +#else private AsyncCallback m_OnReceive, m_OnSend; +#endif + private MessagePump m_MessagePump; private ServerInfo[] m_ServerInfo; private IAccount m_Account; @@ -103,48 +109,6 @@ namespace Server.Network { private AsyncState m_AsyncState; private object m_AsyncLock = new object(); - public static void Pause() { - m_Paused = true; - - for ( int i = 0; i < m_Instances.Count; ++i ) { - NetState ns = m_Instances[i]; - - lock ( ns.m_AsyncLock ) { - ns.m_AsyncState |= AsyncState.Paused; - } - } - } - - private void InternalBeginReceive() { - m_AsyncState |= AsyncState.Pending; - - m_Socket.BeginReceive( m_RecvBuffer, 0, m_RecvBuffer.Length, SocketFlags.None, m_OnReceive, m_Socket ); - } - - public static void Resume() { - m_Paused = false; - - for ( int i = 0; i < m_Instances.Count; ++i ) { - NetState ns = m_Instances[i]; - - if ( ns.m_Socket == null ) { - continue; - } - - lock ( ns.m_AsyncLock ) { - ns.m_AsyncState &= ~AsyncState.Paused; - - try { - if ( ( ns.m_AsyncState & AsyncState.Pending ) == 0 ) - ns.InternalBeginReceive(); - } catch ( Exception ex ) { - TraceException( ex ); - ns.Dispose( false ); - } - } - } - } - private IPacketEncoder m_Encoder = null; public IPacketEncoder PacketEncoder { @@ -515,6 +479,11 @@ namespace Server.Network { } } + public void LaunchBrowser( string url ) { + Send( new MessageLocalized( Serial.MinusOne, -1, MessageType.Label, 0x35, 3, 501231, "", "" ) ); + Send( new LaunchBrowser( url ) ); + } + public CityInfo[] CityInfo { get { return m_CityInfo; @@ -601,14 +570,6 @@ namespace Server.Network { } } - public PacketHandler GetHandler( int packetID ) - { - if ( ContainerGridLines ) - return PacketHandlers.Get6017Handler( packetID ); - else - return PacketHandlers.GetHandler( packetID ); - } - public virtual void Send( Packet p ) { if ( m_Socket == null || m_BlockAllPackets ) { p.OnSend(); @@ -642,12 +603,17 @@ namespace Server.Network { } if ( gram != null ) { +#if Framework_4_0 + m_SendEventArgs.SetBuffer( gram.Buffer, 0, gram.Length ); + Send_Start(); +#else try { m_Socket.BeginSend( gram.Buffer, 0, gram.Length, SocketFlags.None, m_OnSend, m_Socket ); } catch ( Exception ex ) { TraceException( ex ); Dispose( false ); } +#endif } } catch ( CapacityExceededException ) { Console.WriteLine( "Client: {0}: Too much data pending, disconnecting...", this ); @@ -670,11 +636,160 @@ namespace Server.Network { } } - public static void FlushAll() { +#if Framework_4_0 + public void Start() { + m_ReceiveEventArgs = new SocketAsyncEventArgs(); + m_ReceiveEventArgs.Completed += new EventHandler( Receive_Completion ); + m_ReceiveEventArgs.SetBuffer( m_RecvBuffer, 0, m_RecvBuffer.Length ); + + m_SendEventArgs = new SocketAsyncEventArgs(); + m_SendEventArgs.Completed += new EventHandler( Send_Completion ); + + m_Running = true; + + if ( m_Socket == null || m_Paused ) { + return; + } + + Receive_Start(); + } + + private void Receive_Start() + { + try { + bool result = false; + + do { + lock ( m_AsyncLock ) { + if ( ( m_AsyncState & ( AsyncState.Pending | AsyncState.Paused ) ) == 0 ) { + m_AsyncState |= AsyncState.Pending; + result = !m_Socket.ReceiveAsync( m_ReceiveEventArgs ); + + if ( result ) + Receive_Process( m_ReceiveEventArgs ); + } + } + } while ( result ); + } catch ( Exception ex ) { + TraceException( ex ); + Dispose( false ); + } + } + + private void Receive_Completion( object sender, SocketAsyncEventArgs e ) + { + Receive_Process( e ); + + if ( !m_Disposing ) + Receive_Start(); + } + + private void Receive_Process( SocketAsyncEventArgs e ) + { + int byteCount = e.BytesTransferred; + + if ( e.SocketError != SocketError.Success || byteCount <= 0 ) { + Dispose( false ); + return; + } + + m_NextCheckActivity = DateTime.Now + TimeSpan.FromMinutes( 1.2 ); + + byte[] buffer = m_RecvBuffer; + + if ( m_Encoder != null ) + m_Encoder.DecodeIncomingPacket( this, ref buffer, ref byteCount ); + + lock ( m_Buffer ) + m_Buffer.Enqueue( buffer, 0, byteCount ); + + m_MessagePump.OnReceive( this ); + + lock ( m_AsyncLock ) { + m_AsyncState &= ~AsyncState.Pending; + } + } + + private void Send_Start() + { + try { + bool result = false; + + do { + result = !m_Socket.SendAsync( m_SendEventArgs ); + + if ( result ) + Send_Process( m_SendEventArgs ); + } while ( result ); + } catch ( Exception ex ) { + TraceException( ex ); + Dispose( false ); + } + } + + private void Send_Completion( object sender, SocketAsyncEventArgs e ) + { + Send_Process( e ); + + if ( m_Disposing ) + return; + + if ( m_CoalesceSleep >= 0 ) { + Thread.Sleep( m_CoalesceSleep ); + } + + SendQueue.Gram gram; + + lock ( m_SendQueue ) { + gram = m_SendQueue.Dequeue(); + } + + if ( gram != null ) { + m_SendEventArgs.SetBuffer( gram.Buffer, 0, gram.Length ); + Send_Start(); + } + } + + private void Send_Process( SocketAsyncEventArgs e ) + { + int bytes = e.BytesTransferred; + + if ( e.SocketError != SocketError.Success || bytes <= 0 ) { + Dispose( false ); + return; + } + + m_NextCheckActivity = DateTime.Now + TimeSpan.FromMinutes( 1.2 ); + } + + public static void Pause() { + m_Paused = true; + for ( int i = 0; i < m_Instances.Count; ++i ) { NetState ns = m_Instances[i]; - ns.Flush(); + lock ( ns.m_AsyncLock ) { + ns.m_AsyncState |= AsyncState.Paused; + } + } + } + + public static void Resume() { + m_Paused = false; + + for ( int i = 0; i < m_Instances.Count; ++i ) { + NetState ns = m_Instances[i]; + + if ( ns.m_Socket == null ) { + continue; + } + + lock ( ns.m_AsyncLock ) { + ns.m_AsyncState &= ~AsyncState.Paused; + + if ( ( ns.m_AsyncState & AsyncState.Pending ) == 0 ) + ns.Receive_Start(); + } } } @@ -690,64 +805,14 @@ namespace Server.Network { } if ( gram != null ) { - try { - m_Socket.BeginSend( gram.Buffer, 0, gram.Length, SocketFlags.None, m_OnSend, m_Socket ); - return true; - } catch ( Exception ex ) { - TraceException( ex ); - Dispose( false ); - } + m_SendEventArgs.SetBuffer( gram.Buffer, 0, gram.Length ); + Send_Start(); } return false; } - private static int m_CoalesceSleep = -1; - - public static int CoalesceSleep { - get { - return m_CoalesceSleep; - } - set { - m_CoalesceSleep = value; - } - } - - private void OnSend( IAsyncResult asyncResult ) { - Socket s = (Socket)asyncResult.AsyncState; - - try { - int bytes = s.EndSend( asyncResult ); - - if ( bytes <= 0 ) { - Dispose( false ); - return; - } - - m_NextCheckActivity = DateTime.Now + TimeSpan.FromMinutes( 1.2 ); - - if ( m_CoalesceSleep >= 0 ) { - Thread.Sleep( m_CoalesceSleep ); - } - - SendQueue.Gram gram; - - lock ( m_SendQueue ) { - gram = m_SendQueue.Dequeue(); - } - - if ( gram != null ) { - try { - s.BeginSend( gram.Buffer, 0, gram.Length, SocketFlags.None, m_OnSend, s ); - } catch ( Exception ex ) { - TraceException( ex ); - Dispose( false ); - } - } - } catch ( Exception ){ - Dispose( false ); - } - } +#else public void Start() { m_OnReceive = new AsyncCallback( OnReceive ); @@ -771,25 +836,10 @@ namespace Server.Network { } } - public void LaunchBrowser( string url ) { - Send( new MessageLocalized( Serial.MinusOne, -1, MessageType.Label, 0x35, 3, 501231, "", "" ) ); - Send( new LaunchBrowser( url ) ); - } + private void InternalBeginReceive() { + m_AsyncState |= AsyncState.Pending; - private DateTime m_NextCheckActivity; - - public bool CheckAlive() { - if ( m_Socket == null ) - return false; - - if ( DateTime.Now < m_NextCheckActivity ) { - return true; - } - - Console.WriteLine( "Client: {0}: Disconnecting due to inactivity...", this ); - - Dispose(); - return false; + m_Socket.BeginReceive( m_RecvBuffer, 0, m_RecvBuffer.Length, SocketFlags.None, m_OnReceive, m_Socket ); } private void OnReceive( IAsyncResult asyncResult ) { @@ -831,8 +881,144 @@ namespace Server.Network { } } - public void Dispose() { - Dispose( true ); + private void OnSend( IAsyncResult asyncResult ) { + Socket s = (Socket)asyncResult.AsyncState; + + try { + int bytes = s.EndSend( asyncResult ); + + if ( bytes <= 0 ) { + Dispose( false ); + return; + } + + m_NextCheckActivity = DateTime.Now + TimeSpan.FromMinutes( 1.2 ); + + if ( m_CoalesceSleep >= 0 ) { + Thread.Sleep( m_CoalesceSleep ); + } + + SendQueue.Gram gram; + + lock ( m_SendQueue ) { + gram = m_SendQueue.Dequeue(); + } + + if ( gram != null ) { + try { + s.BeginSend( gram.Buffer, 0, gram.Length, SocketFlags.None, m_OnSend, s ); + } catch ( Exception ex ) { + TraceException( ex ); + Dispose( false ); + } + } + } catch ( Exception ){ + Dispose( false ); + } + } + + public static void Pause() { + m_Paused = true; + + for ( int i = 0; i < m_Instances.Count; ++i ) { + NetState ns = m_Instances[i]; + + lock ( ns.m_AsyncLock ) { + ns.m_AsyncState |= AsyncState.Paused; + } + } + } + + public static void Resume() { + m_Paused = false; + + for ( int i = 0; i < m_Instances.Count; ++i ) { + NetState ns = m_Instances[i]; + + if ( ns.m_Socket == null ) { + continue; + } + + lock ( ns.m_AsyncLock ) { + ns.m_AsyncState &= ~AsyncState.Paused; + + try { + if ( ( ns.m_AsyncState & AsyncState.Pending ) == 0 ) + ns.InternalBeginReceive(); + } catch ( Exception ex ) { + TraceException( ex ); + ns.Dispose( false ); + } + } + } + } + + public bool Flush() { + if ( m_Socket == null || !m_SendQueue.IsFlushReady ) { + return false; + } + + SendQueue.Gram gram; + + lock ( m_SendQueue ) { + gram = m_SendQueue.CheckFlushReady(); + } + + if ( gram != null ) { + try { + m_Socket.BeginSend( gram.Buffer, 0, gram.Length, SocketFlags.None, m_OnSend, m_Socket ); + return true; + } catch ( Exception ex ) { + TraceException( ex ); + Dispose( false ); + } + } + + return false; + } +#endif + + public PacketHandler GetHandler( int packetID ) + { + if ( ContainerGridLines ) + return PacketHandlers.Get6017Handler( packetID ); + else + return PacketHandlers.GetHandler( packetID ); + } + + public static void FlushAll() { + for ( int i = 0; i < m_Instances.Count; ++i ) { + NetState ns = m_Instances[i]; + + ns.Flush(); + } + } + + private static int m_CoalesceSleep = -1; + + public static int CoalesceSleep { + get { + return m_CoalesceSleep; + } + set { + m_CoalesceSleep = value; + } + } + + private DateTime m_NextCheckActivity; + + public bool CheckAlive() { + if ( m_Socket == null ) + return false; + + if ( DateTime.Now < m_NextCheckActivity ) { + return true; + } + + Console.WriteLine( "Client: {0}: Disconnecting due to inactivity...", this ); + + Dispose(); + return false; } public static void TraceException( Exception ex ) { @@ -856,6 +1042,10 @@ namespace Server.Network { private bool m_Disposing; + public void Dispose() { + Dispose( true ); + } + public virtual void Dispose( bool flush ) { if ( m_Socket == null || m_Disposing ) { return; @@ -885,8 +1075,15 @@ namespace Server.Network { m_Buffer = null; m_RecvBuffer = null; + +#if Framework_4_0 + m_ReceiveEventArgs = null; + m_SendEventArgs = null; +#else m_OnReceive = null; m_OnSend = null; +#endif + m_Running = false; m_Disposed.Enqueue( this );