(Discord) Cleanups

This commit is contained in:
twinaphex 2019-08-20 21:11:48 +02:00
parent a363af7796
commit 1917b2235e
5 changed files with 146 additions and 301 deletions

View File

@ -3,19 +3,7 @@
// clang-format off // clang-format off
#if defined(DISCORD_DYNAMIC_LIB)
# if defined(_WIN32)
# if defined(DISCORD_BUILDING_SDK)
# define DISCORD_EXPORT __declspec(dllexport)
# else
# define DISCORD_EXPORT __declspec(dllimport)
# endif
# else
# define DISCORD_EXPORT __attribute__((visibility("default")))
# endif
#else
# define DISCORD_EXPORT # define DISCORD_EXPORT
#endif
// clang-format on // clang-format on

View File

@ -1,142 +0,0 @@
include_directories(${PROJECT_SOURCE_DIR}/include)
option(ENABLE_IO_THREAD "Start up a separate I/O thread, otherwise I'd need to call an update function" ON)
option(USE_STATIC_CRT "Use /MT[d] for dynamic library" OFF)
option(WARNINGS_AS_ERRORS "When enabled, compiles with `-Werror` (on *nix platforms)." OFF)
set(CMAKE_CXX_STANDARD 14)
set(BASE_RPC_SRC
${PROJECT_SOURCE_DIR}/include/discord_rpc.h
discord_rpc.cpp
${PROJECT_SOURCE_DIR}/include/discord_register.h
rpc_connection.h
rpc_connection.cpp
serialization.h
serialization.cpp
connection.h
backoff.h
msg_queue.h
)
if (${BUILD_SHARED_LIBS})
if(WIN32)
set(BASE_RPC_SRC ${BASE_RPC_SRC} dllmain.cpp)
endif(WIN32)
endif(${BUILD_SHARED_LIBS})
if(WIN32)
add_definitions(-DDISCORD_WINDOWS)
set(BASE_RPC_SRC ${BASE_RPC_SRC} connection_win.cpp discord_register_win.cpp)
add_library(discord-rpc ${BASE_RPC_SRC})
if (MSVC)
if(USE_STATIC_CRT)
foreach(CompilerFlag
CMAKE_CXX_FLAGS
CMAKE_CXX_FLAGS_DEBUG
CMAKE_CXX_FLAGS_RELEASE
CMAKE_C_FLAGS
CMAKE_C_FLAGS_DEBUG
CMAKE_C_FLAGS_RELEASE)
string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
endforeach()
endif(USE_STATIC_CRT)
target_compile_options(discord-rpc PRIVATE /EHsc
/Wall
/wd4100 # unreferenced formal parameter
/wd4514 # unreferenced inline
/wd4625 # copy constructor deleted
/wd5026 # move constructor deleted
/wd4626 # move assignment operator deleted
/wd4668 # not defined preprocessor macro
/wd4710 # function not inlined
/wd4711 # function was inlined
/wd4820 # structure padding
/wd4946 # reinterpret_cast used between related classes
/wd5027 # move assignment operator was implicitly defined as deleted
)
endif(MSVC)
target_link_libraries(discord-rpc PRIVATE psapi advapi32)
endif(WIN32)
if(UNIX)
set(BASE_RPC_SRC ${BASE_RPC_SRC} connection_unix.cpp)
if (APPLE)
add_definitions(-DDISCORD_OSX)
set(BASE_RPC_SRC ${BASE_RPC_SRC} discord_register_osx.m)
else (APPLE)
add_definitions(-DDISCORD_LINUX)
set(BASE_RPC_SRC ${BASE_RPC_SRC} discord_register_linux.cpp)
endif(APPLE)
add_library(discord-rpc ${BASE_RPC_SRC})
target_link_libraries(discord-rpc PUBLIC pthread)
target_compile_options(discord-rpc PRIVATE
-g
-Wall
-Wextra
-Wpedantic
)
if (${WARNINGS_AS_ERRORS})
target_compile_options(discord-rpc PRIVATE -Werror)
endif (${WARNINGS_AS_ERRORS})
target_compile_options(discord-rpc PRIVATE
-Wno-unknown-pragmas # pragma push thing doesn't work on clang
-Wno-old-style-cast # it's fine
-Wno-c++98-compat # that was almost 2 decades ago
-Wno-c++98-compat-pedantic
-Wno-missing-noreturn
-Wno-padded # structure padding
-Wno-covered-switch-default
-Wno-exit-time-destructors # not sure about these
-Wno-global-constructors
)
if (${BUILD_SHARED_LIBS})
target_compile_options(discord-rpc PRIVATE -fPIC)
endif (${BUILD_SHARED_LIBS})
if (APPLE)
target_link_libraries(discord-rpc PRIVATE "-framework AppKit")
endif (APPLE)
endif(UNIX)
target_include_directories(discord-rpc PRIVATE ${RAPIDJSON}/include)
if (NOT ${ENABLE_IO_THREAD})
target_compile_definitions(discord-rpc PUBLIC -DDISCORD_DISABLE_IO_THREAD)
endif (NOT ${ENABLE_IO_THREAD})
if (${BUILD_SHARED_LIBS})
target_compile_definitions(discord-rpc PUBLIC -DDISCORD_DYNAMIC_LIB)
target_compile_definitions(discord-rpc PRIVATE -DDISCORD_BUILDING_SDK)
endif(${BUILD_SHARED_LIBS})
if (CLANG_FORMAT_CMD)
add_dependencies(discord-rpc clangformat)
endif(CLANG_FORMAT_CMD)
# install
install(
TARGETS discord-rpc
EXPORT "discord-rpc"
RUNTIME
DESTINATION "${CMAKE_INSTALL_BINDIR}"
LIBRARY
DESTINATION "${CMAKE_INSTALL_LIBDIR}"
ARCHIVE
DESTINATION "${CMAKE_INSTALL_LIBDIR}"
INCLUDES
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)
install(
FILES
"../include/discord_rpc.h"
"../include/discord_register.h"
DESTINATION "include"
)

