Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LibEvent-based socket API #1701

Merged
merged 34 commits into from Jan 24, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a8a7488
Added the libevent library.
madmaxoft Jan 5, 2015
6f5e267
Implemented LibEvent-based client connections.
madmaxoft Jan 9, 2015
b8b3409
cNetwork: Linux compilation fix.
madmaxoft Jan 9, 2015
a9b8a53
Extracted Google connection test
worktycho Jan 9, 2015
bef957e
Added newline to logged messages in the tests.
madmaxoft Jan 11, 2015
c733525
Excluded PolarSSL tests from MCS tests.
madmaxoft Jan 11, 2015
fde44cb
cNetwork: Implemented HostnameToIP lookups.
madmaxoft Jan 11, 2015
251c969
cNetwork: Implemented IP-to-hostname lookup.
madmaxoft Jan 11, 2015
28e97d5
cNetwork: Implemented basic server functionality.
madmaxoft Jan 12, 2015
a2aa37b
cNetwork: Implemented link address getting.
madmaxoft Jan 12, 2015
9ffca12
cNetwork: Fixed Linux compilation.
madmaxoft Jan 12, 2015
d8ac99a
cNetwork: Implemented connection shutdown and close.
madmaxoft Jan 12, 2015
ddb1818
cNetwork: Added multithreading protection.
madmaxoft Jan 12, 2015
235b8f1
cNetwork: Added error logging to server socket creation.
madmaxoft Jan 12, 2015
19121d2
Wrap debug variable in ifdef
worktycho Jan 12, 2015
b592062
cNetwork: Fixed compilation.
madmaxoft Jan 13, 2015
5cc8d82
cNetwork: Fixed compilation in out-of-source builds.
madmaxoft Jan 13, 2015
6f29cfe
cNetwork: Cosmetics.
madmaxoft Jan 13, 2015
728a624
cNetwork: Refactored cTCPLinkImpl::Connect into a factory.
madmaxoft Jan 14, 2015
4647e6a
cNetwork: Removed unneeded dependency.
madmaxoft Jan 14, 2015
646e636
cNetwork: Rewritten server listen into a factory method.
madmaxoft Jan 15, 2015
7cddb62
cNetwork: Added an OnError callback for listening servers.
madmaxoft Jan 15, 2015
60807ad
cNetwork: Handle WSA initialization failures.
madmaxoft Jan 15, 2015
ae29a82
cNetwork: Fixed WSAStartup()-not-called error in Listen().
madmaxoft Jan 16, 2015
d3076a3
cNetwork: Split cNetworkSingleton to a separate file.
madmaxoft Jan 17, 2015
1e5aeda
cNetwork: Fixed WinXP dualstack listening.
madmaxoft Jan 17, 2015
c0cb787
cNetwork: Split the main cpp file into several files.
madmaxoft Jan 18, 2015
d468246
cNetwork: Fixed race conditions with lookups; proper shutdown.
madmaxoft Jan 18, 2015
0025340
cTCPLinkImpl: Fixed type conversion warning.
madmaxoft Jan 18, 2015
64855ed
cNetwork: Added error message to error callbacks.
madmaxoft Jan 20, 2015
5b4c5cf
cNetwork: Changed listening API.
madmaxoft Jan 21, 2015
dbf7f13
cNetwork: Added link creation callback.
madmaxoft Jan 22, 2015
9014bdf
cNetwork: Renamed callback to OnConnected()
madmaxoft Jan 22, 2015
10cfa61
cNetwork: Added self pointers to keep objects alive for callbacks.
madmaxoft Jan 23, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Expand Up @@ -25,3 +25,6 @@
[submodule "lib/SQLiteCpp"]
path = lib/SQLiteCpp
url = https://github.com/mc-server/SQLiteCpp.git
[submodule "lib/libevent"]
path = lib/libevent
url = https://github.com/mc-server/libevent.git
17 changes: 16 additions & 1 deletion CMakeLists.txt
Expand Up @@ -95,13 +95,23 @@ set(SQLITECPP_BUILD_EXAMPLES OFF CACHE BOOL "Build examples."
set(SQLITECPP_BUILD_TESTS OFF CACHE BOOL "Build and run tests." FORCE)
set(SQLITECPP_INTERNAL_SQLITE OFF CACHE BOOL "Add the internal SQLite3 source to the project." FORCE)

# Set options for LibEvent, disable all their tests and benchmarks:
set(EVENT__DISABLE_OPENSSL YES CACHE BOOL "Disable OpenSSL in LibEvent" FORCE)
set(EVENT__DISABLE_BENCHMARK YES CACHE BOOL "Disable LibEvent benchmarks" FORCE)
set(EVENT__DISABLE_TESTS YES CACHE BOOL "Disable LibEvent tests" FORCE)
set(EVENT__DISABLE_REGRESS YES CACHE BOOL "Disable LibEvent regression tests" FORCE)
set(EVENT__DISABLE_SAMPLES YES CACHE BOOL "Disable LibEvent samples" FORCE)

# Check that the libraries are present:
if (NOT EXISTS ${CMAKE_SOURCE_DIR}/lib/SQLiteCpp/CMakeLists.txt)
message(FATAL_ERROR "SQLiteCpp is missing in folder lib/SQLiteCpp. Have you initialized the submodules / downloaded the extra libraries?")
endif()
if (NOT EXISTS ${CMAKE_SOURCE_DIR}/lib/polarssl/CMakeLists.txt)
message(FATAL_ERROR "PolarSSL is missing in folder lib/polarssl. Have you initialized the submodules / downloaded the extra libraries?")
endif()
if (NOT EXISTS ${CMAKE_SOURCE_DIR}/lib/libevent/CMakeLists.txt)
message(FATAL_ERROR "LibEvent is missing in folder lib/libevent. Have you initialized and updated the submodules / downloaded the extra libraries?")
endif()

# Include all the libraries:
add_subdirectory(lib/jsoncpp/)
Expand All @@ -112,27 +122,32 @@ add_subdirectory(lib/sqlite/)
add_subdirectory(lib/SQLiteCpp/)
add_subdirectory(lib/expat/)
add_subdirectory(lib/luaexpat/)
add_subdirectory(lib/libevent/)

# Add proper include directories so that SQLiteCpp can find SQLite3:
get_property(SQLITECPP_INCLUDES DIRECTORY "lib/SQLiteCpp/" PROPERTY INCLUDE_DIRECTORIES)
set(SQLITECPP_INCLUDES "${SQLITECPP_INCLUDES}" "${CMAKE_CURRENT_SOURCE_DIR}/lib/sqlite/")
set_property(DIRECTORY lib/SQLiteCpp/ PROPERTY INCLUDE_DIRECTORIES "${SQLITECPP_INCLUDES}")
set_property(TARGET SQLiteCpp PROPERTY INCLUDE_DIRECTORIES "${SQLITECPP_INCLUDES}")

# Add proper includes for LibEvent's event-config.h header:
include_directories(SYSTEM ${LIBEVENT_INCLUDE_DIRS})

if (WIN32)
add_subdirectory(lib/luaproxy/)
endif()


# We use EXCLUDE_FROM_ALL so that only the explicit dependencies are used
# (PolarSSL also has test and example programs in their CMakeLists.txt, we don't want those)
include(lib/polarssl.cmake)
include(lib/polarssl.cmake EXCLUDE_FROM_ALL)

set_exe_flags()

add_subdirectory (src)

if(${SELF_TEST})
message("Tests enabled")
enable_testing()
add_subdirectory (tests)
endif()
Expand Down
1 change: 1 addition & 0 deletions lib/libevent
Submodule libevent added at 0b49ae
3 changes: 2 additions & 1 deletion src/CMakeLists.txt
Expand Up @@ -5,6 +5,7 @@ project (MCServer)
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/")
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/jsoncpp/include")
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/polarssl/include")
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/libevent/include")

set(FOLDERS
OSSupport HTTPServer Items Blocks Protocol Generating PolarSSL++ Bindings
Expand Down Expand Up @@ -323,4 +324,4 @@ endif ()
if (WIN32)
target_link_libraries(${EXECUTABLE} expat tolualib ws2_32.lib Psapi.lib)
endif()
target_link_libraries(${EXECUTABLE} luaexpat jsoncpp polarssl zlib sqlite lua SQLiteCpp)
target_link_libraries(${EXECUTABLE} luaexpat jsoncpp polarssl zlib sqlite lua SQLiteCpp event_core event_extra)
26 changes: 20 additions & 6 deletions src/Globals.h
Expand Up @@ -268,33 +268,47 @@ template class SizeChecker<UInt16, 2>;
#include "OSSupport/StackTrace.h"
#else
// Logging functions
void inline LOGERROR(const char* a_Format, ...) FORMATSTRING(1, 2);
void inline LOGERROR(const char * a_Format, ...) FORMATSTRING(1, 2);

void inline LOGERROR(const char* a_Format, ...)
void inline LOGERROR(const char * a_Format, ...)
{
va_list argList;
va_start(argList, a_Format);
vprintf(a_Format, argList);
putchar('\n');
va_end(argList);
}

void inline LOGWARNING(const char* a_Format, ...) FORMATSTRING(1, 2);
void inline LOGWARNING(const char * a_Format, ...) FORMATSTRING(1, 2);

void inline LOGWARNING(const char* a_Format, ...)
void inline LOGWARNING(const char * a_Format, ...)
{
va_list argList;
va_start(argList, a_Format);
vprintf(a_Format, argList);
putchar('\n');
va_end(argList);
}

void inline LOGD(const char* a_Format, ...) FORMATSTRING(1, 2);
void inline LOGD(const char * a_Format, ...) FORMATSTRING(1, 2);

void inline LOGD(const char* a_Format, ...)
void inline LOGD(const char * a_Format, ...)
{
va_list argList;
va_start(argList, a_Format);
vprintf(a_Format, argList);
putchar('\n');
va_end(argList);
}

void inline LOG(const char * a_Format, ...) FORMATSTRING(1, 2);

void inline LOG(const char * a_Format, ...)
{
va_list argList;
va_start(argList, a_Format);
vprintf(a_Format, argList);
putchar('\n');
va_end(argList);
}

Expand Down
11 changes: 11 additions & 0 deletions src/OSSupport/CMakeLists.txt
Expand Up @@ -10,12 +10,17 @@ SET (SRCS
Event.cpp
File.cpp
GZipFile.cpp
HostnameLookup.cpp
IPLookup.cpp
IsThread.cpp
ListenThread.cpp
NetworkSingleton.cpp
Semaphore.cpp
ServerHandleImpl.cpp
Socket.cpp
SocketThreads.cpp
StackTrace.cpp
TCPLinkImpl.cpp
)

SET (HDRS
Expand All @@ -24,13 +29,19 @@ SET (HDRS
Event.h
File.h
GZipFile.h
HostnameLookup.h
IPLookup.h
IsThread.h
ListenThread.h
Network.h
NetworkSingleton.h
Queue.h
Semaphore.h
ServerHandleImpl.h
Socket.h
SocketThreads.h
StackTrace.h
TCPLinkImpl.h
)

if(NOT MSVC)
Expand Down
1 change: 1 addition & 0 deletions src/OSSupport/CriticalSection.cpp
@@ -1,5 +1,6 @@

#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "CriticalSection.h"



Expand Down
124 changes: 124 additions & 0 deletions src/OSSupport/HostnameLookup.cpp
@@ -0,0 +1,124 @@

// HostnameLookup.cpp

// Implements the cHostnameLookup class representing an in-progress hostname-to-IP lookup

#include "Globals.h"
#include "HostnameLookup.h"
#include <event2/dns.h>
#include "NetworkSingleton.h"





////////////////////////////////////////////////////////////////////////////////
// cHostnameLookup:

cHostnameLookup::cHostnameLookup(cNetwork::cResolveNameCallbacksPtr a_Callbacks):
m_Callbacks(a_Callbacks)
{
}





void cHostnameLookup::Lookup(const AString & a_Hostname)
{
// Store the hostname for the callback:
m_Hostname = a_Hostname;

// Start the lookup:
// Note that we don't have to store the LibEvent lookup handle, LibEvent will free it on its own.
evutil_addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_protocol = IPPROTO_TCP;
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF_UNSPEC;
hints.ai_flags = EVUTIL_AI_CANONNAME;
evdns_getaddrinfo(cNetworkSingleton::Get().GetDNSBase(), a_Hostname.c_str(), nullptr, &hints, Callback, this);
}





void cHostnameLookup::Callback(int a_ErrCode, evutil_addrinfo * a_Addr, void * a_Self)
{
// Get the Self class:
cHostnameLookup * Self = reinterpret_cast<cHostnameLookup *>(a_Self);
ASSERT(Self != nullptr);

// If an error has occurred, notify the error callback:
if (a_ErrCode != 0)
{
Self->m_Callbacks->OnError(a_ErrCode, evutil_socket_error_to_string(a_ErrCode));
cNetworkSingleton::Get().RemoveHostnameLookup(Self);
return;
}

// Call the success handler for each entry received:
bool HasResolved = false;
evutil_addrinfo * OrigAddr = a_Addr;
for (;a_Addr != nullptr; a_Addr = a_Addr->ai_next)
{
char IP[128];
switch (a_Addr->ai_family)
{
case AF_INET: // IPv4
{
sockaddr_in * sin = reinterpret_cast<sockaddr_in *>(a_Addr->ai_addr);
evutil_inet_ntop(AF_INET, &(sin->sin_addr), IP, sizeof(IP));
break;
}
case AF_INET6: // IPv6
{
sockaddr_in6 * sin = reinterpret_cast<sockaddr_in6 *>(a_Addr->ai_addr);
evutil_inet_ntop(AF_INET6, &(sin->sin6_addr), IP, sizeof(IP));
break;
}
default:
{
// 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)
{
Self->m_Callbacks->OnError(DNS_ERR_NODATA, "The name does not resolve to any known address.");
}
else
{
Self->m_Callbacks->OnFinished();
}
evutil_freeaddrinfo(OrigAddr);
cNetworkSingleton::Get().RemoveHostnameLookup(Self);
}





////////////////////////////////////////////////////////////////////////////////
// cNetwork API:

bool cNetwork::HostnameToIP(
const AString & a_Hostname,
cNetwork::cResolveNameCallbacksPtr a_Callbacks
)
{
auto Lookup = std::make_shared<cHostnameLookup>(a_Callbacks);
cNetworkSingleton::Get().AddHostnameLookup(Lookup);
Lookup->Lookup(a_Hostname);
return true;
}




47 changes: 47 additions & 0 deletions src/OSSupport/HostnameLookup.h
@@ -0,0 +1,47 @@

// HostnameLookup.h

// Declares the cHostnameLookup class representing an in-progress hostname-to-IP lookup

// This is an internal header, no-one outside OSSupport should need to include it; use Network.h instead





#pragma once

#include "Network.h"
#include <event2/util.h>





/** Holds information about an in-progress Hostname-to-IP lookup. */
class cHostnameLookup
{
public:
/** Creates the lookup object. Doesn't start the lookup yet. */
cHostnameLookup(cNetwork::cResolveNameCallbacksPtr a_Callbacks);

/** Starts the lookup. */
void Lookup(const AString & a_Hostname);

protected:

/** The callbacks to call for resolved names / errors. */
cNetwork::cResolveNameCallbacksPtr m_Callbacks;

/** The hostname that was queried (needed for the callbacks). */
AString m_Hostname;

static void Callback(int a_ErrCode, struct evutil_addrinfo * a_Addr, void * a_Self);
};
typedef SharedPtr<cHostnameLookup> cHostnameLookupPtr;
typedef std::vector<cHostnameLookupPtr> cHostnameLookupPtrs;