BizHawk/waterbox/ares64/ares/nall/tcptext/tcp-socket.hpp

66 lines
2.0 KiB
C++

#pragma once
/**
* Opens a TCP server with callbacks to send and receive data.
*
* This spawns 3 new threads:
* threadServer: listens for new connections, kicks connections
* threadSend: sends data to the client
* threadReceive: receives data from the client
*
* Each contains it's own loop including sleeps to not use too much CPU.
* The exception is threadReceive which relies on the blocking recv() call (kernel wakes it up again).
*
* Incoming and outgoing data is synchronized using mutexes,
* and put into buffers that are shared with the main thread.
* Meaning, the thread that calls 'update()' with also be the one that gets 'onData()' calls.
* No additional synchronization is needed.
*
* NOTE: if you work on the loop/sleeps, make sure to test CPU usage and package-latency.
*/
namespace nall::TCP {
class Socket {
public:
auto open(u32 port, bool useIPv4) -> bool;
auto close(bool notifyHandler = true) -> void;
auto disconnectClient() -> void;
auto isStarted() const -> bool { return serverRunning; }
auto hasClient() const -> bool { return fdClient >= 0; }
auto getURL(u32 port, bool useIPv4) const -> string;
~Socket() { close(false); }
protected:
auto update() -> void;
auto sendData(const u8* data, u32 size) -> void;
virtual auto onData(const vector<u8> &data) -> void = 0;
virtual auto onConnect() -> void = 0;
virtual auto onDisconnect() -> void = 0;
private:
std::atomic<bool> stopServer{false}; // set to true to let the server-thread know to stop.
std::atomic<bool> serverRunning{false}; // signals the current state of the server-thread
std::atomic<bool> wantKickClient{false}; // set to true to let server know to disconnect the current client (if conn.)
std::atomic<s32> fdServer{-1};
std::atomic<s32> fdClient{-1};
vector<u8> receiveBuffer{};
std::mutex receiveBufferMutex{};
vector<u8> sendBuffer{};
std::mutex sendBufferMutex{};
};
}
#if defined(NALL_HEADER_ONLY)
#include <nall/tcptext/tcp-socket.cpp>
#endif