View File

@ -26,62 +26,66 @@ static int MsgFlags = MSG_NOSIGNAL;
static int MsgFlags = 0; static int MsgFlags = 0;
#endif #endif
static const char* GetTempPath() static const char* GetTempPath(void)
{ {
const char* temp = getenv("XDG_RUNTIME_DIR"); const char* temp = getenv("XDG_RUNTIME_DIR");
temp = temp ? temp : getenv("TMPDIR"); temp = temp ? temp : getenv("TMPDIR");
temp = temp ? temp : getenv("TMP"); temp = temp ? temp : getenv("TMP");
temp = temp ? temp : getenv("TEMP"); temp = temp ? temp : getenv("TEMP");
temp = temp ? temp : "/tmp"; temp = temp ? temp : "/tmp";
return temp; return temp;
} }
/*static*/ BaseConnection* BaseConnection::Create() /*static*/ BaseConnection* BaseConnection::Create()
{ {
PipeAddr.sun_family = AF_UNIX; PipeAddr.sun_family = AF_UNIX;
return &Connection; return &Connection;
} }
/*static*/ void BaseConnection::Destroy(BaseConnection*& c) /*static*/ void BaseConnection::Destroy(BaseConnection*& c)
{ {
auto self = reinterpret_cast<BaseConnectionUnix*>(c); auto self = reinterpret_cast<BaseConnectionUnix*>(c);
self->Close(); self->Close();
c = nullptr; c = nullptr;
} }
bool BaseConnection::Open() bool BaseConnection::Open()
{ {
const char* tempPath = GetTempPath();
auto self = reinterpret_cast<BaseConnectionUnix*>(this);
self->sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (self->sock == -1) {
return false;
}
fcntl(self->sock, F_SETFL, O_NONBLOCK);
#ifdef SO_NOSIGPIPE #ifdef SO_NOSIGPIPE
int optval = 1; int optval = 1;
setsockopt(self->sock, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)); #endif
const char* tempPath = GetTempPath();
auto self = reinterpret_cast<BaseConnectionUnix*>(this);
self->sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (self->sock == -1)
return false;
fcntl(self->sock, F_SETFL, O_NONBLOCK);
#ifdef SO_NOSIGPIPE
setsockopt(self->sock, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval));
#endif #endif
for (int pipeNum = 0; pipeNum < 10; ++pipeNum) { for (int pipeNum = 0; pipeNum < 10; ++pipeNum)
snprintf( {
PipeAddr.sun_path, sizeof(PipeAddr.sun_path), "%s/discord-ipc-%d", tempPath, pipeNum); snprintf(
int err = connect(self->sock, (const sockaddr*)&PipeAddr, sizeof(PipeAddr)); PipeAddr.sun_path, sizeof(PipeAddr.sun_path), "%s/discord-ipc-%d", tempPath, pipeNum);
if (err == 0) { int err = connect(self->sock, (const sockaddr*)&PipeAddr, sizeof(PipeAddr));
self->isOpen = true; if (err == 0)
return true; {
} self->isOpen = true;
} return true;
self->Close(); }
return false; }
self->Close();
return false;
} }
bool BaseConnection::Close() bool BaseConnection::Close()
{ {
auto self = reinterpret_cast<BaseConnectionUnix*>(this); auto self = reinterpret_cast<BaseConnectionUnix*>(this);
if (self->sock == -1) { if (self->sock == -1)
return false; return false;
}
close(self->sock); close(self->sock);
self->sock = -1; self->sock = -1;
self->isOpen = false; self->isOpen = false;
@ -90,33 +94,32 @@ bool BaseConnection::Close()
bool BaseConnection::Write(const void* data, size_t length) bool BaseConnection::Write(const void* data, size_t length)
{ {
auto self = reinterpret_cast<BaseConnectionUnix*>(this); ssize_t sentBytes;
auto self = reinterpret_cast<BaseConnectionUnix*>(this);
if (self->sock == -1) { if (self->sock == -1)
return false; return false;
}
ssize_t sentBytes = send(self->sock, data, length, MsgFlags); sentBytes = send(self->sock, data, length, MsgFlags);
if (sentBytes < 0) { if (sentBytes < 0)
Close(); Close();
} return sentBytes == (ssize_t)length;
return sentBytes == (ssize_t)length;
} }
bool BaseConnection::Read(void* data, size_t length) bool BaseConnection::Read(void* data, size_t length)
{ {
auto self = reinterpret_cast<BaseConnectionUnix*>(this); int res;
auto self = reinterpret_cast<BaseConnectionUnix*>(this);
if (self->sock == -1) { if (self->sock == -1)
return false; return false;
}
int res = (int)recv(self->sock, data, length, MsgFlags); res = (int)recv(self->sock, data, length, MsgFlags);
if (res < 0) { if (res < 0)
if (errno == EAGAIN) { {
return false; if (errno == EAGAIN)
} return false;
Close(); Close();
} }
return res == (int)length; return res == (int)length;
} }

View File

@ -12,7 +12,8 @@ int GetProcessId()
return (int)::GetCurrentProcessId(); return (int)::GetCurrentProcessId();
} }
struct BaseConnectionWin : public BaseConnection { struct BaseConnectionWin : public BaseConnection
{
HANDLE pipe{INVALID_HANDLE_VALUE}; HANDLE pipe{INVALID_HANDLE_VALUE};
}; };
@ -36,28 +37,33 @@ bool BaseConnection::Open()
const size_t pipeDigit = sizeof(pipeName) / sizeof(wchar_t) - 2; const size_t pipeDigit = sizeof(pipeName) / sizeof(wchar_t) - 2;
pipeName[pipeDigit] = L'0'; pipeName[pipeDigit] = L'0';
auto self = reinterpret_cast<BaseConnectionWin*>(this); auto self = reinterpret_cast<BaseConnectionWin*>(this);
for (;;) { for (;;)
self->pipe = ::CreateFileW( {
pipeName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr); self->pipe = ::CreateFileW(
if (self->pipe != INVALID_HANDLE_VALUE) { pipeName, GENERIC_READ | GENERIC_WRITE, 0,
self->isOpen = true; nullptr, OPEN_EXISTING, 0, nullptr);
return true; if (self->pipe != INVALID_HANDLE_VALUE)
} {
self->isOpen = true;
return true;
}
auto lastError = GetLastError(); auto lastError = GetLastError();
if (lastError == ERROR_FILE_NOT_FOUND) { if (lastError == ERROR_FILE_NOT_FOUND)
if (pipeName[pipeDigit] < L'9') { {
pipeName[pipeDigit]++; if (pipeName[pipeDigit] < L'9')
continue; {
} pipeName[pipeDigit]++;
} continue;
else if (lastError == ERROR_PIPE_BUSY) { }
if (!WaitNamedPipeW(pipeName, 10000)) { }
return false; else if (lastError == ERROR_PIPE_BUSY)
} {
continue; if (!WaitNamedPipeW(pipeName, 10000))
} return false;
return false; continue;
}
return false;
} }
} }
@ -72,57 +78,50 @@ bool BaseConnection::Close()
bool BaseConnection::Write(const void* data, size_t length) bool BaseConnection::Write(const void* data, size_t length)
{ {
if (length == 0) { if (length == 0)
return true; return true;
}
auto self = reinterpret_cast<BaseConnectionWin*>(this); auto self = reinterpret_cast<BaseConnectionWin*>(this);
assert(self); assert(self);
if (!self) { if (!self)
return false; return false;
} if (self->pipe == INVALID_HANDLE_VALUE)
if (self->pipe == INVALID_HANDLE_VALUE) {
return false; return false;
}
assert(data); assert(data);
if (!data) { if (!data)
return false; return false;
}
const DWORD bytesLength = (DWORD)length; const DWORD bytesLength = (DWORD)length;
DWORD bytesWritten = 0; DWORD bytesWritten = 0;
return ::WriteFile(self->pipe, data, bytesLength, &bytesWritten, nullptr) == TRUE && return ::WriteFile(self->pipe, data, bytesLength,
bytesWritten == bytesLength; &bytesWritten, nullptr) == TRUE &&
bytesWritten == bytesLength;
} }
bool BaseConnection::Read(void* data, size_t length) bool BaseConnection::Read(void* data, size_t length)
{ {
assert(data); assert(data);
if (!data) { if (!data)
return false; return false;
} auto self = reinterpret_cast<BaseConnectionWin*>(this);
auto self = reinterpret_cast<BaseConnectionWin*>(this); assert(self);
assert(self); if (!self)
if (!self) { return false;
return false; if (self->pipe == INVALID_HANDLE_VALUE)
} return false;
if (self->pipe == INVALID_HANDLE_VALUE) { DWORD bytesAvailable = 0;
return false; if (::PeekNamedPipe(self->pipe, nullptr, 0, nullptr, &bytesAvailable, nullptr)) {
} if (bytesAvailable >= length)
DWORD bytesAvailable = 0; {
if (::PeekNamedPipe(self->pipe, nullptr, 0, nullptr, &bytesAvailable, nullptr)) { DWORD bytesToRead = (DWORD)length;
if (bytesAvailable >= length) { DWORD bytesRead = 0;
DWORD bytesToRead = (DWORD)length; if (::ReadFile(self->pipe, data, bytesToRead, &bytesRead, nullptr) == TRUE) {
DWORD bytesRead = 0; assert(bytesToRead == bytesRead);
if (::ReadFile(self->pipe, data, bytesToRead, &bytesRead, nullptr) == TRUE) { return true;
assert(bytesToRead == bytesRead); }
return true; else
} Close();
else { }
Close(); }
} else
} Close();
} return false;
else {
Close();
}
return false;
} }

