summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattes D <github@xoft.cz>2015-01-12 10:17:11 +0100
committerMattes D <github@xoft.cz>2015-01-22 20:12:47 +0100
commita2aa37bdc505c72edd5c9d41bac6e7679cea13c3 (patch)
treec6dff3370af92807b84808c438edd7eb406812f2
parentcNetwork: Implemented basic server functionality. (diff)
downloadcuberite-a2aa37bdc505c72edd5c9d41bac6e7679cea13c3.tar
cuberite-a2aa37bdc505c72edd5c9d41bac6e7679cea13c3.tar.gz
cuberite-a2aa37bdc505c72edd5c9d41bac6e7679cea13c3.tar.bz2
cuberite-a2aa37bdc505c72edd5c9d41bac6e7679cea13c3.tar.lz
cuberite-a2aa37bdc505c72edd5c9d41bac6e7679cea13c3.tar.xz
cuberite-a2aa37bdc505c72edd5c9d41bac6e7679cea13c3.tar.zst
cuberite-a2aa37bdc505c72edd5c9d41bac6e7679cea13c3.zip
-rw-r--r--src/OSSupport/Network.cpp174
-rw-r--r--tests/Network/EchoServer.cpp8
2 files changed, 121 insertions, 61 deletions
diff --git a/src/OSSupport/Network.cpp b/src/OSSupport/Network.cpp
index 399bffe50..2c9b2ef37 100644
--- a/src/OSSupport/Network.cpp
+++ b/src/OSSupport/Network.cpp
@@ -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;
}
diff --git a/tests/Network/EchoServer.cpp b/tests/Network/EchoServer.cpp
index e6571a57f..2316d1177 100644
--- a/tests/Network/EchoServer.cpp
+++ b/tests/Network/EchoServer.cpp
@@ -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);
}
};