1
0

cNetwork: Changed listening API.

The link-callbacks for each new accepted link are now received from the OnIncomingConnection listen-callback.
This commit is contained in:
Mattes D 2015-01-21 21:12:11 +01:00
parent 64855ed340
commit 5b4c5cf2be
5 changed files with 79 additions and 51 deletions

View File

@ -139,8 +139,15 @@ public:
// Force a virtual destructor for all descendants: // Force a virtual destructor for all descendants:
virtual ~cListenCallbacks() {} virtual ~cListenCallbacks() {}
/** Called when the TCP server created with Listen() accepts an incoming connection. /** Called when the TCP server created with Listen() receives a new incoming connection.
Provides the newly created Link that can be used for communication. */ Returns the link callbacks that the server should use for the newly created link.
If a nullptr is returned, the connection is dropped immediately;
otherwise a new cTCPLink instance is created and OnAccepted() is called. */
virtual cTCPLink::cCallbacksPtr OnIncomingConnection(const AString & a_RemoteIPAddress, UInt16 a_RemotePort) = 0;
/** Called when the TCP server created with Listen() creates a new link for an incoming connection.
Provides the newly created Link that can be used for communication.
Called right after a successful OnIncomingConnection(). */
virtual void OnAccepted(cTCPLink & a_Link) = 0; virtual void OnAccepted(cTCPLink & a_Link) = 0;
/** Called when the socket fails to listen on the specified port. */ /** Called when the socket fails to listen on the specified port. */
@ -180,7 +187,7 @@ public:
Implemented in TCPLinkImpl.cpp. */ Implemented in TCPLinkImpl.cpp. */
static bool Connect( static bool Connect(
const AString & a_Host, const AString & a_Host,
const UInt16 a_Port, UInt16 a_Port,
cConnectCallbacksPtr a_ConnectCallbacks, cConnectCallbacksPtr a_ConnectCallbacks,
cTCPLink::cCallbacksPtr a_LinkCallbacks cTCPLink::cCallbacksPtr a_LinkCallbacks
); );
@ -192,9 +199,8 @@ public:
Returns a cServerHandle that can be used to query the operation status and close the server. Returns a cServerHandle that can be used to query the operation status and close the server.
Implemented in ServerHandleImpl.cpp. */ Implemented in ServerHandleImpl.cpp. */
static cServerHandlePtr Listen( static cServerHandlePtr Listen(
const UInt16 a_Port, UInt16 a_Port,
cListenCallbacksPtr a_ListenCallbacks, cListenCallbacksPtr a_ListenCallbacks
cTCPLink::cCallbacksPtr a_LinkCallbacks
); );

View File

