Compare commits

...

14 Commits

Author SHA1 Message Date
d72163ad27 Merge pull request #8 from lioncash/bind
Listener: Remove unnecessary bind() within start()
2019-09-03 19:55:03 -07:00
fb3d880b63 Merge pull request #7 from lioncash/assignment
Listener: Simplify assignment within accept()
2019-09-03 19:54:45 -07:00
ebe78edac7 Merge pull request #6 from lioncash/constexpr
Listener: Move port constants into cpp file
2019-09-03 19:54:27 -07:00
092f7dd0f2 Merge pull request #5 from lioncash/array
Endpoint: Use std::array where applicable
2019-09-03 19:54:02 -07:00
Lioncash
be121a1bb9 Listener: Remove unnecessary bind() within start()
std::thread already handles execution of member functions
out-of-the-box.
2019-09-03 10:18:52 -04:00
Lioncash
33908dd86a Listener: Simplify assignment within accept()
We can just assign to the ret variable directly.
2019-09-03 10:15:33 -04:00
Lioncash
4538b20e73 Listener: Use C++17 deduction guides for mutex locks
Same thing, but without hardcoding the mutex type.
2019-09-03 10:13:30 -04:00
Lioncash
04ea97ac8e Listener: Move port constants into cpp file
These are a complete internal detail, so we can hide them from the
header entirely.
2019-09-03 10:07:14 -04:00
Lioncash
5a97e587b6 Endpoint: Use std::array where applicable
Makes the interface a little more strongly-typed, and in some cases
makes it less likely to pass in invalid data.
2019-09-03 09:54:50 -04:00
dff87c2c6a Merge pull request #3 from lioncash/include
General: Amend includes where applicable
2019-09-03 00:36:09 -07:00
417e79f924 Merge pull request #4 from lioncash/zero
General: Use list initialization where applicable
2019-09-03 00:35:57 -07:00
Lioncash
9f7c855acd General: Use list initialization where applicable
Same behavior, but without the need for separating the assignment from
the declaration
2019-09-03 00:55:06 -04:00
Lioncash
714e88bb7a Socket: Add missing noexcept specifier to LastWSAError()
This is used within a noexcept function, so it needs the noexcept
specifier.
2019-09-03 00:27:30 -04:00
Lioncash
d4891f187f General: Amend includes where applicable 2019-09-03 00:26:08 -04:00
6 changed files with 144 additions and 102 deletions

View File

