#pragma once /** ** \defgroup ssb SSB ** Everything about SSB, SHS, and MUXRPC happens here. ** @{ */ #include "quickjs.h" #include #include #include enum { k_ssb_rpc_flag_binary = 0x0, k_ssb_rpc_flag_utf8 = 0x1, k_ssb_rpc_flag_json = 0x2, k_ssb_rpc_mask_type = 0x3, k_ssb_rpc_flag_end_error = 0x4, k_ssb_rpc_flag_stream = 0x8, k_ssb_rpc_mask_message = 0xC, k_ssb_rpc_mask_send = 0xf, k_ssb_rpc_flag_new_request = 0x10, k_ssb_blob_bytes_max = 5 * 1024 * 1024, }; /** ** The type of change to a set of connections. */ typedef enum _tf_ssb_change_t { k_tf_ssb_change_create, k_tf_ssb_change_connect, k_tf_ssb_change_remove, } tf_ssb_change_t; /** ** Flags describing the structure of a message. */ typedef enum _tf_ssb_message_flags_t { /** ** The sequence field precedes the author field if specified. The ** other way around, otherwise. */ k_tf_ssb_message_flag_sequence_before_author = 1, } tf_ssb_message_flags_t; /** An SSB instance. */ typedef struct _tf_ssb_t tf_ssb_t; /** An SSB connection. */ typedef struct _tf_ssb_connection_t tf_ssb_connection_t; /** A trace instance. */ typedef struct _tf_trace_t tf_trace_t; /** An SQLite database handle. */ typedef struct sqlite3 sqlite3; /** An event loop. */ typedef struct uv_loop_s uv_loop_t; /** A socket address. */ struct sockaddr_in; enum { k_id_base64_len = 57, k_id_bin_len = 32, k_blob_id_len = 53, }; /** ** Statistics about an SSB instance. */ typedef struct _tf_ssb_stats_t { /** Number of active connections. */ int connections; /** Number of active hosts discovered by network broadcast. */ int broadcasts; /** Number of messages stored. */ int messages_stored; /** Number of blobs stored. */ int blobs_stored; /** Number of RPC messages received. */ int rpc_in; /** Number of RPC messages sent. */ int rpc_out; /** Number of active RPC requests. */ int request_count; /** Number of callbacks registered. */ struct { int rpc; int connections_changed; int message_added; int blob_want_added; int broadcasts_changed; } callbacks; } tf_ssb_stats_t; /** ** State about requesting blobs. */ typedef struct _tf_ssb_blob_wants_t { /** The request number of the blob.wants RPC call. */ int32_t request_number; /** The number of blob wants we are waiting for a response to. */ int wants_sent; /** The last blob ID considered. */ char last_id[k_blob_id_len]; } tf_ssb_blob_wants_t; /** ** A queue for storing messages. */ typedef struct _tf_ssb_store_queue_t { /** The first node in the queue. */ void* head; /** The last node in the queue. */ void* tail; /** Whether the queue is currently running. */ bool running; } tf_ssb_store_queue_t; /** ** Create an SSB instance. ** @param loop The event loop to use or NULL to create a new one. ** @param context The JS context to use or NULL to create a new one. ** @param db_path The path to the SQLite database to use. ** @param network_key The SSB network key to use or NULL to use the standard key. */ tf_ssb_t* tf_ssb_create(uv_loop_t* loop, JSContext* context, const char* db_path, const char* network_key); /** ** Destroy an SSB instance. ** @param ssb The SSB instance to destroy. */ void tf_ssb_destroy(tf_ssb_t* ssb); /** ** Start optional periodic work. ** @param ssb The SSB instance. */ void tf_ssb_start_periodic(tf_ssb_t* ssb); /** ** Control logging verbosity. ** @param ssb The SSB instance. ** @param verbose True to log messages for every RPC message sent and received. */ void tf_ssb_set_verbose(tf_ssb_t* ssb, bool verbose); /** ** Acquire an SQLite database for unrestricted reading. Release qith tf_ssb_release_db_reader(). ** @param ssb The SSB instance. ** @return A database with full read access to the database. */ sqlite3* tf_ssb_acquire_db_reader(tf_ssb_t* ssb); /** ** Acquire an SQLite database for restricted reading. Release qith ** tf_ssb_release_db_reader(). ** @param ssb The SSB instance. ** @return A database with read access to a safe subset of the database. */ sqlite3* tf_ssb_acquire_db_reader_restricted(tf_ssb_t* ssb); /** ** Release a database acquired with tf_ssb_acquire_db_reader() or ** tf_ssb_acquire_db_reader_restricted(). ** @param ssb The SSB instance. ** @param db The database. */ void tf_ssb_release_db_reader(tf_ssb_t* ssb, sqlite3* db); /** ** Acquire an SQLite database with full write access to the database. Release ** with tf_ssb_release_db_writer(). ** @param ssb The SSB instance. ** @return The writable database. */ sqlite3* tf_ssb_acquire_db_writer(tf_ssb_t* ssb); /** ** Release a database acquired with tf_ssb_acquire_db_writer(). ** @param ssb The SSB instance. ** @param db The database. */ void tf_ssb_release_db_writer(tf_ssb_t* ssb, sqlite3* db); /** ** Get the SSB instance's event loop. ** @param ssb The SSB instance. ** @return The loop. */ uv_loop_t* tf_ssb_get_loop(tf_ssb_t* ssb); /** ** Generate a public/private key pair for the SSB instance. ** @param ssb The SSB instance. */ void tf_ssb_generate_keys(tf_ssb_t* ssb); /** ** Generate a public/private key pair and store in buffers. ** @param[out] out_public Buffer to receive the public key. ** @param public_size Size of the public key buffer. ** @param[out] out_private Buffer to receive the private key. ** @param private_size Size of the private key buffer. */ void tf_ssb_generate_keys_buffer(char* out_public, size_t public_size, char* out_private, size_t private_size); /** ** Get the private key of the SSB instance. ** @param ssb The SSB instance. ** @param[out] out_private Buffer to receive the private key. ** @param private_size The size of the private key buffer. */ void tf_ssb_get_private_key(tf_ssb_t* ssb, uint8_t* out_private, size_t private_size); /** ** Set the trace instance to use for the SSB instance. ** @param ssb The SSB instance. ** @param trace The trace instance to use. */ void tf_ssb_set_trace(tf_ssb_t* ssb, tf_trace_t* trace); /** ** Get the SSB instance's trace instance. ** @param ssb The SSB instance. ** @return The trace instance. */ tf_trace_t* tf_ssb_get_trace(tf_ssb_t* ssb); /** ** Get the SSB istance's JS context. ** @param ssb The SSB instance. ** @return The JS context. */ JSContext* tf_ssb_get_context(tf_ssb_t* ssb); /** ** Begin listening for SSB discovery messages. ** @param ssb The SSB instance. ** @param linger True if listening for broadcasts should keep the event loop alive. */ void tf_ssb_broadcast_listener_start(tf_ssb_t* ssb, bool linger); /** ** Begin sending SSB discovevry messages. ** @param ssb The SSB instance. */ void tf_ssb_broadcast_sender_start(tf_ssb_t* ssb); /** ** Run the SSB instance until there is no work to do or stopped. ** @param ssb The SSB instance. */ void tf_ssb_run(tf_ssb_t* ssb); /** ** Sign an SSB message. ** @param ssb The SSB instance. ** @param author The author's public key. ** @param private_key The author's private key. ** @param message The message to sign. ** @return The signed message. */ JSValue tf_ssb_sign_message(tf_ssb_t* ssb, const char* author, const uint8_t* private_key, JSValue message); /** ** Get the server's identity. ** @param ssb The SSB instance. ** @param[out] out_id A buffer populated with the identity. ** @param out_id_size The size of the identity buffer. ** @return True if the identity was successfully retrieved. */ bool tf_ssb_whoami(tf_ssb_t* ssb, char* out_id, size_t out_id_size); /** ** Call a callback for each active host discovered by network discovery broadcast. ** @param ssb The SSB instance. ** @param callback The callback. ** @param user_data User data for the callback. */ void tf_ssb_visit_broadcasts( tf_ssb_t* ssb, void (*callback)(const char* host, const struct sockaddr_in* addr, tf_ssb_connection_t* tunnel, const uint8_t* pub, void* user_data), void* user_data); /** ** Get the identities of all active connections. ** @param ssb The SSB instance. ** @return A NULL-terminated array of SSB identities. Free with tf_free(). */ const char** tf_ssb_get_connection_ids(tf_ssb_t* ssb); /** ** Retrieve a list of active connections. ** @param ssb The SSB instance. ** @param[out] out_connections An array to be populated with the connections. ** @param out_connections_count The size of the connections array. ** @return The number of connections populated in out_connections. */ int tf_ssb_get_connections(tf_ssb_t* ssb, tf_ssb_connection_t** out_connections, int out_connections_count); /** ** Establish an SHS connection with a host. ** @param ssb The SSB instance. ** @param host The host name or address. ** @param port The host's SHS port. ** @param key The host's SSB identity. */ void tf_ssb_connect(tf_ssb_t* ssb, const char* host, int port, const uint8_t* key); /** ** Establish an SHS connection with a host by string address. ** @param ssb The SSB instance. ** @param address The address. */ void tf_ssb_connect_str(tf_ssb_t* ssb, const char* address); /** ** Begin listening for SHS connections on the given port. ** @param ssb The SSB instance. ** @param port The port number. ** @return The assigned port on success or 0 on failure. */ int tf_ssb_server_open(tf_ssb_t* ssb, int port); /** ** Stop listening for SHS connections. ** @param ssb The SSB instance. */ void tf_ssb_server_close(tf_ssb_t* ssb); /** ** Close all active SHS connections. ** @param ssb The SSB instance. */ void tf_ssb_close_all(tf_ssb_t* ssb); /** ** Send a graceful close message to all active SHS connections. ** @param ssb The SSB instance. */ void tf_ssb_send_close(tf_ssb_t* ssb); /** ** Convert an SSB identity from string to binary. ** @param[out] bin A buffer to receive the binary identity. ** @param str The string identity. ** @return True if the conversion was successful. */ bool tf_ssb_id_str_to_bin(uint8_t* bin, const char* str); /** ** Convert an SSB identity from binary to string. ** @param[out] str A buffer to receive the identity string. ** @param str_size The size of the string buffer. ** @param bin The binary identity. ** @return True if the conversion was successful. */ bool tf_ssb_id_bin_to_str(char* str, size_t str_size, const uint8_t* bin); /** ** Verify a message's signature and remove the signature if successful. ** @param context A JS context. ** @param val The message. ** @param[out] out_id A buffer to receive the message's identity. ** @param out_id_size The size of out_id. ** @param[out] out_signature A buffer to receive the message's signature. ** @param out_signature_size The size of out_signature. ** @param[out] out_flags tf_ssb_message_flags_t describing the message. ** @return True if the signature is valid and was successfully extracted. */ bool tf_ssb_verify_and_strip_signature(JSContext* context, JSValue val, char* out_id, size_t out_id_size, char* out_signature, size_t out_signature_size, int* out_flags); /** ** Determine the message identifier. ** @param context A JS context. ** @param message The message. ** @param[out] out_id A buffer to receive the identifier. ** @param out_id_size The size of out_id. */ void tf_ssb_calculate_message_id(JSContext* context, JSValue message, char* out_id, size_t out_id_size); /** ** A function called on completion of tf_ssb_verify_strip_and_store_message(). ** @param id The stored message identifier. ** @param verified True if the message was verified successfully. ** @param is_new True if the message was newly added to the database. ** @param user_data The user data. */ typedef void(tf_ssb_verify_strip_store_callback_t)(const char* id, bool verified, bool is_new, void* user_data); /** ** Verify a message's signature, remove the signature, and store the message in the database. ** @param ssb The SSB instance. ** @param value The message. ** @param callback A callback called when the operation completed. ** @param user_data User data to pass to the callback. */ void tf_ssb_verify_strip_and_store_message(tf_ssb_t* ssb, JSValue value, tf_ssb_verify_strip_store_callback_t* callback, void* user_data); /** ** Check if a connection is an outgoing connection. ** @param connection The connection. ** @return True if the connection is outgoing. */ bool tf_ssb_connection_is_client(tf_ssb_connection_t* connection); /** ** Get the hostname of the remote end of a connection. ** @param connection The connection. ** @return The hostname or address. */ const char* tf_ssb_connection_get_host(tf_ssb_connection_t* connection); /** ** Get a connection's remote port number. ** @param connection The connection. ** @return The port number. */ int tf_ssb_connection_get_port(tf_ssb_connection_t* connection); /** ** If a connection is a tunnel, get its parent connection. ** @param connection The connection. ** @return The parent connection if the connection is tunneled or NULL. */ tf_ssb_connection_t* tf_ssb_connection_get_tunnel(tf_ssb_connection_t* connection); /** ** Get a connection's SSB instance. ** @param connection The connection. ** @return The SSB instance. */ tf_ssb_t* tf_ssb_connection_get_ssb(tf_ssb_connection_t* connection); /** ** Get a connection's JS context. ** @param connection The connection. ** @return The JS context. */ JSContext* tf_ssb_connection_get_context(tf_ssb_connection_t* connection); /** ** Close a connection. ** @param connection The connection. */ void tf_ssb_connection_close(tf_ssb_connection_t* connection); /** ** Check whether a connection is connected. ** @param connection The connection. ** @return True if the connection is alive. */ bool tf_ssb_connection_is_connected(tf_ssb_connection_t* connection); /** ** Get the next outgoing request number for a connection. ** @param connection The connection. ** @return The next request number. */ int32_t tf_ssb_connection_next_request_number(tf_ssb_connection_t* connection); /** ** Get an active connection by its identity. ** @param ssb The SSB instance. ** @param id The SSB identity. ** @return The connection if found or NULL. */ tf_ssb_connection_t* tf_ssb_connection_get(tf_ssb_t* ssb, const char* id); /** ** Get the SSB identity of a connection. ** @param connection The connection. ** @param[out] out_id A buffer to be populated with the identity. ** @param out_id_size The size of out_id. ** @return True if the identity was retrieved. */ bool tf_ssb_connection_get_id(tf_ssb_connection_t* connection, char* out_id, size_t out_id_size); /** ** Get the JS object representing a connection. ** @param connection The connection. ** @return The object. */ JSValue tf_ssb_connection_get_object(tf_ssb_connection_t* connection); /** ** A callback called when a callback is cleaned up. ** @param ssb The SSB instance. ** @param user_data User data. */ typedef void(tf_ssb_callback_cleanup_t)(tf_ssb_t* ssb, void* user_data); /** ** A callback called when the connection list changes. ** @param ssb The SSB instance. ** @param change The type of change. ** @param connection The connection that changed. ** @param user_data User data. */ typedef void(tf_ssb_connections_changed_callback_t)(tf_ssb_t* ssb, tf_ssb_change_t change, tf_ssb_connection_t* connection, void* user_data); /** ** Register a callback when the connection list changes. ** @param ssb The SSB instance. ** @param callback The callback to register. ** @param cleanup The cleanup callback to register. ** @param user_data User data to pass to the callbacks. */ void tf_ssb_add_connections_changed_callback(tf_ssb_t* ssb, tf_ssb_connections_changed_callback_t* callback, tf_ssb_callback_cleanup_t* cleanup, void* user_data); /** ** Remove a callback when the connection list changes. ** @param ssb The SSB instance. ** @param callback The callback. ** @param user_data The user data registered with the callback. */ void tf_ssb_remove_connections_changed_callback(tf_ssb_t* ssb, tf_ssb_connections_changed_callback_t* callback, void* user_data); /** ** A callback called when a new broadcast is received or one expires. ** @param ssb The SSB instance. ** @param user_data The user data. */ typedef void(tf_ssb_broadcasts_changed_callback_t)(tf_ssb_t* ssb, void* user_data); /** ** Register a callback when broadcasts change. ** @param ssb The SSB instance. ** @param callback The callback function. ** @param cleanup A function to call when the callback is removed. ** @param user_data User data to pass to the callback. */ void tf_ssb_add_broadcasts_changed_callback(tf_ssb_t* ssb, tf_ssb_broadcasts_changed_callback_t* callback, tf_ssb_callback_cleanup_t* cleanup, void* user_data); /** ** Remove a callback registered for when broadcasts changed. ** @param ssb The SSB instance. ** @param callback The callback function. ** @param user_data The user data registered with the callback. */ void tf_ssb_remove_broadcasts_changed_callback(tf_ssb_t* ssb, tf_ssb_broadcasts_changed_callback_t* callback, void* user_data); /** ** A callback called when a message is added to the database. ** @param ssb The SSB instance. ** @param id The message identifier. ** @param user_data The user data. */ typedef void(tf_ssb_message_added_callback_t)(tf_ssb_t* ssb, const char* id, void* user_data); /** ** Register a callback called when a message is added to the database. ** @param ssb The SSB instance. ** @param callback The callback function. ** @param cleanup A function to call when the callback is removed. ** @param user_data User data to pass to the callback. */ void tf_ssb_add_message_added_callback(tf_ssb_t* ssb, tf_ssb_message_added_callback_t* callback, tf_ssb_callback_cleanup_t* cleanup, void* user_data); /** ** Remove a callback registered for when a message is added to the database. ** @param ssb The SSB instance. ** @param callback The callback function. ** @param user_data User data registered with the callback. */ void tf_ssb_remove_message_added_callback(tf_ssb_t* ssb, tf_ssb_message_added_callback_t* callback, void* user_data); /** ** Call all callbacks registered for when a message is added to the database. ** @param ssb The SSB instance. ** @param id The message identity added. ** @param message_with_keys The message added in the format required if keys are requested. */ void tf_ssb_notify_message_added(tf_ssb_t* ssb, const char* id, JSValue message_with_keys); /** ** Record that a new blob was stored. ** @param ssb The SSB instance. ** @param id The identity of the newly stored blob. */ void tf_ssb_notify_blob_stored(tf_ssb_t* ssb, const char* id); /** ** A callback called when a blob is newly requested. ** @param ssb The SSB instance. ** @param id The blob identity. ** @param user_data The user data. */ typedef void(tf_ssb_blob_want_added_callback_t)(tf_ssb_t* ssb, const char* id, void* user_data); /** ** Register a function to be called when a blob is newly requested. ** @param ssb The SSB instance. ** @param callback The callback. ** @param cleanup A function to call when the callback is removed. ** @param user_data User data to pass to the callback. */ void tf_ssb_add_blob_want_added_callback(tf_ssb_t* ssb, tf_ssb_blob_want_added_callback_t* callback, tf_ssb_callback_cleanup_t* cleanup, void* user_data); /** ** Remove a callback registered for when a blob is newly requested. ** @param ssb The SSB instance. ** @param callback The callback to remove. ** @param user_data The user data registered with the callback. */ void tf_ssb_remove_blob_want_added_callback(tf_ssb_t* ssb, tf_ssb_blob_want_added_callback_t* callback, void* user_data); /** ** Call all callbacks registered for when a blob is newly requested. ** @param ssb The SSB instance. ** @param id The requested blob identity. */ void tf_ssb_notify_blob_want_added(tf_ssb_t* ssb, const char* id); /** ** A function called when a MUXRPC request is made. ** @param connection The SSB connection. ** @param flags The RPC flags. ** @param request_number The request number. ** @param args Request arguments. ** @param message The raw message data. ** @param size The size of the raw message data. ** @param user_data User data registered with the callback. */ typedef void(tf_ssb_rpc_callback_t)(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data); /** ** Register a MUXRPC callback by name. ** @param ssb The SSB instance. ** @param name The NULL-terminated name. ** @param callback The callback. ** @param cleanup A function to be called when the callback is removed. ** @param user_data User data to pass to the callback. */ void tf_ssb_add_rpc_callback(tf_ssb_t* ssb, const char** name, tf_ssb_rpc_callback_t* callback, tf_ssb_callback_cleanup_t* cleanup, void* user_data); /** ** Remove a MUXRPC callback. ** @param ssb The SSB instance. ** @param name The NULL-terminated name. ** @param callback The callback to remove. ** @param user_data The user data registered with the callback. */ void tf_ssb_remove_rpc_callback(tf_ssb_t* ssb, const char** name, tf_ssb_rpc_callback_t* callback, void* user_data); /** ** Send a MUXRPC message. ** @param connection The connection on which to send the message. ** @param flags The message flags. ** @param request_number The request number. ** @param message The message payload. ** @param size The size of the message. ** @param callback A callback to call if a response is received. ** @param cleanup A callback to call if the callback is removed. ** @param user_data User data to pass to the callback. */ void tf_ssb_connection_rpc_send(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, const uint8_t* message, size_t size, tf_ssb_rpc_callback_t* callback, tf_ssb_callback_cleanup_t* cleanup, void* user_data); /** ** Send a JSON MUXRPC message. ** @param connection The connection on which to send the message. ** @param flags The message flags. ** @param request_number The request number. ** @param message The JS message payload. ** @param callback A callback to call if a response is received. ** @param cleanup A callback to call if the callback is removed. ** @param user_data User data to pass to the callback. */ void tf_ssb_connection_rpc_send_json( tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue message, tf_ssb_rpc_callback_t* callback, tf_ssb_callback_cleanup_t* cleanup, void* user_data); /** ** Send a MUXRPC error message. ** @param connection The connection on which to send the message. ** @param flags The message flags. ** @param request_number The request number. ** @param error The error string. */ void tf_ssb_connection_rpc_send_error(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, const char* error); /** ** Send a MUXRPC "method not allowed" error message. ** @param connection The connection on which to send the message. ** @param flags The message flags. ** @param request_number The request number. ** @param name The name of the not-allowed method. */ void tf_ssb_connection_rpc_send_error_method_not_allowed(tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, const char* name); /** ** Register a callback to be called when a message is received for the given ** request number. ** @param connection The connection on which to register the callback. ** @param request_number The request number. ** @param callback The callback. ** @param cleanup The function to call when the callback is removed. ** @param user_data User data to pass to the callback. ** @param dependent_connection A connection, which, if removed, invalidates this request. */ void tf_ssb_connection_add_request(tf_ssb_connection_t* connection, int32_t request_number, tf_ssb_rpc_callback_t* callback, tf_ssb_callback_cleanup_t* cleanup, void* user_data, tf_ssb_connection_t* dependent_connection); /** ** Remove a callback registered to be called when a message is received for the ** given request number. ** @param connection The connection. ** @param request_number The request number. */ void tf_ssb_connection_remove_request(tf_ssb_connection_t* connection, int32_t request_number); /** ** A function scheduled to be run later. ** @param connection The owning connection. ** @param user_data User data registered with the callback. */ typedef void(tf_ssb_scheduled_callback_t)(tf_ssb_connection_t* connection, void* user_data); /** ** Schedule work to be run when the server is next idle. ** @param connection The owning connection. ** @param callback The callback to call. ** @param user_data User data to pass to the callback. */ void tf_ssb_connection_schedule_idle(tf_ssb_connection_t* connection, tf_ssb_scheduled_callback_t* callback, void* user_data); /** ** Schedule work to run on a worker thread. ** @param connection The owning connection. ** @param work_callback The callback to run on a thread. ** @param after_work_callback The callback to run on the main thread when the work is complete. ** @param user_data User data to pass to the callback. */ void tf_ssb_connection_run_work(tf_ssb_connection_t* connection, void (*work_callback)(tf_ssb_connection_t* connection, void* user_data), void (*after_work_callback)(tf_ssb_connection_t* connection, int result, void* user_data), void* user_data); /** ** Register for new messages on a connection. ** @param connection The SHS connection. ** @param author The author for whom to request new messages. ** @param request_number The MUXRPC request on which to send new messages. ** @param keys Whether to send with keys. */ void tf_ssb_connection_add_new_message_request(tf_ssb_connection_t* connection, const char* author, int32_t request_number, bool keys); /** ** Remove a request for new messages on a connection. ** @param connection the SHS connection. ** @param author The author for whom to no longer request new messages. */ void tf_ssb_connection_remove_new_message_request(tf_ssb_connection_t* connection, const char* author); /** ** Get whether we are an attendant on a room connection. ** @param connection The SHS connection. ** @return True if this is an attendant connection. */ bool tf_ssb_connection_is_attendant(tf_ssb_connection_t* connection); /** ** Get the request number used to notify of room attendant changes. ** @param connection the SHS connection. ** @return A request number. */ int32_t tf_ssb_connection_get_attendant_request_number(tf_ssb_connection_t* connection); /** ** Register for attendant change notifications on a connection. ** @param connection The SHS connection. ** @param attendant Whether this connection will be an attendant. ** @param request_number The request number on which to send attendant changes. */ void tf_ssb_connection_set_attendant(tf_ssb_connection_t* connection, bool attendant, int request_number); /** ** Clear all attendants from a room. ** @param connection The SHS connection. */ void tf_ssb_connection_clear_room_attendants(tf_ssb_connection_t* connection); /** ** Add a room attendant. ** @param connection The SHS connection. ** @param id The attendant identifier. */ void tf_ssb_connection_add_room_attendant(tf_ssb_connection_t* connection, const char* id); /** ** Remove a room attendant. ** @param connection The SHS connection. ** @param id The attendanr identifier. */ void tf_ssb_connection_remove_room_attendant(tf_ssb_connection_t* connection, const char* id); /** ** Create a tunnel. ** @param ssb The SSB instance. ** @param portal_id The identity of the tunnel intermediary. ** @param request_number The tunnel request. ** @param target_id The identity being tunneled to. ** @return The new tunnel connection. */ tf_ssb_connection_t* tf_ssb_connection_tunnel_create(tf_ssb_t* ssb, const char* portal_id, int32_t request_number, const char* target_id); /** ** Get the request number on which to send EBT responses. ** @param connection The SHS connection. ** @return The request number. */ int32_t tf_ssb_connection_get_ebt_request_number(tf_ssb_connection_t* connection); /** ** Set the request number on which to send EBT responses. ** @param connection The SHS connection. ** @param request_number The request number. */ void tf_ssb_connection_set_ebt_request_number(tf_ssb_connection_t* connection, int32_t request_number); /** ** Get whether the EBT clock has been sent for a connection. ** @param connection An SHS connection. ** @return True if the clock has been sent. */ bool tf_ssb_connection_get_sent_clock(tf_ssb_connection_t* connection); /** ** Set the EBT clock sent state for a connection. ** @param connection An SHS connection. ** @param sent_clock Whether the clock has been sent. */ void tf_ssb_connection_set_sent_clock(tf_ssb_connection_t* connection, bool sent_clock); /** ** Get the JS class ID of the SSB connection class. ** @return The class ID */ JSClassID tf_ssb_get_connection_class_id(); /** ** Get general statistics about an SSB instance. ** @param ssb The SSB instance. ** @param[out] out_stats Populated with performance statistics. */ void tf_ssb_get_stats(tf_ssb_t* ssb, tf_ssb_stats_t* out_stats); /** ** Get information about requested blobs. ** @param connection An SHS connection. ** @return Blob wants information. */ tf_ssb_blob_wants_t* tf_ssb_connection_get_blob_wants_state(tf_ssb_connection_t* connection); /** ** Get a report of information about recent disconnections. ** @param ssb The SSB instance. ** @param context A JS context. ** @return Information about disconnections. */ JSValue tf_ssb_get_disconnection_debug(tf_ssb_t* ssb, JSContext* context); /** ** Record whether the calling thread is busy. ** @param ssb The SSB instance. ** @param busy True if the calling thread is now busy. */ void tf_ssb_record_thread_busy(tf_ssb_t* ssb, bool busy); /** ** Get an estimate of utilization of all running threads. ** @param ssb The SSB instance. ** @return The utilization percent. */ float tf_ssb_get_average_thread_percent(tf_ssb_t* ssb); /** ** Register a callback to be called when the main thread blocks for an ** unreasonable amount of time. ** @param ssb The SSB instance. ** @param callback The callback to call. ** @param user_data User data to pass to the callback. */ void tf_ssb_set_hitch_callback(tf_ssb_t* ssb, void (*callback)(const char* name, uint64_t duration_ns, void* user_data), void* user_data); /** ** Get the queue of messages in the progress of being stored. ** @param ssb The SSB instance. ** @return The queue. */ tf_ssb_store_queue_t* tf_ssb_get_store_queue(tf_ssb_t* ssb); /** ** Increment the SSB instance's ref count. Prevents it from being destroyed ** until it reaches zero. ** @param ssb The SSB instance. */ void tf_ssb_ref(tf_ssb_t* ssb); /** ** Decrement the SSB instance's ref count. May destroy the instance when the ** count returns to zero. ** @param ssb The SSB instance. */ void tf_ssb_unref(tf_ssb_t* ssb); /** ** Record whether the calling thread is the main thread or not. Some ** operations are disallowed on the main thread for performance. ** @param ssb The SSB instance. ** @param main_thread Whether the calling thread is the main thread. */ void tf_ssb_set_main_thread(tf_ssb_t* ssb, bool main_thread); /** ** Get whether the running server is operating a room. ** @param ssb The SSB instance. ** @return True if the server is a room. */ bool tf_ssb_is_room(tf_ssb_t* ssb); /** ** Set whether the running server is operating a room. ** @param ssb The SSB instance. ** @param is_room Whether to run a room. */ void tf_ssb_set_is_room(tf_ssb_t* ssb, bool is_room); /** ** Get the name of the room hosted by the running server. ** @param ssb The SSB instance. ** @return The room name or NULL. */ const char* tf_ssb_get_room_name(tf_ssb_t* ssb); /** ** Set the name of the room hosted by the running server. ** @param ssb The SSB instance. ** @param room_name The name of the room. */ void tf_ssb_set_room_name(tf_ssb_t* ssb, const char* room_name); /** ** Schedule work to be run after a time delay. ** @param ssb The SSB instance. ** @param delay_ms The duration to wait in milliseconds. ** @param callback The callback to call to run the work. ** @param user_data User data to pass to the callback. */ void tf_ssb_schedule_work(tf_ssb_t* ssb, int delay_ms, void (*callback)(tf_ssb_t* ssb, void* user_data), void* user_data); /** @} */