@ -31,12 +31,8 @@ static bool IsValidSocket(evutil_socket_t a_Socket)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// cServerHandleImpl: // cServerHandleImpl:
cServerHandleImpl::cServerHandleImpl( cServerHandleImpl::cServerHandleImpl(cNetwork::cListenCallbacksPtr a_ListenCallbacks):
cNetwork::cListenCallbacksPtr a_ListenCallbacks,
cTCPLink::cCallbacksPtr a_LinkCallbacks
):
m_ListenCallbacks(a_ListenCallbacks), m_ListenCallbacks(a_ListenCallbacks),
m_LinkCallbacks(a_LinkCallbacks),
m_ConnListener(nullptr), m_ConnListener(nullptr),
m_SecondaryConnListener(nullptr), m_SecondaryConnListener(nullptr),
m_IsListening(false), m_IsListening(false),
@ -92,11 +88,10 @@ void cServerHandleImpl::Close(void)
cServerHandleImplPtr cServerHandleImpl::Listen( cServerHandleImplPtr cServerHandleImpl::Listen(
UInt16 a_Port, UInt16 a_Port,
cNetwork::cListenCallbacksPtr a_ListenCallbacks, cNetwork::cListenCallbacksPtr a_ListenCallbacks
cTCPLink::cCallbacksPtr a_LinkCallbacks
) )
{ {
cServerHandleImplPtr res = cServerHandleImplPtr{new cServerHandleImpl(a_ListenCallbacks, a_LinkCallbacks)}; cServerHandleImplPtr res = cServerHandleImplPtr{new cServerHandleImpl(a_ListenCallbacks)};
if (res->Listen(a_Port)) if (res->Listen(a_Port))
{ {
cNetworkSingleton::Get().AddServer(res); cNetworkSingleton::Get().AddServer(res);
@ -253,8 +248,37 @@ void cServerHandleImpl::Callback(evconnlistener * a_Listener, evutil_socket_t a_
cServerHandleImpl * Self = reinterpret_cast<cServerHandleImpl *>(a_Self); cServerHandleImpl * Self = reinterpret_cast<cServerHandleImpl *>(a_Self);
ASSERT(Self != nullptr); ASSERT(Self != nullptr);
// Get the textual IP address and port number out of a_Addr:
char IPAddress[128];
evutil_inet_ntop(a_Addr->sa_family, a_Addr->sa_data, IPAddress, ARRAYCOUNT(IPAddress));
UInt16 Port = 0;
switch (a_Addr->sa_family)
{
case AF_INET:
{
sockaddr_in * sin = reinterpret_cast<sockaddr_in *>(a_Addr);
Port = ntohs(sin->sin_port);
break;
}
case AF_INET6:
{
sockaddr_in6 * sin6 = reinterpret_cast<sockaddr_in6 *>(a_Addr);
Port = ntohs(sin6->sin6_port);
break;
}
}
// Call the OnIncomingConnection callback to get the link callbacks to use:
cTCPLink::cCallbacksPtr LinkCallbacks = Self->m_ListenCallbacks->OnIncomingConnection(IPAddress, Port);
if (LinkCallbacks == nullptr)
{
// Drop the connection:
evutil_closesocket(a_Socket);
return;
}
// Create a new cTCPLink for the incoming connection: // Create a new cTCPLink for the incoming connection:
cTCPLinkImplPtr Link = std::make_shared<cTCPLinkImpl>(a_Socket, Self->m_LinkCallbacks, Self, a_Addr, static_cast<socklen_t>(a_Len)); cTCPLinkImplPtr Link = std::make_shared<cTCPLinkImpl>(a_Socket, LinkCallbacks, Self, a_Addr, static_cast<socklen_t>(a_Len));
{ {
cCSLock Lock(Self->m_CS); cCSLock Lock(Self->m_CS);
Self->m_Connections.push_back(Link); Self->m_Connections.push_back(Link);
@ -289,12 +313,11 @@ void cServerHandleImpl::RemoveLink(const cTCPLinkImpl * a_Link)
// cNetwork API: // cNetwork API:
cServerHandlePtr cNetwork::Listen( cServerHandlePtr cNetwork::Listen(
const UInt16 a_Port, UInt16 a_Port,
cNetwork::cListenCallbacksPtr a_ListenCallbacks, cNetwork::cListenCallbacksPtr a_ListenCallbacks
cTCPLink::cCallbacksPtr a_LinkCallbacks
) )
{ {
return cServerHandleImpl::Listen(a_Port, a_ListenCallbacks, a_LinkCallbacks); return cServerHandleImpl::Listen(a_Port, a_ListenCallbacks);
} }

View File

@ -46,8 +46,7 @@ public:
Always returns a server instance; in the event of a failure, the instance holds the error details. Use IsListening() to query success. */ Always returns a server instance; in the event of a failure, the instance holds the error details. Use IsListening() to query success. */
static cServerHandleImplPtr Listen( static cServerHandleImplPtr Listen(
UInt16 a_Port, UInt16 a_Port,
cNetwork::cListenCallbacksPtr a_ListenCallbacks, cNetwork::cListenCallbacksPtr a_ListenCallbacks
cTCPLink::cCallbacksPtr a_LinkCallbacks
); );
// cServerHandle overrides: // cServerHandle overrides:
@ -58,9 +57,6 @@ protected:
/** The callbacks used to notify about incoming connections. */ /** The callbacks used to notify about incoming connections. */
cNetwork::cListenCallbacksPtr m_ListenCallbacks; cNetwork::cListenCallbacksPtr m_ListenCallbacks;
/** The callbacks used to create new cTCPLink instances for incoming connections. */
cTCPLink::cCallbacksPtr m_LinkCallbacks;
/** The LibEvent handle representing the main listening socket. */ /** The LibEvent handle representing the main listening socket. */
evconnlistener * m_ConnListener; evconnlistener * m_ConnListener;
@ -86,10 +82,7 @@ protected:
/** Creates a new instance with the specified callbacks. /** Creates a new instance with the specified callbacks.
Initializes the internals, but doesn't start listening yet. */ Initializes the internals, but doesn't start listening yet. */
cServerHandleImpl( cServerHandleImpl(cNetwork::cListenCallbacksPtr a_ListenCallbacks);
cNetwork::cListenCallbacksPtr a_ListenCallbacks,
cTCPLink::cCallbacksPtr a_LinkCallbacks
);
/** Starts listening on the specified port. /** Starts listening on the specified port.
Returns true if successful, false on failure. On failure, sets m_ErrorCode and m_ErrorMsg. */ Returns true if successful, false on failure. On failure, sets m_ErrorCode and m_ErrorMsg. */

View File

@ -304,7 +304,7 @@ void cTCPLinkImpl::UpdateRemoteAddress(void)
bool cNetwork::Connect( bool cNetwork::Connect(
const AString & a_Host, const AString & a_Host,
const UInt16 a_Port, UInt16 a_Port,
cNetwork::cConnectCallbacksPtr a_ConnectCallbacks, cNetwork::cConnectCallbacksPtr a_ConnectCallbacks,
cTCPLink::cCallbacksPtr a_LinkCallbacks cTCPLink::cCallbacksPtr a_LinkCallbacks
) )

View File

@ -12,27 +12,6 @@
class cEchoServerCallbacks:
public cNetwork::cListenCallbacks
{
virtual void OnAccepted(cTCPLink & a_Link) override
{
LOGD("New client accepted (%s:%d), sending welcome message.", a_Link.GetRemoteIP().c_str(), a_Link.GetRemotePort());
// Send a welcome message to each connecting client:
a_Link.Send("Welcome to the simple echo server.\r\n");
LOGD("Welcome message queued.");
}
virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override
{
LOGWARNING("An error occured while listening for connections: %d (%s).", a_ErrorCode, a_ErrorMsg.c_str());
}
};
/** cTCPLink callbacks that echo everything they receive back to the remote peer. */ /** cTCPLink callbacks that echo everything they receive back to the remote peer. */
class cEchoLinkCallbacks: class cEchoLinkCallbacks:
public cTCPLink::cCallbacks public cTCPLink::cCallbacks
@ -70,10 +49,37 @@ class cEchoLinkCallbacks:
class cEchoServerCallbacks:
public cNetwork::cListenCallbacks
{
virtual cTCPLink::cCallbacksPtr OnIncomingConnection(const AString & a_RemoteIPAddress, UInt16 a_RemotePort)
{
LOGD("New incoming connection(%s:%d).", a_RemoteIPAddress.c_str(), a_RemotePort);
return std::make_shared<cEchoLinkCallbacks>();
}
virtual void OnAccepted(cTCPLink & a_Link) override
{
LOGD("New client accepted (%s:%d), sending welcome message.", a_Link.GetRemoteIP().c_str(), a_Link.GetRemotePort());
// Send a welcome message to each connecting client:
a_Link.Send("Welcome to the simple echo server.\r\n");
LOGD("Welcome message queued.");
}
virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override
{
LOGWARNING("An error occured while listening for connections: %d (%s).", a_ErrorCode, a_ErrorMsg.c_str());
}
};
int main() int main()
{ {
LOGD("EchoServer: starting up"); LOGD("EchoServer: starting up");
cServerHandlePtr Server = cNetwork::Listen(9876, std::make_shared<cEchoServerCallbacks>(), std::make_shared<cEchoLinkCallbacks>()); cServerHandlePtr Server = cNetwork::Listen(9876, std::make_shared<cEchoServerCallbacks>());
if (!Server->IsListening()) if (!Server->IsListening())
{ {
LOGWARNING("Cannot listen on port 9876"); LOGWARNING("Cannot listen on port 9876");