ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
session_host.cpp
Go to the documentation of this file.
1#include <emscripten/bind.h>
2#include "protocol_bytes.h"
3extern "C" {
4#include <ascii-chat/common.h>
8#include "session/host.h"
9}
10#include <emscripten.h>
11#include <array>
12#include <cstdint>
13#include <vector>
14
15EM_JS(void, browser_host_send, (uint32_t client, const uint8_t *data, size_t length), {
16 if (Module.hostPacketCallback)
17 Module.hostPacketCallback(client, HEAPU8.slice(data, data + length));
18});
19
21 session_host_t *host = nullptr;
22 std::array<acip_transport_t, MAX_SESSION_PARTICIPANTS> transports{};
23 std::array<uint32_t, MAX_SESSION_PARTICIPANTS> client_ids{};
24 void reset() {
26 host = nullptr;
27 client_ids.fill(0);
28 transports.fill({});
29 }
31 reset();
32 }
33};
34static BrowserHostState state;
35static asciichat_error_t host_transport_send(acip_transport_t *transport, const void *data, size_t length) {
36 if (!transport || !data || !length)
37 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid browser host packet");
38 browser_host_send((uint32_t)(uintptr_t)transport->impl_data, static_cast<const uint8_t *>(data), length);
39 return ASCIICHAT_OK;
40}
41static bool connected(acip_transport_t *transport) {
42 return state.host != NULL;
43}
44static socket_t no_socket(acip_transport_t *transport) {
45 return INVALID_SOCKET_VALUE;
46}
47static acip_transport_type_t transport_type(acip_transport_t *transport) {
49}
50static const acip_transport_methods_t methods = [] {
52 result.send = host_transport_send;
53 result.is_connected = connected;
54 result.get_socket = no_socket;
55 result.get_type = transport_type;
56 return result;
57}();
58
59static void browser_host_destroy(void) {
60 state.reset();
61}
62static asciichat_error_t browser_host_create(void) {
63 browser_host_destroy();
64 session_host_config_t config{};
66 state.host = session_host_create(&config);
67 if (!state.host)
68 return SET_ERRNO(ERROR_MEMORY, "Cannot create browser session host");
69 return session_host_render_audio(state.host);
70}
71static uint32_t browser_host_add_client(void) {
72 if (!state.host) {
73 SET_ERRNO(ERROR_INVALID_STATE, "Browser host is not initialized");
74 return 0;
75 }
76 for (size_t i = 0; i < MAX_SESSION_PARTICIPANTS; ++i) {
77 if (state.client_ids[i])
78 continue;
79 uint32_t id = session_host_add_client(state.host, NULL, ACIP_TRANSPORT_BORROWED, "browser", 0);
80 if (!id)
81 return 0;
82 state.client_ids[i] = id;
83 state.transports[i] = {};
84 state.transports[i].methods = &methods;
85 state.transports[i].impl_data = reinterpret_cast<void *>(static_cast<uintptr_t>(id));
86 if (session_host_set_client_transport(state.host, id, &state.transports[i], ACIP_TRANSPORT_BORROWED) !=
88 session_host_remove_client(state.host, id);
89 state.client_ids[i] = 0;
90 return 0;
91 }
92 return id;
93 }
94 SET_ERRNO(ERROR_INVALID_STATE, "Browser session host has no available client slots");
95 return 0;
96}
97static void browser_host_remove_client(uint32_t id) {
98 if (!state.host)
99 return;
100 session_host_remove_client(state.host, id);
101 for (size_t i = 0; i < MAX_SESSION_PARTICIPANTS; ++i)
102 if (state.client_ids[i] == id)
103 state.client_ids[i] = 0;
104}
105static asciichat_error_t browser_host_set_local_client(uint32_t id) {
107 target.client_id = id;
108 return session_host_set_render_target(state.host, id ? &target : NULL);
109}
110static asciichat_error_t browser_host_receive(uint32_t id, uint32_t type, const void *data, size_t length) {
111 if (!state.host || !id || !data)
112 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid browser host packet or client");
113 return session_host_receive_packet(state.host, id, static_cast<packet_type_t>(type), data, length);
114}
115static asciichat_error_t browser_host_render(void) {
116 return session_host_render_video(state.host);
117}
118static asciichat_error_t browser_host_render_audio(void) {
119 return session_host_render_audio(state.host);
120}
121
122// Browser host packets arrive at frame rate. Retain their backing storage.
124public:
125 int receive(unsigned id, unsigned type, ProtocolBytes packet) {
126 const size_t length = packet["length"].as<size_t>();
127 input_.resize(length ? length : 1);
128 if (length)
129 emscripten::val(emscripten::typed_memory_view(length, input_.data())).call<void>("set", packet);
130 return browser_host_receive(id, type, input_.data(), length);
131 }
132
133private:
134 std::vector<uint8_t> input_;
135};
136
137EMSCRIPTEN_BINDINGS(ascii_chat_session_host) {
138 emscripten::function("browser_host_create", +[]() { return static_cast<int>(browser_host_create()); });
139 emscripten::function("browser_host_destroy", &browser_host_destroy);
140 emscripten::function("browser_host_add_client", &browser_host_add_client);
141 emscripten::function(
142 "browser_host_set_local_client",
143 +[](uint32_t id) { return static_cast<int>(browser_host_set_local_client(id)); });
144 emscripten::function("browser_host_remove_client", &browser_host_remove_client);
145 emscripten::function("browser_host_render", +[]() { return static_cast<int>(browser_host_render()); });
146 emscripten::function("browser_host_render_audio", +[]() { return static_cast<int>(browser_host_render_audio()); });
147 emscripten::class_<HostPacketBinding>("HostPacketBinding")
148 .constructor<>()
149 .function("receive", &HostPacketBinding::receive);
150}
ascii-chat Discovery Service (ACDS) Protocol Message Formats
ACIP client-side protocol library and ACDS client connection API.
#define SET_ERRNO(code,...)
int receive(unsigned id, unsigned type, ProtocolBytes packet)
⚙️ Common definitions, error codes, macros, and types shared throughout the application
unsigned int uint32_t
Definition common.h:62
unsigned char uint8_t
Definition common.h:60
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
@ ERROR_INVALID_STATE
@ ERROR_MEMORY
Definition error_codes.h:51
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_INVALID_PARAM
#define MAX_SESSION_PARTICIPANTS
packet_type_t
Network protocol packet type enumeration.
Definition packet.h:301
asciichat_error_t session_host_destroy(session_host_t *host)
Destroy session host and free resources.
Definition host.c:289
asciichat_error_t session_host_set_client_transport(session_host_t *host, uint32_t client_id, acip_transport_t *transport, acip_transport_ownership_t ownership)
Select a transport for a specific client in the host.
Definition host.c:1703
struct session_host session_host_t
Opaque session host handle.
struct acip_transport acip_transport_t
Forward declaration of ACIP transport.
Definition host.h:506
asciichat_error_t session_host_remove_client(session_host_t *host, uint32_t client_id)
Remove a client by ID.
Definition host.c:1385
session_host_t * session_host_create(const session_host_config_t *config)
Create a new session host.
Definition host.c:234
asciichat_error_t session_host_render_audio(session_host_t *host)
Definition host.c:817
asciichat_error_t session_host_render_video(session_host_t *host)
Definition host.c:810
uint32_t session_host_add_client(session_host_t *host, acip_transport_t *transport, acip_transport_ownership_t ownership, const char *ip, int port)
Definition host.c:1129
asciichat_error_t session_host_set_render_target(session_host_t *host, const session_host_render_target_t *target)
Definition host.c:1550
asciichat_error_t session_host_receive_packet(session_host_t *host, uint32_t client_id, packet_type_t ptype, const void *data, size_t len)
Definition host.c:343
🏠 Server-side session hosting abstraction
int socket_t
Transport abstraction layer for ACIP protocol.
acip_transport_type_t
Transport method table (virtual function table).
@ ACIP_TRANSPORT_WEBRTC
WebRTC DataChannel (P2P).
EMSCRIPTEN_BINDINGS(ascii_chat_session_host)
EM_JS(void, browser_host_send,(uint32_t client, const uint8_t *data, size_t length), { if(Module.hostPacketCallback) Module.hostPacketCallback(client, HEAPU8.slice(data, data+length));})
std::array< acip_transport_t, MAX_SESSION_PARTICIPANTS > transports
std::array< uint32_t, MAX_SESSION_PARTICIPANTS > client_ids
session_host_t * host
Transport method table (virtual function table).
asciichat_error_t(* send)(acip_transport_t *transport, const void *data, size_t len)
Send data through this transport.
bool(* is_connected)(acip_transport_t *transport)
Check if transport is connected.
socket_t(* get_socket)(acip_transport_t *transport)
Get underlying socket (if applicable).
acip_transport_type_t(* get_type)(acip_transport_t *transport)
Get transport type.
void * impl_data
Transport-specific state.
Host-side event hooks for joins, departures, media, and errors.
Definition host.h:159
int max_clients
Maximum number of clients.
Definition host.h:170
session host render target is intentionally a small, concrete record. Fields such as client_id,...
Definition host.h:450