1
0

cNetwork: Implemented link address getting.

This commit is contained in:
Mattes D 2015-01-12 10:17:11 +01:00
parent 28e97d5468
commit a2aa37bdc5
2 changed files with 121 additions and 61 deletions

View File

@ -62,6 +62,13 @@ typedef std::vector<cIPLookupPtr> cIPLookupPtrs;
// fwd:
class cServerHandleImpl;
/** Implements the cTCPLink details so that it can represent the single connection between two endpoints. */
class cTCPLinkImpl:
public cTCPLink
@ -76,8 +83,9 @@ public:
cTCPLinkImpl(const cCallbacksPtr a_LinkCallbacks);
/** Creates a new link based on the given socket.
Used for connections accepted in a server using cNetwork::Listen(). */
cTCPLinkImpl(evutil_socket_t a_Socket, cCallbacksPtr a_LinkCallbacks, cServerHandleImpl * a_Server);
Used for connections accepted in a server using cNetwork::Listen().
a_Address and a_AddrLen describe the remote peer that has connected. */
cTCPLinkImpl(evutil_socket_t a_Socket, cCallbacksPtr a_LinkCallbacks, cServerHandleImpl * a_Server, const sockaddr * a_Address, int a_AddrLen);
/** Queues a connection request to the specified host.
a_ConnectCallbacks must be valid.
@ -86,10 +94,10 @@ public:
// cTCPLink overrides:
virtual bool Send(const void * a_Data, size_t a_Length) override;
virtual AString GetLocalIP(void) const override;
virtual UInt16 GetLocalPort(void) const override;
virtual AString GetRemoteIP(void) const override;
virtual UInt16 GetRemotePort(void) const override;
virtual AString GetLocalIP(void) const override { return m_LocalIP; }
virtual UInt16 GetLocalPort(void) const override { return m_LocalPort; }
virtual AString GetRemoteIP(void) const override { return m_RemoteIP; }
virtual UInt16 GetRemotePort(void) const override { return m_RemotePort; }
virtual void Close(void) override;
virtual void Drop(void) override;
@ -106,12 +114,33 @@ protected:
Only valid for incoming connections, NULL for outgoing connections. */
cServerHandleImpl * m_Server;
/** The IP address of the local endpoint. Valid only after the socket has been connected. */
AString m_LocalIP;
/** The port of the local endpoint. Valid only after the socket has been connected. */
UInt16 m_LocalPort;
/** The IP address of the remote endpoint. Valid only after the socket has been connected. */
AString m_RemoteIP;
/** The port of the remote endpoint. Valid only after the socket has been connected. */
UInt16 m_RemotePort;
/** Callback that LibEvent calls when there's data available from the remote peer. */
static void ReadCallback(bufferevent * a_BufferEvent, void * a_Self);
/** Callback that LibEvent calls when there's a non-data-related event on the socket. */
static void EventCallback(bufferevent * a_BufferEvent, short a_What, void * a_Self);
/** Sets a_IP and a_Port to values read from a_Address, based on the correct address family. */
static void UpdateAddress(const sockaddr * a_Address, int a_AddrLen, AString & a_IP, UInt16 & a_Port);
/** Updates m_LocalIP and m_LocalPort based on the metadata read from the socket. */
void UpdateLocalAddress(void);
/** Updates m_RemoteIP and m_RemotePort based on the metadata read from the socket. */
void UpdateRemoteAddress(void);
};
typedef SharedPtr<cTCPLinkImpl> cTCPLinkImplPtr;
typedef std::vector<cTCPLinkImplPtr> cTCPLinkImplPtrs;
@ -337,13 +366,13 @@ void cHostnameLookup::Callback(int a_ErrCode, evutil_addrinfo * a_Addr, void * a
}
default:
{
// Unknown address family, handle as error
continue;
// Unknown address family, handle as if this entry wasn't received
continue; // for (a_Addr)
}
}
Self->m_Callbacks->OnNameResolved(Self->m_Hostname, IP);
HasResolved = true;
}
} // for (a_Addr)
// If only unsupported families were reported, call the Error handler:
if (!HasResolved)
@ -378,11 +407,21 @@ cIPLookup::cIPLookup(const AString & a_IP, cNetwork::cResolveNameCallbacksPtr a_
{
sockaddr_in * sa4 = reinterpret_cast<sockaddr_in *>(&sa);
evdns_base_resolve_reverse(cNetworkSingleton::Get().m_DNSBase, &(sa4->sin_addr), 0, Callback, this);
break;
}
case AF_INET6:
{
sockaddr_in6 * sa6 = reinterpret_cast<sockaddr_in6 *>(&sa);
evdns_base_resolve_reverse_ipv6(cNetworkSingleton::Get().m_DNSBase, &(sa6->sin6_addr), 0, Callback, this);
break;
}
}
default:
{
LOGWARNING("%s: Unknown address family: %d", __FUNCTION__, sa.ss_family);
ASSERT(!"Unknown address family");
break;
}
} // switch (address family)
}
@ -429,11 +468,13 @@ cTCPLinkImpl::cTCPLinkImpl(cTCPLink::cCallbacksPtr a_LinkCallbacks):
cTCPLinkImpl::cTCPLinkImpl(evutil_socket_t a_Socket, cTCPLink::cCallbacksPtr a_LinkCallbacks, cServerHandleImpl * a_Server):
cTCPLinkImpl::cTCPLinkImpl(evutil_socket_t a_Socket, cTCPLink::cCallbacksPtr a_LinkCallbacks, cServerHandleImpl * a_Server, const sockaddr * a_Address, int a_AddrLen):
super(a_LinkCallbacks),
m_BufferEvent(bufferevent_socket_new(cNetworkSingleton::Get().m_EventBase, a_Socket, BEV_OPT_CLOSE_ON_FREE)),
m_Server(a_Server)
{
UpdateLocalAddress();
UpdateAddress(a_Address, a_AddrLen, m_RemoteIP, m_RemotePort);
bufferevent_setcb(m_BufferEvent, ReadCallback, nullptr, EventCallback, this);
bufferevent_enable(m_BufferEvent, EV_READ | EV_WRITE);
}
@ -499,50 +540,6 @@ bool cTCPLinkImpl::Send(const void * a_Data, size_t a_Length)
AString cTCPLinkImpl::GetLocalIP(void) const
{
// TODO
ASSERT(!"cTCPLinkImpl::GetLocalIP: Not implemented yet");
return "";
}
UInt16 cTCPLinkImpl::GetLocalPort(void) const
{
// TODO
ASSERT(!"cTCPLinkImpl::GetLocalPort(): Not implemented yet");
return 0;
}
AString cTCPLinkImpl::GetRemoteIP(void) const
{
// TODO
ASSERT(!"cTCPLinkImpl::GetRemoteIP(): Not implemented yet");
return "";
}
UInt16 cTCPLinkImpl::GetRemotePort(void) const
{
// TODO
ASSERT(!"cTCPLinkImpl::GetRemotePort(): Not implemented yet");
return 0;
}
void cTCPLinkImpl::Close(void)
{
// TODO
@ -621,6 +618,8 @@ void cTCPLinkImpl::EventCallback(bufferevent * a_BufferEvent, short a_What, void
Self->m_ConnectCallbacks.reset();
return;
}
Self->UpdateLocalAddress();
Self->UpdateRemoteAddress();
}
// If the connection has been closed, call the link callback and remove the connection:
@ -647,6 +646,64 @@ void cTCPLinkImpl::EventCallback(bufferevent * a_BufferEvent, short a_What, void
void cTCPLinkImpl::UpdateAddress(const sockaddr * a_Address, int a_AddrLen, AString & a_IP, UInt16 & a_Port)
{
char IP[128];
switch (a_Address->sa_family)
{
case AF_INET: // IPv4:
{
const sockaddr_in * sin = reinterpret_cast<const sockaddr_in *>(a_Address);
evutil_inet_ntop(AF_INET, &(sin->sin_addr), IP, sizeof(IP));
a_Port = ntohs(sin->sin_port);
break;
}
case AF_INET6: // IPv6
{
const sockaddr_in6 * sin = reinterpret_cast<const sockaddr_in6 *>(a_Address);
evutil_inet_ntop(AF_INET6, &(sin->sin6_addr), IP, sizeof(IP));
a_Port = ntohs(sin->sin6_port);
break;
}
default:
{
LOGWARNING("%s: Unknown socket address family: %d", __FUNCTION__, a_Address->sa_family);
ASSERT(!"Unknown socket address family");
break;
}
}
a_IP.assign(IP);
}
void cTCPLinkImpl::UpdateLocalAddress(void)
{
sockaddr_storage sa;
int salen = static_cast<int>(sizeof(sa));
getsockname(bufferevent_getfd(m_BufferEvent), reinterpret_cast<sockaddr *>(&sa), &salen);
UpdateAddress(reinterpret_cast<const sockaddr *>(&sa), salen, m_LocalIP, m_LocalPort);
}
void cTCPLinkImpl::UpdateRemoteAddress(void)
{
sockaddr_storage sa;
int salen = static_cast<int>(sizeof(sa));
getpeername(bufferevent_getfd(m_BufferEvent), reinterpret_cast<sockaddr *>(&sa), &salen);
UpdateAddress(reinterpret_cast<const sockaddr *>(&sa), salen, m_LocalIP, m_LocalPort);
}
////////////////////////////////////////////////////////////////////////////////
// cServerHandleImpl:
@ -786,7 +843,7 @@ void cServerHandleImpl::Callback(evconnlistener * a_Listener, evutil_socket_t a_
ASSERT(Self != nullptr);
// Create a new cTCPLink for the incoming connection:
cTCPLinkImplPtr Link = std::make_shared<cTCPLinkImpl>(a_Socket, Self->m_LinkCallbacks, Self);
cTCPLinkImplPtr Link = std::make_shared<cTCPLinkImpl>(a_Socket, Self->m_LinkCallbacks, Self, a_Addr, a_Len);
Self->m_Connections.push_back(Link);
// Call the OnAccepted callback:
@ -933,6 +990,9 @@ cNetworkSingleton & cNetworkSingleton::Get(void)
}
bool cNetworkSingleton::Connect(
const AString & a_Host,
const UInt16 a_Port,
@ -947,7 +1007,7 @@ bool cNetworkSingleton::Connect(
// Queue the connection:
if (!ConnRequest->Connect(a_Host, a_Port, a_ConnectCallbacks))
{
// TODO: m_Connections.remove(ConnRequest);
RemoveLink(ConnRequest.get());
return false;
}

View File

@ -17,7 +17,7 @@ class cEchoServerCallbacks:
{
virtual void OnAccepted(cTCPLink & a_Link) override
{
LOGD("New client accepted, sending welcome message.");
LOGD("New client accepted (%s:%p), 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.");
@ -35,19 +35,19 @@ class cEchoLinkCallbacks:
virtual void OnReceivedData(cTCPLink & a_Link, const char * a_Data, size_t a_Size) override
{
// Echo the incoming data back to outgoing data:
LOGD("%p: Data received (%u bytes), echoing back.", &a_Link, static_cast<unsigned>(a_Size));
LOGD("%p (%s:%d): Data received (%u bytes), echoing back.", &a_Link, a_Link.GetRemoteIP().c_str(), a_Link.GetRemotePort(), static_cast<unsigned>(a_Size));
a_Link.Send(a_Data, a_Size);
LOGD("Echo queued");
}
virtual void OnRemoteClosed(cTCPLink & a_Link) override
{
LOGD("%p: Remote has closed the connection.", &a_Link);
LOGD("%p (%s:%d): Remote has closed the connection.", &a_Link, a_Link.GetRemoteIP().c_str(), a_Link.GetRemotePort());
}
virtual void OnError(cTCPLink & a_Link, int a_ErrorCode) override
{
LOGD("%p: Error %d in the cEchoLinkCallbacks.", &a_Link, a_ErrorCode);
LOGD("%p (%s:%d): Error %d in the cEchoLinkCallbacks.", &a_Link, a_Link.GetRemoteIP().c_str(), a_Link.GetRemotePort(), a_ErrorCode);
}
};