View File

@ -247,16 +247,17 @@ static void Discord_UpdateConnection(void)
static bool RegisterForEvent(const char* evtName) static bool RegisterForEvent(const char* evtName)
{ {
auto qmessage = SendQueue.GetNextAddMessage(); auto qmessage = SendQueue.GetNextAddMessage();
if (qmessage) { if (qmessage)
qmessage->length = {
JsonWriteSubscribeCommand(qmessage->buffer, sizeof(qmessage->buffer), Nonce++, evtName); qmessage->length =
SendQueue.CommitAdd(); JsonWriteSubscribeCommand(qmessage->buffer, sizeof(qmessage->buffer), Nonce++, evtName);
if (IoThread) SendQueue.CommitAdd();
IoThread->Notify(); if (IoThread)
return true; IoThread->Notify();
} return true;
return false; }
return false;
} }
static bool DeregisterForEvent(const char* evtName) static bool DeregisterForEvent(const char* evtName)
@ -279,17 +280,15 @@ extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
const char* optionalSteamId) const char* optionalSteamId)
{ {
IoThread = new (std::nothrow) IoThreadHolder(); IoThread = new (std::nothrow) IoThreadHolder();
if (IoThread == nullptr) { if (IoThread == nullptr)
return; return;
}
if (autoRegister) { if (autoRegister)
if (optionalSteamId && optionalSteamId[0]) { {
Discord_RegisterSteamGame(applicationId, optionalSteamId); if (optionalSteamId && optionalSteamId[0])
} Discord_RegisterSteamGame(applicationId, optionalSteamId);
else { else
Discord_Register(applicationId, nullptr); Discord_Register(applicationId, nullptr);
}
} }
Pid = GetProcessId(); Pid = GetProcessId();
@ -297,29 +296,26 @@ extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
{ {
std::lock_guard<std::mutex> guard(HandlerMutex); std::lock_guard<std::mutex> guard(HandlerMutex);
if (handlers) { if (handlers)
QueuedHandlers = *handlers; QueuedHandlers = *handlers;
} else
else {
QueuedHandlers = {}; QueuedHandlers = {};
}
Handlers = {}; Handlers = {};
} }
if (Connection) { if (Connection)
return; return;
}
Connection = RpcConnection::Create(applicationId); Connection = RpcConnection::Create(applicationId);
Connection->onConnect = [](JsonDocument& readyMessage) Connection->onConnect = [](JsonDocument& readyMessage)
{ {
Discord_UpdateHandlers(&QueuedHandlers); Discord_UpdateHandlers(&QueuedHandlers);
auto data = GetObjMember(&readyMessage, "data"); auto data = GetObjMember(&readyMessage, "data");
auto user = GetObjMember(data, "user"); auto user = GetObjMember(data, "user");
auto userId = GetStrMember(user, "id"); auto userId = GetStrMember(user, "id");
auto username = GetStrMember(user, "username"); auto username = GetStrMember(user, "username");
auto avatar = GetStrMember(user, "avatar"); auto avatar = GetStrMember(user, "avatar");
if (userId && username) if (userId && username)
{ {
StringCopy(connectedUser.userId, userId); StringCopy(connectedUser.userId, userId);
@ -367,7 +363,8 @@ extern "C" DISCORD_EXPORT void Discord_Shutdown(void)
RpcConnection::Destroy(Connection); RpcConnection::Destroy(Connection);
} }
extern "C" DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* presence) extern "C" DISCORD_EXPORT void
Discord_UpdatePresence(const DiscordRichPresence* presence)
{ {
{ {
std::lock_guard<std::mutex> guard(PresenceMutex); std::lock_guard<std::mutex> guard(PresenceMutex);