예제 #1
0
        /// <summary>
        /// Releases the Stream's SocketAsyncEventArgs back to the pool,
        /// and free's up another slot for a new client to connect
        /// </summary>
        /// <param name="Stream">The TcpStream object that is being released.</param>
        public void Release(TCPStream Stream)
        {
            // If the stream has been released, then we stop here
            if (!IsRunning || Stream.Released)
            {
                return;
            }

            // Make sure the connection is closed properly
            if (!Stream.SocketClosed)
            {
                Stream.Close();
                return;
            }

            // To prevent cross instance releasing
            //if (!Object.ReferenceEquals(this, Stream.SocketManager))
            //throw new ArgumentException("Cannot pass a GamespyTcpStream belonging to a different TcpSocket than this one.");

            // If we are still registered for this event, then the EventArgs should
            // NEVER be disposed here, or we have an error to fix
            if (Stream.DisposedEventArgs)
            {
                // Dispose old buffer tokens
                BufferManager.ReleaseBuffer(Stream.ReadEventArgs);
                BufferManager.ReleaseBuffer(Stream.WriteEventArgs);

                // Create new Read Event Args
                SocketAsyncEventArgs SockArgR = new SocketAsyncEventArgs();
                BufferManager.AssignBuffer(SockArgR);
                SocketReadWritePool.Push(SockArgR);

                // Create new Write Event Args
                SocketAsyncEventArgs SockArgW = new SocketAsyncEventArgs();
                BufferManager.AssignBuffer(SockArgW);
                SocketReadWritePool.Push(SockArgW);
            }
            else
            {
                // Set null's
                Stream.ReadEventArgs.AcceptSocket  = null;
                Stream.WriteEventArgs.AcceptSocket = null;

                // Get our ReadWrite AsyncEvent object back
                SocketReadWritePool.Push(Stream.ReadEventArgs);
                SocketReadWritePool.Push(Stream.WriteEventArgs);
            }

            // Now that we have another set of AsyncEventArgs, we can
            // release this users Semephore lock, allowing another connection
            MaxConnectionsEnforcer.Release();
        }
예제 #2
0
 /// <summary>
 /// When a new connection is established, the parent class is responsible for
 /// processing the connected client
 /// </summary>
 /// <param name="Stream">A TcpStream object that wraps the I/O AsyncEventArgs and socket</param>
 protected abstract void ProcessAccept(TCPStream Stream);
예제 #3
0
        /// <summary>
        /// Once a connection has been received, its handed off here to convert it into
        /// our client object, and prepared to be handed off to the parent for processing
        /// </summary>
        /// <param name="AcceptEventArg"></param>
        protected async void PrepareAccept(SocketAsyncEventArgs AcceptEventArg)
        {
            // If we do not get a success code here, we have a bad socket
            if (IgnoreNewConnections || AcceptEventArg.SocketError != SocketError.Success)
            {
                // This method closes the socket and releases all resources, both
                // managed and unmanaged. It internally calls Dispose.
                AcceptEventArg.AcceptSocket.Close();

                // Put the SAEA back in the pool.
                SocketAcceptPool.Push(AcceptEventArg);
                StartAcceptAsync();
                return;
            }

            // If the server is full, send an error message to the player
            if (ConnectionEnforceMode == EnforceMode.DuringPrepare)
            {
                bool Success = await MaxConnectionsEnforcer.WaitAsync(WaitTimeout);

                if (!Success)
                {
                    // If we arent even listening...
                    if (!IsRunning)
                    {
                        return;
                    }

                    // Alert the client that we are full
                    if (!String.IsNullOrEmpty(FullErrorMessage))
                    {
                        OnAcceptFails(AcceptEventArg.AcceptSocket);
                    }

                    // Log so we can track this!
                    //Program.ErrorLog.Write("NOTICE: [GamespyTcpSocket.PrepareAccept] The Server is currently full! Rejecting connecting client.");

                    // Put the SAEA back in the pool.
                    AcceptEventArg.AcceptSocket.Close();
                    SocketAcceptPool.Push(AcceptEventArg);
                    StartAcceptAsync();
                    return;
                }
            }

            // Begin accepting a new connection
            StartAcceptAsync();

            // Grab a send/receive object
            SocketAsyncEventArgs ReadArgs  = SocketReadWritePool.Pop();
            SocketAsyncEventArgs WriteArgs = SocketReadWritePool.Pop();

            // Pass over the reference to the new socket that is handling
            // this specific stream, and dereference it so we can hand the
            // acception event back over
            ReadArgs.AcceptSocket       = WriteArgs.AcceptSocket = AcceptEventArg.AcceptSocket;
            AcceptEventArg.AcceptSocket = null;

            // Hand back the AcceptEventArg so another connection can be accepted
            SocketAcceptPool.Push(AcceptEventArg);

            // Hand off processing to the parent
            TCPStream Stream = null;

            try
            {
                Stream = new TCPStream(this, ReadArgs, WriteArgs);
                ProcessAccept(Stream);
            }
            catch (Exception e)
            {
                // Report Error
                OnException(e);

                // Make sure the connection is closed properly
                if (Stream != null)
                {
                    Release(Stream);
                }
            }
        }