ISocketConnectionAcceptor

Implemented by applications in order to be notified of connections as they are established by a ITcpEndpoint (i.e. either a TcpServer or TcpClient).

For every call to ITcpEndpoint::Connect() there will either ne a single call to OnConnect() or else a single call to OnConnectFailure() by the ITcpEndpoint.

OnConnect() is called if and only if a connection was established, otherwise OnConnectFailure() is called. OnConnectFailure() may indicate an I/O error. It may also be called with the windows error code WSA_OPERATION_ABORTED because a pending ITcpEndpoint::Connect() was aborted by a call to ITcpEndpoint::Close().

The ITcpEndpoint only makes at most one pending call to AcceptEx/ConnectEx at a time. When the completion packet is processed by an IOCP worker thread there will either be a call to OnConnect() or else OnConnectFailure().

ITcpEndpoint::Close() doesn't cancel an obligation to issue a notification. Rather it should only be seen as a way to make the notification happen sooner rather than later.

Both OnConnect() and OnConnectFailure() must not throw any exceptions.

There are no restrictions on when ITcpEndpoint::Connect() may be called. For example, it may be called within the implementation of OnConnect() or OnConnectFailure().


struct ISocketConnectionAcceptor
{
    virtual void OnConnect(ITcpEndpoint* ep, boost::asio::ip::tcp::socket* s) = 0;
    virtual void OnConnectFailure(ITcpEndpoint* ep,SocketErrorCode ec, bool closed) = 0;
};


void OnConnect(ITcpEndpoint* ep, boost::asio::ip::tcp::socket* s)

Notification of a successfully connected socket, issued as a result of a call to ITcpEndpoint::Connect().

The implementor of this function must take ownership of the given socket (i.e. take responsibility for closing it).

The given socket will already have been associated with the same IOCP port (i.e. with a call to CreateIoCompletionPort())


void OnConnectFailure(ITcpEndpoint* ep,SocketErrorCode ec, bool closed)

Notification of a failure trying to connect a socket, issued as a result of a call to ITcpEndpoint::Connect().

Possible values of ec.sc are:

ec.windowsErrorCode = WSA_OPERATION_ABORTED is issued if a pending AcceptEx was aborted by closing the server.

If 'closed' is true then a client has called ITcpEndpoint::Close() by the time this function was called.

Typically an implementation of this function will want to issue another ITcpEndpoint::Connect() when 'closed' is false.

How to limit the number of connections

It is possible to impose an upper bound on the total number of connections. Let this be MAX_NUM_CONNECTIONS.

The implementor of the ISocketConnectionAcceptor keeps a count on the current number of connected sockets. This uses InterlockedIncrement and InterlockedDecrement.

OnConnectFailure() should call ITcpEndpoint::Connect() unless 'closed' is true, so that the ITcpEndpoint can recover from errors.

The implementation of OnConnect() calls InterlockedIncrement() on the counter and if the count is less than MAX_NUM_CONNECTIONS it calls ITcpEndpoint::Connect() to allow another connection to be established.

When each connection is closed there is a call to InterlockedDecrement(). If this transitions to MAX_NUM_CONNECTIONS-1 then ITcpEndpoint::Connect() is called, allowing it to establish another connection.

Threading rules

$$(OnConnect,OnConnectFailure)