blob: f1806f0992174f57fedb0d02c5c1309435d47ba8 [file] [log] [blame] [edit]
/*
* Copyright 2024 Rive
*/
#pragma once
#include <memory>
#include <string>
#include <stdint.h>
#ifdef __EMSCRIPTEN__
#include <emscripten/websocket.h>
#include <arpa/inet.h>
#include <deque>
#define SOCKET EMSCRIPTEN_WEBSOCKET_T
#elif defined(_WIN32)
#include "WinSock2.h"
#else
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define SOCKET int
#endif
// Simple utility for connecting a tool to its python harness via TCP socket.
class TCPClient
{
public:
constexpr static uint32_t HANDSHAKE_TOKEN = 0xfee1600d;
constexpr static uint32_t SHUTDOWN_TOKEN = 0xfee1dead;
static std::unique_ptr<TCPClient> Connect(
const char* serverAddress /*server:port*/);
~TCPClient();
const char* serverAddress() const { return m_serverAddress.c_str(); }
std::unique_ptr<TCPClient> clone() const;
void sendall(const void* data, size_t byteCount);
void recvall(void* data, size_t byteCount);
// Send a 4-byte uint32_t to the server.
void send4(uint32_t);
// Receive a 4-byte uint32_t to the server.
uint32_t recv4();
// Send "HANDSHAKE_TOKEN" to the server.
void sendHandshake();
// Read 4 bytes from the server and verify they are "HANDSHAKE_TOKEN".
void recvHandshake();
void sendString(const std::string& str);
std::string recvString();
private:
TCPClient(const char* serverAddress /*server:port*/, bool* success);
uint32_t send(const char* data, uint32_t size);
uint32_t recv(char* buff, uint32_t size);
#ifdef _WIN32
static int GetLastError() { return WSAGetLastError(); }
#else
static int GetLastError() { return errno; }
#endif
const std::string m_serverAddress;
SOCKET m_sockfd;
#ifdef __EMSCRIPTEN__
static EM_BOOL OnWebSocketOpen(int eventType,
const EmscriptenWebSocketOpenEvent* e,
void* userData);
static EM_BOOL OnWebSocketMessage(int eventType,
const EmscriptenWebSocketMessageEvent*,
void* userData);
static EM_BOOL OnWebSocketError(int eventType,
const EmscriptenWebSocketErrorEvent*,
void* userData);
enum class WebSocketStatus
{
pendingConnection,
open,
error,
};
WebSocketStatus m_webSocketStatus = WebSocketStatus::pendingConnection;
std::deque<uint8_t> m_serverMessages;
#endif
};