/// <summary>
/// Callback method for asynchronous accept operation.
/// </summary>
private void ProcessAccept()
{
TransportProvider<Socket> client = new TransportProvider<Socket>();
SocketAsyncEventArgs receiveArgs = null;
TcpClientInfo clientInfo;
try
{
if (CurrentState == ServerState.NotRunning)
return;
if (m_acceptArgs.SocketError != SocketError.Success)
{
// Error is unrecoverable.
// We need to make sure to restart the
// server before we throw the error.
SocketError error = m_acceptArgs.SocketError;
ThreadPool.QueueUserWorkItem(state => ReStart());
throw new SocketException((int)error);
}
// Process the newly connected client.
client.Provider = m_acceptArgs.AcceptSocket;
// Set up SocketAsyncEventArgs for receive operations.
receiveArgs = FastObjectFactory<SocketAsyncEventArgs>.CreateObjectFunction();
receiveArgs.Completed += ReceiveHandler;
// Return to accepting new connections.
m_acceptArgs.AcceptSocket = null;
if (!m_tcpServer.AcceptAsync(m_acceptArgs))
{
ThreadPool.QueueUserWorkItem(state => ProcessAccept());
}
#if !MONO
// Authenticate the connected client Windows credentials.
if (m_integratedSecurity)
{
NetworkStream socketStream = null;
NegotiateStream authenticationStream = null;
try
{
socketStream = new NetworkStream(client.Provider);
authenticationStream = new NegotiateStream(socketStream);
authenticationStream.AuthenticateAsServer();
if (authenticationStream.RemoteIdentity is WindowsIdentity)
Thread.CurrentPrincipal = new WindowsPrincipal((WindowsIdentity)authenticationStream.RemoteIdentity);
}
finally
{
if (socketStream != null)
socketStream.Dispose();
if (authenticationStream != null)
authenticationStream.Dispose();
}
}
#endif
if (MaxClientConnections != -1 && ClientIDs.Length >= MaxClientConnections)
{
// Reject client connection since limit has been reached.
TerminateConnection(client, receiveArgs, false);
}
else
{
// We can proceed further with receiving data from the client.
clientInfo = new TcpClientInfo()
{
Client = client,
SendArgs = FastObjectFactory<SocketAsyncEventArgs>.CreateObjectFunction(),
SendLock = new SpinLock(),
SendQueue = new ConcurrentQueue<TcpServerPayload>()
};
// Set up socket args.
client.SetSendBuffer(SendBufferSize);
clientInfo.SendArgs.Completed += m_sendHandler;
clientInfo.SendArgs.SetBuffer(client.SendBuffer, 0, client.SendBufferSize);
m_clientInfoLookup.TryAdd(client.ID, clientInfo);
OnClientConnected(client.ID);
if (!m_payloadAware)
{
receiveArgs.UserToken = client;
}
else
{
EventArgs<TransportProvider<Socket>, bool> userToken = ReusableObjectPool<EventArgs<TransportProvider<Socket>, bool>>.Default.TakeObject();
userToken.Argument1 = client;
receiveArgs.UserToken = userToken;
}
ReceivePayloadAsync(client, receiveArgs);
}
}
catch (Exception ex)
{
// Notify of the exception.
if ((object)client.Provider != null)
{
string clientAddress = ((IPEndPoint)client.Provider.RemoteEndPoint).Address.ToString();
string errorMessage = string.Format("Unable to accept connection to client [{0}]: {1}", clientAddress, ex.Message);
OnClientConnectingException(new Exception(errorMessage, ex));
}
if ((object)receiveArgs != null)
{
TerminateConnection(client, receiveArgs, false);
}
}
}