@@ -1,16 +1,24 @@
#pragma once #pragma once
#include "Common.hpp" #include <array>
#include "Socket.hpp"
#include <thread>
#include <mutex>
#include <condition_variable> #include <condition_variable>
#include <cstddef>
#include <functional>
#include <mutex>
#include <thread>
#include "jbus/Common.hpp"
#include "jbus/Socket.hpp"
namespace jbus { namespace jbus {
using ReadWriteBuffer = std::array<u8, 4>;
/** Main class for performing JoyBoot and subsequent JoyBus I/O operations. /** Main class for performing JoyBoot and subsequent JoyBus I/O operations.
* Instances should be obtained though the jbus::Listener::accept method. */ * Instances should be obtained though the jbus::Listener::accept method. */
class Endpoint { class Endpoint {
using Buffer = std::array<u8, 5>;
/** Self-contained class for solving Kawasedo's GBA BootROM challenge. /** Self-contained class for solving Kawasedo's GBA BootROM challenge.
* GBA will boot client_pad.bin code on completion. * GBA will boot client_pad.bin code on completion.
* *
@@ -48,14 +56,14 @@ class Endpoint {
u32 xc_progLen; u32 xc_progLen;
u8* x10_statusPtr; u8* x10_statusPtr;
FGBACallback x14_callback; FGBACallback x14_callback;
u8 x18_readBuf[4]; ReadWriteBuffer x18_readBuf;
u8 x1c_writeBuf[4]; ReadWriteBuffer x1c_writeBuf;
s32 x20_byteInWindow; s32 x20_byteInWindow;
u64 x28_ticksAfterXf; u64 x28_ticksAfterXf;
u32 x30_justStarted; u32 x30_justStarted;
u32 x34_bytesSent; u32 x34_bytesSent;
u32 x38_crc; u32 x38_crc;
u32 x3c_checkStore[7]; std::array<u32, 7> x3c_checkStore;
s32 x58_currentKey; s32 x58_currentKey;
s32 x5c_initMessage; s32 x5c_initMessage;
s32 x60_gameId; s32 x60_gameId;
@@ -109,7 +117,7 @@ class Endpoint {
std::condition_variable m_issueCv; std::condition_variable m_issueCv;
KawasedoChallenge m_joyBoot; KawasedoChallenge m_joyBoot;
FGBACallback m_callback; FGBACallback m_callback;
u8 m_buffer[5]; Buffer m_buffer{};
u8* m_readDstPtr = nullptr; u8* m_readDstPtr = nullptr;
u8* m_statusPtr = nullptr; u8* m_statusPtr = nullptr;
u64 m_lastGCTick = 0; u64 m_lastGCTick = 0;
@@ -120,9 +128,9 @@ class Endpoint {
bool m_running = true; bool m_running = true;
void clockSync(); void clockSync();
void send(const u8* buffer); void send(Buffer buffer);
size_t receive(u8* buffer); size_t receive(Buffer& buffer);
size_t runBuffer(u8* buffer, std::unique_lock<std::mutex>& lk); size_t runBuffer(Buffer& buffer, std::unique_lock<std::mutex>& lk);
bool idleGetStatus(std::unique_lock<std::mutex>& lk); bool idleGetStatus(std::unique_lock<std::mutex>& lk);
void transferProc(); void transferProc();
void transferWakeup(ThreadLocalEndpoint& endpoint, u8 status); void transferWakeup(ThreadLocalEndpoint& endpoint, u8 status);
@@ -163,30 +171,30 @@ public:
EJoyReturn GBAReset(u8* status); EJoyReturn GBAReset(u8* status);
/** @brief Send READ command to GBA asynchronously. /** @brief Send READ command to GBA asynchronously.
* @param dst Destination pointer for 4-byte packet of data. * @param dst Destination reference for 4-byte packet of data.
* @param status Destination pointer for EJStatFlags. * @param status Destination pointer for EJStatFlags.
* @param callback Functor to execute when operation completes. * @param callback Functor to execute when operation completes.
* @return GBA_READY if submitted, or GBA_NOT_READY if another operation in progress. */ * @return GBA_READY if submitted, or GBA_NOT_READY if another operation in progress. */
EJoyReturn GBAReadAsync(u8* dst, u8* status, FGBACallback&& callback); EJoyReturn GBAReadAsync(ReadWriteBuffer& dst, u8* status, FGBACallback&& callback);
/** @brief Send READ command to GBA synchronously. /** @brief Send READ command to GBA synchronously.
* @param dst Destination pointer for 4-byte packet of data. * @param dst Destination reference for 4-byte packet of data.
* @param status Destination pointer for EJStatFlags. * @param status Destination pointer for EJStatFlags.
* @return GBA_READY if submitted, or GBA_NOT_READY if another operation in progress. */ * @return GBA_READY if submitted, or GBA_NOT_READY if another operation in progress. */
EJoyReturn GBARead(u8* dst, u8* status); EJoyReturn GBARead(ReadWriteBuffer& dst, u8* status);
/** @brief Send WRITE command to GBA asynchronously. /** @brief Send WRITE command to GBA asynchronously.
* @param src Source pointer for 4-byte packet of data. It is not required to keep resident. * @param src Source pointer for 4-byte packet of data. It is not required to keep resident.
* @param status Destination pointer for EJStatFlags. * @param status Destination pointer for EJStatFlags.
* @param callback Functor to execute when operation completes. * @param callback Functor to execute when operation completes.
* @return GBA_READY if submitted, or GBA_NOT_READY if another operation in progress. */ * @return GBA_READY if submitted, or GBA_NOT_READY if another operation in progress. */
EJoyReturn GBAWriteAsync(const u8* src, u8* status, FGBACallback&& callback); EJoyReturn GBAWriteAsync(ReadWriteBuffer src, u8* status, FGBACallback&& callback);
/** @brief Send WRITE command to GBA synchronously. /** @brief Send WRITE command to GBA synchronously.
* @param src Source pointer for 4-byte packet of data. It is not required to keep resident. * @param src Source pointer for 4-byte packet of data. It is not required to keep resident.
* @param status Destination pointer for EJStatFlags. * @param status Destination pointer for EJStatFlags.
* @return GBA_READY if submitted, or GBA_NOT_READY if another operation in progress. */ * @return GBA_READY if submitted, or GBA_NOT_READY if another operation in progress. */
EJoyReturn GBAWrite(const u8* src, u8* status); EJoyReturn GBAWrite(ReadWriteBuffer src, u8* status);
/** @brief Initiate JoyBoot sequence on this endpoint. /** @brief Initiate JoyBoot sequence on this endpoint.
* @param paletteColor Palette for displaying logo in ROM header [0,6]. * @param paletteColor Palette for displaying logo in ROM header [0,6].
@@ -241,18 +249,18 @@ public:
EJoyReturn GBAResetAsync(u8* status, FGBACallback&& callback); EJoyReturn GBAResetAsync(u8* status, FGBACallback&& callback);
/** @brief Send READ command to GBA asynchronously. /** @brief Send READ command to GBA asynchronously.
* @param dst Destination pointer for 4-byte packet of data. * @param dst Destination reference for 4-byte packet of data.
* @param status Destination pointer for EJStatFlags. * @param status Destination pointer for EJStatFlags.
* @param callback Functor to execute when operation completes. * @param callback Functor to execute when operation completes.
* @return GBA_READY if submitted, or GBA_NOT_READY if another operation in progress. */ * @return GBA_READY if submitted, or GBA_NOT_READY if another operation in progress. */
EJoyReturn GBAReadAsync(u8* dst, u8* status, FGBACallback&& callback); EJoyReturn GBAReadAsync(ReadWriteBuffer& dst, u8* status, FGBACallback&& callback);
/** @brief Send WRITE command to GBA asynchronously. /** @brief Send WRITE command to GBA asynchronously.
* @param src Source pointer for 4-byte packet of data. It is not required to keep resident. * @param src 4-byte packet of data. It is not required to keep resident.
* @param status Destination pointer for EJStatFlags. * @param status Destination pointer for EJStatFlags.
* @param callback Functor to execute when operation completes. * @param callback Functor to execute when operation completes.
* @return GBA_READY if submitted, or GBA_NOT_READY if another operation in progress. */ * @return GBA_READY if submitted, or GBA_NOT_READY if another operation in progress. */
EJoyReturn GBAWriteAsync(const u8* src, u8* status, FGBACallback&& callback); EJoyReturn GBAWriteAsync(ReadWriteBuffer src, u8* status, FGBACallback&& callback);
/** @brief Get virtual SI channel assigned to this endpoint. /** @brief Get virtual SI channel assigned to this endpoint.
* @return SI channel */ * @return SI channel */

View File

@@ -1,12 +1,14 @@
#pragma once #pragma once
#include "Common.hpp" #include <memory>
#include "Socket.hpp"
#include <thread>
#include <queue>
#include <mutex> #include <mutex>
#include <queue>
#include <thread>
#include "jbus/Socket.hpp"
namespace jbus { namespace jbus {
class Endpoint;
/** Server interface for accepting incoming connections from GBA emulator instances. */ /** Server interface for accepting incoming connections from GBA emulator instances. */
class Listener { class Listener {
@@ -17,9 +19,6 @@ class Listener {
std::queue<std::unique_ptr<Endpoint>> m_endpointQueue; std::queue<std::unique_ptr<Endpoint>> m_endpointQueue;
bool m_running = false; bool m_running = false;
static const uint32_t DataPort = 0xd6ba;
static const uint32_t ClockPort = 0xc10c;
void listenerProc(); void listenerProc();
public: public:
@@ -33,6 +32,7 @@ public:
* @return Endpoint instance, ready to issue commands. */ * @return Endpoint instance, ready to issue commands. */
std::unique_ptr<Endpoint> accept(); std::unique_ptr<Endpoint> accept();
Listener();
~Listener(); ~Listener();
}; };

View File

@@ -1,17 +1,14 @@
#pragma once #pragma once
#include <sys/types.h> #include <cstddef>
#include <fcntl.h> #include <cstdint>
#include <string> #include <string>
#include <memory.h>
#ifdef _WIN32 #ifdef _WIN32
#include <BaseTsd.h> #include <BaseTsd.h>
typedef UINT_PTR SOCKET; using SOCKET = UINT_PTR;
#endif #endif
#include "Common.hpp"
struct sockaddr_in; struct sockaddr_in;
namespace jbus::net { namespace jbus::net {

View File

@@ -1,7 +1,13 @@
#include "jbus/Endpoint.hpp" #include "jbus/Endpoint.hpp"
#include <algorithm>
#define LOG_TRANSFER 0 #define LOG_TRANSFER 0
#if LOG_TRANSFER
#include <cstdio>
#endif
namespace jbus { namespace jbus {
#define ROUND_UP_8(val) (((val) + 7) & ~7) #define ROUND_UP_8(val) (((val) + 7) & ~7)
@@ -355,18 +361,20 @@ void Endpoint::clockSync() {
m_running = false; m_running = false;
} }
void Endpoint::send(const u8* buffer) { void Endpoint::send(Buffer buffer) {
m_lastCmd = buffer[0]; m_lastCmd = buffer[0];
net::Socket::EResult result; net::Socket::EResult result;
size_t sentBytes; size_t sentBytes;
if (m_lastCmd == CMD_WRITE) if (m_lastCmd == CMD_WRITE) {
result = m_dataSocket.send(buffer, 5, sentBytes); result = m_dataSocket.send(buffer.data(), buffer.size(), sentBytes);
else } else {
result = m_dataSocket.send(buffer, 1, sentBytes); result = m_dataSocket.send(buffer.data(), 1, sentBytes);
}
if (m_lastCmd != CMD_STATUS) if (m_lastCmd != CMD_STATUS) {
m_booted = true; m_booted = true;
}
if (result != net::Socket::EResult::OK) { if (result != net::Socket::EResult::OK) {
m_running = false; m_running = false;
@@ -378,30 +386,31 @@ void Endpoint::send(const u8* buffer) {
#endif #endif
} }
size_t Endpoint::receive(u8* buffer) { size_t Endpoint::receive(Buffer& buffer) {
if (!m_dataSocket) { if (!m_dataSocket) {
m_running = false; m_running = false;
return 5; return buffer.size();
} }
size_t recvBytes = 0; size_t recvBytes = 0;
net::Socket::EResult result = m_dataSocket.recv(buffer, 5, recvBytes); const net::Socket::EResult result = m_dataSocket.recv(buffer.data(), buffer.size(), recvBytes);
if (result == net::Socket::EResult::Error) { if (result == net::Socket::EResult::Error) {
m_running = false; m_running = false;
return 5; return buffer.size();
} }
if (recvBytes > 5) if (recvBytes > buffer.size()) {
recvBytes = 5; recvBytes = buffer.size();
}
#if LOG_TRANSFER #if LOG_TRANSFER
if (recvBytes > 0) { if (recvBytes > 0) {
if (m_lastCmd == CMD_STATUS || m_lastCmd == CMD_RESET) { if (m_lastCmd == CMD_STATUS || m_lastCmd == CMD_RESET) {
printf("Stat/Reset [< %02x%02x%02x%02x%02x] (%lu)\n", (u8)buffer[0], (u8)buffer[1], (u8)buffer[2], (u8)buffer[3], printf("Stat/Reset [< %02x%02x%02x%02x%02x] (%lu)\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4],
(u8)buffer[4], recvBytes); recvBytes);
} else { } else {
printf("Receive [< %02x%02x%02x%02x%02x] (%lu)\n", (u8)buffer[0], (u8)buffer[1], (u8)buffer[2], (u8)buffer[3], printf("Receive [< %02x%02x%02x%02x%02x] (%lu)\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4],
(u8)buffer[4], recvBytes); recvBytes);
} }
} }
#endif #endif
@@ -409,23 +418,22 @@ size_t Endpoint::receive(u8* buffer) {
return recvBytes; return recvBytes;
} }
size_t Endpoint::runBuffer(u8* buffer, std::unique_lock<std::mutex>& lk) { size_t Endpoint::runBuffer(Buffer& buffer, std::unique_lock<std::mutex>& lk) {
u8 tmpBuffer[5]; Buffer tmpBuffer = buffer;
memmove(tmpBuffer, buffer, 5);
lk.unlock(); lk.unlock();
clockSync(); clockSync();
send(tmpBuffer); send(tmpBuffer);
size_t receivedBytes = receive(tmpBuffer); const size_t receivedBytes = receive(tmpBuffer);
lk.lock(); lk.lock();
memmove(buffer, tmpBuffer, 5);
buffer = tmpBuffer;
return receivedBytes; return receivedBytes;
} }
bool Endpoint::idleGetStatus(std::unique_lock<std::mutex>& lk) { bool Endpoint::idleGetStatus(std::unique_lock<std::mutex>& lk) {
u8 buffer[] = {CMD_STATUS, 0, 0, 0, 0}; Buffer buffer{u8(CMD_STATUS), 0, 0, 0, 0};
return runBuffer(buffer, lk); return runBuffer(buffer, lk) != 0;
} }
void Endpoint::transferProc() { void Endpoint::transferProc() {
@@ -455,10 +463,12 @@ void Endpoint::transferProc() {
*m_statusPtr = m_buffer[0]; *m_statusPtr = m_buffer[0];
break; break;
case CMD_READ: case CMD_READ:
if (m_statusPtr) if (m_statusPtr != nullptr) {
*m_statusPtr = m_buffer[4]; *m_statusPtr = m_buffer[4];
if (m_readDstPtr) }
memmove(m_readDstPtr, m_buffer, 4); if (m_readDstPtr != nullptr) {
std::copy(m_buffer.cbegin(), m_buffer.cbegin() + 4, m_readDstPtr);
}
break; break;
default: default:
break; break;
@@ -594,17 +604,19 @@ EJoyReturn Endpoint::GBAReset(u8* status) {
return GBA_READY; return GBA_READY;
} }
EJoyReturn Endpoint::GBAReadAsync(u8* dst, u8* status, FGBACallback&& callback) { EJoyReturn Endpoint::GBAReadAsync(ReadWriteBuffer& dst, u8* status, FGBACallback&& callback) {
if (!m_running) if (!m_running) {
return GBA_NOT_READY; return GBA_NOT_READY;
}
std::unique_lock<std::mutex> lk(m_syncLock); std::unique_lock<std::mutex> lk(m_syncLock);
if (m_cmdIssued) if (m_cmdIssued) {
return GBA_NOT_READY; return GBA_NOT_READY;
}
m_cmdIssued = true; m_cmdIssued = true;
m_statusPtr = status; m_statusPtr = status;
m_readDstPtr = dst; m_readDstPtr = dst.data();
m_buffer[0] = CMD_READ; m_buffer[0] = CMD_READ;
m_callback = std::move(callback); m_callback = std::move(callback);
@@ -613,17 +625,19 @@ EJoyReturn Endpoint::GBAReadAsync(u8* dst, u8* status, FGBACallback&& callback)
return GBA_READY; return GBA_READY;
} }
EJoyReturn Endpoint::GBARead(u8* dst, u8* status) { EJoyReturn Endpoint::GBARead(ReadWriteBuffer& dst, u8* status) {
if (!m_running) if (!m_running) {
return GBA_NOT_READY; return GBA_NOT_READY;
}
std::unique_lock<std::mutex> lk(m_syncLock); std::unique_lock<std::mutex> lk(m_syncLock);
if (m_cmdIssued) if (m_cmdIssued) {
return GBA_NOT_READY; return GBA_NOT_READY;
}
m_cmdIssued = true; m_cmdIssued = true;
m_statusPtr = status; m_statusPtr = status;
m_readDstPtr = dst; m_readDstPtr = dst.data();
m_buffer[0] = CMD_READ; m_buffer[0] = CMD_READ;
m_callback = bindSync(); m_callback = bindSync();
@@ -633,19 +647,22 @@ EJoyReturn Endpoint::GBARead(u8* dst, u8* status) {
return GBA_READY; return GBA_READY;
} }
EJoyReturn Endpoint::GBAWriteAsync(const u8* src, u8* status, FGBACallback&& callback) { EJoyReturn Endpoint::GBAWriteAsync(ReadWriteBuffer src, u8* status, FGBACallback&& callback) {
if (!m_running) if (!m_running) {
return GBA_NOT_READY; return GBA_NOT_READY;
}
std::unique_lock<std::mutex> lk(m_syncLock); std::unique_lock<std::mutex> lk(m_syncLock);
if (m_cmdIssued) if (m_cmdIssued) {
return GBA_NOT_READY; return GBA_NOT_READY;
}
m_cmdIssued = true; m_cmdIssued = true;
m_statusPtr = status; m_statusPtr = status;
m_buffer[0] = CMD_WRITE; m_buffer[0] = CMD_WRITE;
for (int i = 0; i < 4; ++i) for (size_t i = 0; i < src.size(); ++i) {
m_buffer[i + 1] = src[i]; m_buffer[i + 1] = src[i];
}
m_callback = std::move(callback); m_callback = std::move(callback);
m_issueCv.notify_one(); m_issueCv.notify_one();
@@ -653,19 +670,22 @@ EJoyReturn Endpoint::GBAWriteAsync(const u8* src, u8* status, FGBACallback&& cal
return GBA_READY; return GBA_READY;
} }
EJoyReturn Endpoint::GBAWrite(const u8* src, u8* status) { EJoyReturn Endpoint::GBAWrite(ReadWriteBuffer src, u8* status) {
if (!m_running) if (!m_running) {
return GBA_NOT_READY; return GBA_NOT_READY;
}
std::unique_lock<std::mutex> lk(m_syncLock); std::unique_lock<std::mutex> lk(m_syncLock);
if (m_cmdIssued) if (m_cmdIssued) {
return GBA_NOT_READY; return GBA_NOT_READY;
}
m_cmdIssued = true; m_cmdIssued = true;
m_statusPtr = status; m_statusPtr = status;
m_buffer[0] = CMD_WRITE; m_buffer[0] = CMD_WRITE;
for (int i = 0; i < 4; ++i) for (size_t i = 0; i < src.size(); ++i) {
m_buffer[i + 1] = src[i]; m_buffer[i + 1] = src[i];
}
m_callback = bindSync(); m_callback = bindSync();
m_issueCv.notify_one(); m_issueCv.notify_one();
@@ -733,28 +753,29 @@ EJoyReturn ThreadLocalEndpoint::GBAResetAsync(u8* status, FGBACallback&& callbac
return GBA_READY; return GBA_READY;
} }
EJoyReturn ThreadLocalEndpoint::GBAReadAsync(u8* dst, u8* status, FGBACallback&& callback) { EJoyReturn ThreadLocalEndpoint::GBAReadAsync(ReadWriteBuffer& dst, u8* status, FGBACallback&& callback) {
if (!m_ep.m_running || m_ep.m_cmdIssued) if (!m_ep.m_running || m_ep.m_cmdIssued)
return GBA_NOT_READY; return GBA_NOT_READY;
m_ep.m_cmdIssued = true; m_ep.m_cmdIssued = true;
m_ep.m_statusPtr = status; m_ep.m_statusPtr = status;
m_ep.m_readDstPtr = dst; m_ep.m_readDstPtr = dst.data();
m_ep.m_buffer[0] = Endpoint::CMD_READ; m_ep.m_buffer[0] = Endpoint::CMD_READ;
m_ep.m_callback = std::move(callback); m_ep.m_callback = std::move(callback);
return GBA_READY; return GBA_READY;
} }
EJoyReturn ThreadLocalEndpoint::GBAWriteAsync(const u8* src, u8* status, FGBACallback&& callback) { EJoyReturn ThreadLocalEndpoint::GBAWriteAsync(ReadWriteBuffer src, u8* status, FGBACallback&& callback) {
if (!m_ep.m_running || m_ep.m_cmdIssued) if (!m_ep.m_running || m_ep.m_cmdIssued)
return GBA_NOT_READY; return GBA_NOT_READY;
m_ep.m_cmdIssued = true; m_ep.m_cmdIssued = true;
m_ep.m_statusPtr = status; m_ep.m_statusPtr = status;
m_ep.m_buffer[0] = Endpoint::CMD_WRITE; m_ep.m_buffer[0] = Endpoint::CMD_WRITE;
for (int i = 0; i < 4; ++i) for (size_t i = 0; i < src.size(); ++i) {
m_ep.m_buffer[i + 1] = src[i]; m_ep.m_buffer[i + 1] = src[i];
}
m_ep.m_callback = std::move(callback); m_ep.m_callback = std::move(callback);
return GBA_READY; return GBA_READY;

View File

@@ -1,9 +1,19 @@
#include "jbus/Listener.hpp" #include "jbus/Listener.hpp"
#include <cstdint>
#include "jbus/Common.hpp"
#include "jbus/Endpoint.hpp" #include "jbus/Endpoint.hpp"
#define LOG_LISTENER 0 #define LOG_LISTENER 0
#if LOG_LISTENER
#include <cstdio>
#endif
namespace jbus { namespace jbus {
constexpr uint32_t DataPort = 0xd6ba;
constexpr uint32_t ClockPort = 0xc10c;
void Listener::listenerProc() { void Listener::listenerProc() {
#if LOG_LISTENER #if LOG_LISTENER
@@ -23,7 +33,7 @@ void Listener::listenerProc() {
WaitGCTicks(GetGCTicksPerSec()); WaitGCTicks(GetGCTicksPerSec());
} else { } else {
#if LOG_LISTENER #if LOG_LISTENER
printf("data listening on port %d\n", DataPort); printf("data listening on port %u\n", DataPort);
#endif #endif
} }
} }
@@ -36,7 +46,7 @@ void Listener::listenerProc() {
WaitGCTicks(GetGCTicksPerSec()); WaitGCTicks(GetGCTicksPerSec());
} else { } else {
#if LOG_LISTENER #if LOG_LISTENER
printf("clock listening on port %d\n", ClockPort); printf("clock listening on port %u\n", ClockPort);
#endif #endif
} }
} }
@@ -58,7 +68,7 @@ void Listener::listenerProc() {
#endif #endif
} }
if (acceptData && acceptClock) { if (acceptData && acceptClock) {
std::unique_lock<std::mutex> lk(m_queueLock); std::unique_lock lk{m_queueLock};
m_endpointQueue.push(std::make_unique<Endpoint>(0, std::move(acceptData), std::move(acceptClock))); m_endpointQueue.push(std::make_unique<Endpoint>(0, std::move(acceptData), std::move(acceptClock)));
} }
WaitGCTicks(GetGCTicksPerSec()); WaitGCTicks(GetGCTicksPerSec());
@@ -74,7 +84,7 @@ void Listener::listenerProc() {
void Listener::start() { void Listener::start() {
stop(); stop();
m_running = true; m_running = true;
m_listenerThread = std::thread(std::bind(&Listener::listenerProc, this)); m_listenerThread = std::thread(&Listener::listenerProc, this);
} }
void Listener::stop() { void Listener::stop() {
@@ -84,16 +94,18 @@ void Listener::stop() {
} }
std::unique_ptr<Endpoint> Listener::accept() { std::unique_ptr<Endpoint> Listener::accept() {
std::unique_lock<std::mutex> lk(m_queueLock); std::unique_lock lk{m_queueLock};
if (m_endpointQueue.size()) { if (m_endpointQueue.empty()) {
std::unique_ptr<Endpoint> ret; return nullptr;
ret = std::move(m_endpointQueue.front()); }
auto ret = std::move(m_endpointQueue.front());
m_endpointQueue.pop(); m_endpointQueue.pop();
return ret; return ret;
}
return {};
} }
Listener::Listener() = default;
Listener::~Listener() { stop(); } Listener::~Listener() { stop(); }
} // namespace jbus } // namespace jbus

View File

@@ -1,13 +1,19 @@
#include "jbus/Socket.hpp" #include "jbus/Socket.hpp"
#include <cstdio>
#include <cstring>
#ifndef _WIN32 #ifndef _WIN32
#include <sys/socket.h> #include <cerrno>
#include <arpa/inet.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <arpa/inet.h> #include <sys/socket.h>
#include <netdb.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <cerrno>
#else #else
#include <WinSock2.h> #include <WinSock2.h>
#include <Ws2tcpip.h> #include <Ws2tcpip.h>
@@ -42,11 +48,10 @@ void IPAddress::resolve(const std::string& address) noexcept {
m_valid = true; m_valid = true;
} else { } else {
/* Not a valid address, try to convert it as a host name */ /* Not a valid address, try to convert it as a host name */
addrinfo hints; addrinfo hints = {};
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET; hints.ai_family = AF_INET;
addrinfo* result = NULL; addrinfo* result = nullptr;
if (getaddrinfo(address.c_str(), NULL, &hints, &result) == 0) { if (getaddrinfo(address.c_str(), nullptr, &hints, &result) == 0) {
if (result) { if (result) {
addr = reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr; addr = reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr;
freeaddrinfo(result); freeaddrinfo(result);
@@ -61,8 +66,7 @@ void IPAddress::resolve(const std::string& address) noexcept {
uint32_t IPAddress::toInteger() const noexcept { return ntohl(m_address); } uint32_t IPAddress::toInteger() const noexcept { return ntohl(m_address); }
static sockaddr_in createAddress(uint32_t address, unsigned short port) { static sockaddr_in createAddress(uint32_t address, unsigned short port) {
sockaddr_in addr; sockaddr_in addr = {};
memset(&addr, 0, sizeof(addr));
addr.sin_addr.s_addr = htonl(address); addr.sin_addr.s_addr = htonl(address);
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_port = htons(port); addr.sin_port = htons(port);
@@ -102,7 +106,7 @@ void Socket::setRemoteSocket(int remSocket) noexcept {
} }
#ifdef _WIN32 #ifdef _WIN32
Socket::EResult Socket::LastWSAError() { Socket::EResult Socket::LastWSAError() noexcept {
switch (WSAGetLastError()) { switch (WSAGetLastError()) {
case WSAEWOULDBLOCK: case WSAEWOULDBLOCK:
case WSAEALREADY: case WSAEALREADY: