#ifndef HYPERSWARM_MULTIPLAYER_PEER_H
#define HYPERSWARM_MULTIPLAYER_PEER_H
#include <godot_cpp/classes/multiplayer_peer_extension.hpp>
#include <godot_cpp/core/binder_common.hpp>
#include "packet_queue.h"
#include "udx_transport.h"
namespace godot {
class HyperswarmMultiplayerPeer : public MultiplayerPeerExtension {
GDCLASS(HyperswarmMultiplayerPeer, MultiplayerPeerExtension)
private:
UdxTransport _transport;
public:
// C++-only accessor, so a sibling extension class (the overlay) can attach its
// own protocol to these connections. Not bound to Godot: handing a raw
// transport pointer to GDScript would be a way to corrupt the loop from the
// main thread.
UdxTransport *transport_internal() { return &_transport; }
private:
// Multiplayer state.
int32_t _unique_id;
int32_t _target_peer;
int32_t _transfer_channel;
TransferMode _transfer_mode;
ConnectionStatus _connection_status;
bool _is_server_peer;
bool _refuse_connections;
// Current packet being read by Godot (must persist between _get_packet calls).
Packet _current_packet;
bool _has_current_packet;
protected:
static void _bind_methods();
public:
HyperswarmMultiplayerPeer();
~HyperswarmMultiplayerPeer() override;
// ---- Custom methods exposed to GDScript ----
// Create a server listening on the given port (unencrypted).
Error create_server(int port);
// Connect to a server at address:port (unencrypted).
Error create_client(const String &address, int port);
// Generate a new Curve25519 keypair for Noise encryption.
// Returns: {public_key: PackedByteArray, secret_key: PackedByteArray}
Dictionary generate_keypair();
// Create a Noise-encrypted server with the given keypair.
Error create_server_with_keypair(int port, const PackedByteArray &public_key,
const PackedByteArray &secret_key);
// Connect to a Noise-encrypted server. Remote public key is used
// to verify the server's identity during the Noise XX handshake.
Error create_client_with_key(const String &address, int port,
const PackedByteArray &remote_public_key);
// Get the remote peer's verified public key after Noise handshake.
// Returns empty PackedByteArray if not encrypted or handshake not complete.
PackedByteArray get_peer_public_key(int peer_id) const;
// Get networking stats.
Dictionary get_stats() const;
// Get per-peer RTT stats (srtt, rttvar, rto, min_rtt) in milliseconds.
Dictionary get_peer_rtt(int peer_id) const;
// ---- DHT Discovery API ----
// Generate a new Ed25519 keypair for DHT identity.
// Returns: {public_key: PackedByteArray(32), secret_key: PackedByteArray(64)}
Dictionary generate_dht_keypair();
// Join the DHT network with Ed25519 keypair and optional bootstrap nodes.
// Starts the transport if not already running.
Error join_dht(const PackedByteArray &public_key, const PackedByteArray &secret_key,
const PackedStringArray &bootstrap_nodes = PackedStringArray());
// Connect to a remote peer by their Ed25519 public key (via DHT discovery).
Error connect_to_peer(const PackedByteArray &remote_public_key);
// Start listening for incoming DHT connections.
Error listen_on_dht();
// Announce a 32-byte topic on the DHT.
Error announce_topic(const PackedByteArray &topic);
// Lookup a 32-byte topic on the DHT.
Error lookup_topic(const PackedByteArray &topic);
// Join a topic with server and/or client mode (session-counted, auto-refresh).
// Matches JS Hyperswarm.join(topic, {server, client}).
Error join_topic(const PackedByteArray &topic, bool server, bool client);
// Leave a topic (decrements session; unannounces when server sessions reach 0).
// Matches JS Hyperswarm.leave(topic).
Error leave_topic(const PackedByteArray &topic);
// Get DHT status info.
Dictionary get_dht_status() const;
// ---- Swarm Manager API ----
// Join a topic with auto-connect, retry, and priority management.
// Equivalent to JS: const swarm = new Hyperswarm(); swarm.join(topic)
Error swarm_join(const PackedByteArray &topic, bool server, bool client);
// Leave a swarm topic.
Error swarm_leave(const PackedByteArray &topic);
// Add an explicit peer by public key (direct connect, not topic-based).
Error swarm_join_peer(const PackedByteArray &public_key);
// Remove an explicit peer.
Error swarm_leave_peer(const PackedByteArray &public_key);
// Get SwarmManager diagnostic status.
Dictionary get_swarm_status() const;
// Get per-connection diagnostics (Array of Dictionary, one per active DhtConnection).
Array get_connection_diagnostics() const;
// ---- DHT Storage API ----
// Store an immutable value on the DHT. key = BLAKE2b(value).
// Result emitted via dht_put_complete signal.
Error dht_put(const PackedByteArray &data);
// Retrieve an immutable value from the DHT by key.
// Result emitted via dht_get_complete signal.
Error dht_get(const PackedByteArray &key);
// Store a mutable value signed with our DHT keypair.
// Result emitted via dht_mutable_put_complete signal.
Error dht_mutable_put(const PackedByteArray &data, int seq);
// Retrieve a mutable value by public key.
// Result emitted via dht_mutable_get_complete signal.
Error dht_mutable_get(const PackedByteArray &public_key, int min_seq);
// ---- Required MultiplayerPeerExtension overrides ----
void _close() override;
void _disconnect_peer(int32_t p_peer, bool p_force) override;
Error _get_packet(const uint8_t **r_buffer, int32_t *r_buffer_size) override;
Error _put_packet(const uint8_t *p_buffer, int32_t p_buffer_size) override;
int32_t _get_available_packet_count() const override;
int32_t _get_max_packet_size() const override;
int32_t _get_packet_peer() const override;
int32_t _get_packet_channel() const override;
MultiplayerPeer::TransferMode _get_packet_mode() const override;
ConnectionStatus _get_connection_status() const override;
int32_t _get_unique_id() const override;
bool _is_server() const override;
void _set_target_peer(int32_t p_peer) override;
void _set_transfer_channel(int32_t p_channel) override;
void _set_transfer_mode(MultiplayerPeer::TransferMode p_mode) override;
int32_t _get_transfer_channel() const override;
MultiplayerPeer::TransferMode _get_transfer_mode() const override;
void _poll() override;
// ---- Optional overrides ----
void _set_refuse_new_connections(bool p_enable) override;
bool _is_refusing_new_connections() const override;
bool _is_server_relay_supported() const override;
};
} // namespace godot
#endif // HYPERSWARM_MULTIPLAYER_PEER_H