9#include <ascii-chat/common.h>
10#include <ascii-chat/log/logging.h>
11#include <ascii-chat/network/acip/acds.h>
37 log_debug(
"Negotiation initialized (initiator=%d)", is_initiator);
42 return SET_ERRNO(ERROR_INVALID_PARAM,
"ctx is NULL");
46 log_info(
"Starting NAT detection for host negotiation...");
49 if (result != ASCIICHAT_OK) {
52 log_error(
"NAT detection failed");
63 log_info(
"NAT detection complete, waiting for peer quality...");
68 if (!ctx || !peer_quality) {
69 return SET_ERRNO(ERROR_INVALID_PARAM,
"ctx or peer_quality is NULL");
97static uint8_t determine_connection_type(
const nat_quality_t *quality) {
99 return ACIP_CONNECTION_TYPE_STUN;
103 return ACIP_CONNECTION_TYPE_DIRECT_PUBLIC;
105 return ACIP_CONNECTION_TYPE_UPNP;
107 return ACIP_CONNECTION_TYPE_STUN;
113 return SET_ERRNO(ERROR_INVALID_PARAM,
"ctx is NULL");
117 return SET_ERRNO(ERROR_INVALID_STATE,
"Cannot determine result: detection incomplete");
156 log_info(
"Negotiation result: THEY ARE HOST (addr=%s:%u, type=%d)", ctx->
host_address, ctx->
host_port,
178 return ERROR_INVALID_PARAM;
183 const uint8_t participant_ids[][16],
size_t num_participants,
184 uint8_t out_future_host_id[16]) {
185 if (!collected_quality || !participant_ids || !out_future_host_id) {
186 SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid parameters");
187 return ERROR_INVALID_PARAM;
191 SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid participant count");
192 return ERROR_INVALID_PARAM;
196 if (num_participants == 1) {
197 memcpy(out_future_host_id, participant_ids[0], 16);
198 log_info(
"Only one participant, electing as future host");
204 for (
size_t i = 0; i < num_participants; i++) {
213 for (
size_t i = 0; i < num_participants; i++) {
217 for (
size_t j = 0; j < num_participants; j++) {
233 if (wins > best_wins || (wins == best_wins && memcmp(participant_ids[i], participant_ids[best_idx], 16) < 0)) {
240 memcpy(out_future_host_id, participant_ids[best_idx], 16);
242 log_info(
"Future host elected (participant index %zu with %d wins)", best_idx, best_wins);
int nat_compare_quality(const nat_quality_t *ours, const nat_quality_t *theirs, bool we_are_initiator)
Compare two NAT qualities and determine who should host.
void nat_quality_init(nat_quality_t *quality)
Initialize NAT quality structure with defaults.
asciichat_error_t nat_detect_quality(nat_quality_t *quality, const char *stun_server, uint16_t local_port)
Detect NAT quality using all available methods.
int nat_compute_tier(const nat_quality_t *quality)
Compute NAT tier for host selection (0=best, 4=worst)
void nat_quality_from_acip(const acip_nat_quality_t *acip, nat_quality_t *out)
Convert acip_nat_quality_t to nat_quality_t.
asciichat_error_t negotiate_start_detection(negotiate_ctx_t *ctx, const char *stun_server, uint16_t local_port)
Start NAT detection phase.
asciichat_error_t negotiate_receive_peer_quality(negotiate_ctx_t *ctx, const acip_nat_quality_t *peer_quality)
Process received peer NAT quality.
void negotiate_init(negotiate_ctx_t *ctx, const uint8_t session_id[16], const uint8_t participant_id[16], bool is_initiator)
Initialize negotiation context.
asciichat_error_t negotiate_determine_result(negotiate_ctx_t *ctx)
Determine negotiation result.
bool negotiate_is_complete(const negotiate_ctx_t *ctx)
Check if negotiation is complete.
asciichat_error_t negotiate_get_error(const negotiate_ctx_t *ctx)
Get negotiation error (if failed)
asciichat_error_t negotiate_elect_future_host(const acip_nat_quality_t collected_quality[], const uint8_t participant_ids[][16], size_t num_participants, uint8_t out_future_host_id[16])
Elect future host from multiple participants (NEW P2P design)
negotiate_state_t negotiate_get_state(const negotiate_ctx_t *ctx)
Get current negotiation state.
Host negotiation logic for discovery mode.
negotiate_state_t
Negotiation state.
@ NEGOTIATE_STATE_INIT
Initial state.
@ NEGOTIATE_STATE_WE_HOST
We won, becoming host.
@ NEGOTIATE_STATE_THEY_HOST
They won, connecting as client.
@ NEGOTIATE_STATE_WAITING_PEER
Waiting for peer's NAT quality.
@ NEGOTIATE_STATE_FAILED
Negotiation failed.
@ NEGOTIATE_STATE_COMPARING
Comparing qualities.
@ NEGOTIATE_STATE_COMPLETE
Negotiation complete.
@ NEGOTIATE_STATE_DETECTING_NAT
Running NAT detection.
uint8_t participant_id[16]
NAT quality assessment result.
bool detection_complete
All probes finished.
uint32_t upload_kbps
Upload bandwidth in Kbps.
char public_address[64]
Public IP address.
bool has_public_ip
STUN reflexive == local IP.
bool upnp_available
UPnP/NAT-PMP mapping succeeded.
uint16_t upnp_mapped_port
Mapped external port (if upnp_available)
Host negotiation context.
bool we_are_host
True if we should become host.
uint8_t connection_type
acip_connection_type_t
uint8_t participant_id[16]
char host_address[64]
Host's address (ours if we_are_host)
nat_quality_t our_quality
Our NAT quality.
bool peer_quality_received
Have we received peer's quality?
nat_quality_t peer_quality
Peer's NAT quality (when received)
bool is_initiator
Did we create this session?
uint16_t host_port
Host's port.