ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
networking.cpp
Go to the documentation of this file.
1#include <emscripten/bind.h>
2extern "C" {
3#include "../client.h"
4#include "../security.h"
6}
7#include "networking.h"
8#include "../common/opts.h"
9#include "byte_arrays.h"
10#include <sodium.h>
11#include <array>
12#include <cstddef>
13#include <cstdint>
14#include <string>
15#include <optional>
16#include <vector>
17
18static int init_client(OptionsPatch options) {
19 int result = client_init();
20 if (result)
21 SET_ERRNO(ERROR_INIT, "Browser client initialization failed");
22 return result ? result : initial_options(options);
23}
24
25// One JS-owned lifetime controls the module-global client handshake state.
27public:
28 explicit ClientSessionBinding(OptionsPatch options) {
29 if (active_) {
30 result_ = SET_ERRNO(ERROR_INVALID_STATE, "Client session is already initialized");
31 return;
32 }
33 result_ = init_client(options);
34 if (!result_) {
35 active_ = true;
36 owned_ = true;
37 }
38 }
40 if (owned_) {
42 active_ = false;
43 }
44 }
47 bool valid() const {
48 return owned_;
49 }
50 int error() const {
51 return result_;
52 }
53
54private:
55 static bool active_;
56 bool owned_ = false;
57 int result_ = 0;
58};
59bool ClientSessionBinding::active_ = false;
60
61QuicControlResult network_quic_output(crypto_context_t *context) {
62 uint8_t data[256];
63 size_t length = 0;
64 uint32_t flow = 0;
65 const int code = browser_security_output(context, data, sizeof(data), &length, &flow);
66 emscripten::val result = emscripten::val::object();
67 result.set("code", code);
68 result.set("flow", flow);
69 result.set("packet", length ? binding_copy_output(data, length) : emscripten::val::null());
70 return QuicControlResult(result);
71}
72
73QuicPacketResult network_quic_packet(crypto_context_t *context, bool seal, unsigned flow, unsigned delivery,
74 PeerBytes packet) {
75 auto input_data = binding_copy_input(packet);
76 std::vector<uint8_t> output(input_data.size() + (seal ? 94 : 0));
77 size_t length = 0;
78 uint64_t sequence = 0;
79 int code = browser_security_packet(context, seal, flow, delivery, input_data.data(), input_data.size(), output.data(),
80 output.size(), &length, &sequence);
81 emscripten::val result = emscripten::val::object();
82 result.set("code", code);
83 result.set("packet", binding_copy_output(output.data(), length));
84 result.set("sequence", emscripten::val::global("BigInt")(std::to_string(sequence)));
85 if (!input_data.empty())
86 sodium_memzero(input_data.data(), input_data.size());
87 if (!output.empty())
88 sodium_memzero(output.data(), output.size());
89 return QuicPacketResult(result);
90}
91
92static int client_quic_init() {
94}
95static int client_quic_tick() {
97}
98static double client_quic_epoch() {
100}
101static QuicControlResult client_quic_output() {
103}
104static QuicPacketResult client_quic_packet(bool seal, unsigned flow, unsigned delivery, PeerBytes packet) {
105 return network_quic_packet(client_security_context(), seal, flow, delivery, packet);
106}
107
108static int set_server_address(const std::string &host, int port) {
109 if (host.empty() || port <= 0 || port > 65535)
110 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid client server address or port");
111 const int result = client_set_server_address(host.c_str(), port);
112 if (result)
113 SET_ERRNO(ERROR_INVALID_STATE, "Cannot set client server address");
114 return result;
115}
116static std::optional<std::string> client_public_key() {
117 const uint8_t *key = client_public_key_bytes();
118 if (!key) {
119 SET_ERRNO(ERROR_CRYPTO_KEY, "Cannot get client public key");
120 return std::nullopt;
121 }
122 std::array<char, 65> hex{};
123 sodium_bin2hex(hex.data(), hex.size(), key, 32);
124 return std::string(hex.data());
125}
126
127EMSCRIPTEN_BINDINGS(ascii_chat_network) {
128 emscripten::function("initClient", &init_client);
129 emscripten::class_<ClientSessionBinding>("ClientSessionBinding")
130 .constructor<OptionsPatch>()
131 .function("valid", &ClientSessionBinding::valid)
132 .function("error", &ClientSessionBinding::error);
133
134 emscripten::function("client_cleanup", &client_cleanup);
135 emscripten::function("client_generate_keypair", &client_generate_keypair);
136 emscripten::function("client_get_connection_state", &client_get_connection_state);
137 emscripten::function("client_resolve_crypto_policy", &client_resolve_crypto_policy);
138 emscripten::function("client_handshake_begin", +[]() { return static_cast<int>(client_handshake_begin()); });
139 emscripten::function(
140 "client_acds_handshake_begin", +[](uint8_t mode) { return static_cast<int>(client_acds_handshake_begin(mode)); });
141 emscripten::function(
142 "network_error_action",
143 +[](int code) { return static_cast<int>(network_error_action(static_cast<asciichat_error_t>(code))); });
144 emscripten::function("setServerAddress", &set_server_address);
145 emscripten::function("clientPublicKey", &client_public_key);
146
147 emscripten::register_type<QuicControlResult>("QuicControlResult",
148 "{ code: number; flow: number; packet: Uint8Array | null }");
149 emscripten::register_type<QuicPacketResult>("QuicPacketResult",
150 "{ code: number; sequence: bigint; packet: Uint8Array }");
151 emscripten::function("clientQuicInit", &client_quic_init);
152 emscripten::function("clientQuicTick", &client_quic_tick);
153 emscripten::function("clientQuicEpoch", &client_quic_epoch);
154 emscripten::function("clientQuicOutput", &client_quic_output);
155 emscripten::function("clientQuicPacket", &client_quic_packet);
156}
#define SET_ERRNO(code,...)
emscripten::val binding_copy_output(const void *data, size_t length)
Definition byte_arrays.h:18
std::vector< uint8_t > binding_copy_input(emscripten::val bytes)
Definition byte_arrays.h:6
ClientSessionBinding(const ClientSessionBinding &)=delete
ClientSessionBinding(OptionsPatch options)
ClientSessionBinding & operator=(const ClientSessionBinding &)=delete
unsigned int uint32_t
Definition common.h:62
unsigned long long uint64_t
Definition common.h:63
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_CRYPTO_KEY
Definition error_codes.h:94
@ ERROR_INIT
Definition error_codes.h:56
@ ERROR_INVALID_PARAM
Network error handling utilities.
network_error_action_t network_error_action(asciichat_error_t code)
EMSCRIPTEN_BINDINGS(ascii_chat_network)
QuicControlResult network_quic_output(crypto_context_t *context)
QuicPacketResult network_quic_packet(crypto_context_t *context, bool seal, unsigned flow, unsigned delivery, PeerBytes packet)
int initial_options(OptionsPatch patch)
Definition opts.cpp:28
crypto_context_t * client_security_context(void)
const uint8_t * client_public_key_bytes(void)
int client_resolve_crypto_policy(bool secure, int encryption)
void client_cleanup(void)
int client_set_server_address(const char *server_host, int server_port)
int client_get_connection_state(void)
int client_init(void)
int client_generate_keypair(void)
asciichat_error_t client_acds_handshake_begin(uint8_t mode)
asciichat_error_t client_handshake_begin(void)
double browser_security_epoch(crypto_context_t *ctx)
asciichat_error_t browser_security_packet(crypto_context_t *ctx, bool seal, uint32_t channel, uint32_t delivery, const uint8_t *packet, size_t length, uint8_t *output, size_t capacity, size_t *out_length, uint64_t *sequence)
asciichat_error_t browser_security_output(crypto_context_t *ctx, uint8_t *output, size_t capacity, size_t *length, uint32_t *channel)
asciichat_error_t browser_security_tick(crypto_context_t *ctx)
asciichat_error_t browser_security_init(crypto_context_t *ctx)
Endpoint cryptographic state for handshake, packet protection, authentication, and rekeying.