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:
parent
64855ed340
commit
5b4c5cf2be
|
@ -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
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
|
@ -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");
|
||||||
|
|
Loading…
Reference in New Issue
Block a user