track open/close state in connection, disconnect on read error, clarify error codes a little
This commit is contained in:
parent
c3c27c730d
commit
d5e6c4c11a
5 changed files with 47 additions and 5 deletions
|
@ -11,6 +11,7 @@ int GetProcessId();
|
||||||
struct BaseConnection {
|
struct BaseConnection {
|
||||||
static BaseConnection* Create();
|
static BaseConnection* Create();
|
||||||
static void Destroy(BaseConnection*&);
|
static void Destroy(BaseConnection*&);
|
||||||
|
bool isOpen{false};
|
||||||
bool Open();
|
bool Open();
|
||||||
bool Close();
|
bool Close();
|
||||||
bool Write(const void* data, size_t length);
|
bool Write(const void* data, size_t length);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -18,7 +19,12 @@ struct BaseConnectionUnix : public BaseConnection {
|
||||||
};
|
};
|
||||||
|
|
||||||
static BaseConnectionUnix Connection;
|
static BaseConnectionUnix Connection;
|
||||||
sockaddr_un PipeAddr{};
|
static sockaddr_un PipeAddr{};
|
||||||
|
#ifdef MSG_NOSIGNAL
|
||||||
|
static int MsgFlags = MSG_NOSIGNAL;
|
||||||
|
#else
|
||||||
|
static int MsgFlags = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
static const char* GetTempPath()
|
static const char* GetTempPath()
|
||||||
{
|
{
|
||||||
|
@ -52,11 +58,17 @@ bool BaseConnection::Open()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
fcntl(self->sock, F_SETFL, O_NONBLOCK);
|
fcntl(self->sock, F_SETFL, O_NONBLOCK);
|
||||||
|
#ifdef SO_NOSIGPIPE
|
||||||
|
int optval = 1;
|
||||||
|
setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval));
|
||||||
|
#endif
|
||||||
|
|
||||||
for (int pipeNum = 0; pipeNum < 10; ++pipeNum) {
|
for (int pipeNum = 0; pipeNum < 10; ++pipeNum) {
|
||||||
snprintf(
|
snprintf(
|
||||||
PipeAddr.sun_path, sizeof(PipeAddr.sun_path), "%s/discord-ipc-%d", tempPath, pipeNum);
|
PipeAddr.sun_path, sizeof(PipeAddr.sun_path), "%s/discord-ipc-%d", tempPath, pipeNum);
|
||||||
int err = connect(self->sock, (const sockaddr*)&PipeAddr, sizeof(PipeAddr));
|
int err = connect(self->sock, (const sockaddr*)&PipeAddr, sizeof(PipeAddr));
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
|
self->isOpen = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,6 +84,7 @@ bool BaseConnection::Close()
|
||||||
}
|
}
|
||||||
close(self->sock);
|
close(self->sock);
|
||||||
self->sock = -1;
|
self->sock = -1;
|
||||||
|
self->isOpen = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +96,10 @@ bool BaseConnection::Write(const void* data, size_t length)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t sentBytes = send(self->sock, data, length, 0);
|
ssize_t sentBytes = send(self->sock, data, length, MsgFlags);
|
||||||
|
if (sentBytes < 0) {
|
||||||
|
Close();
|
||||||
|
}
|
||||||
return sentBytes == (ssize_t)length;
|
return sentBytes == (ssize_t)length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,6 +111,12 @@ bool BaseConnection::Read(void* data, size_t length)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int res = recv(self->sock, data, length, 0);
|
int res = recv(self->sock, data, length, MsgFlags);
|
||||||
|
if (res < 0) {
|
||||||
|
if (errno == EAGAIN) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Close();
|
||||||
|
}
|
||||||
return res == (int)length;
|
return res == (int)length;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ bool BaseConnection::Open()
|
||||||
self->pipe = ::CreateFileW(
|
self->pipe = ::CreateFileW(
|
||||||
pipeName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
|
pipeName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||||
if (self->pipe != INVALID_HANDLE_VALUE) {
|
if (self->pipe != INVALID_HANDLE_VALUE) {
|
||||||
|
self->isOpen = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,6 +65,7 @@ bool BaseConnection::Close()
|
||||||
auto self = reinterpret_cast<BaseConnectionWin*>(this);
|
auto self = reinterpret_cast<BaseConnectionWin*>(this);
|
||||||
::CloseHandle(self->pipe);
|
::CloseHandle(self->pipe);
|
||||||
self->pipe = INVALID_HANDLE_VALUE;
|
self->pipe = INVALID_HANDLE_VALUE;
|
||||||
|
self->isOpen = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +84,13 @@ bool BaseConnection::Read(void* data, size_t length)
|
||||||
if (::ReadFile(self->pipe, data, length, nullptr, nullptr) == TRUE) {
|
if (::ReadFile(self->pipe, data, length, nullptr, nullptr) == TRUE) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Close();
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,13 +97,18 @@ bool RpcConnection::Read(JsonDocument& message)
|
||||||
for (;;) {
|
for (;;) {
|
||||||
bool didRead = connection->Read(&readFrame, sizeof(MessageFrameHeader));
|
bool didRead = connection->Read(&readFrame, sizeof(MessageFrameHeader));
|
||||||
if (!didRead) {
|
if (!didRead) {
|
||||||
|
if (!connection->isOpen) {
|
||||||
|
lastErrorCode = (int)ErrorCode::PipeClosed;
|
||||||
|
StringCopy(lastErrorMessage, "Pipe closed");
|
||||||
|
Close();
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (readFrame.length > 0) {
|
if (readFrame.length > 0) {
|
||||||
didRead = connection->Read(readFrame.message, readFrame.length);
|
didRead = connection->Read(readFrame.message, readFrame.length);
|
||||||
if (!didRead) {
|
if (!didRead) {
|
||||||
lastErrorCode = -2;
|
lastErrorCode = (int)ErrorCode::ReadCorrupt;
|
||||||
StringCopy(lastErrorMessage, "Partial data in frame");
|
StringCopy(lastErrorMessage, "Partial data in frame");
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
|
@ -132,7 +137,7 @@ bool RpcConnection::Read(JsonDocument& message)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// something bad happened
|
// something bad happened
|
||||||
lastErrorCode = -1;
|
lastErrorCode = (int)ErrorCode::ReadCorrupt;
|
||||||
StringCopy(lastErrorMessage, "Bad ipc frame");
|
StringCopy(lastErrorMessage, "Bad ipc frame");
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -8,6 +8,12 @@
|
||||||
constexpr size_t MaxRpcFrameSize = 64 * 1024;
|
constexpr size_t MaxRpcFrameSize = 64 * 1024;
|
||||||
|
|
||||||
struct RpcConnection {
|
struct RpcConnection {
|
||||||
|
enum class ErrorCode : int {
|
||||||
|
Success = 0,
|
||||||
|
PipeClosed = 1,
|
||||||
|
ReadCorrupt = 2,
|
||||||
|
};
|
||||||
|
|
||||||
enum class Opcode : uint32_t {
|
enum class Opcode : uint32_t {
|
||||||
Handshake = 0,
|
Handshake = 0,
|
||||||
Frame = 1,
|
Frame = 1,
|
||||||
|
|
Loading…
Reference in a new issue