macula_hole_punch (macula v0.14.3)
View SourceQUIC Hole Punch Executor with Cancellation and Adaptive Timing.
Implements the simultaneous open (SYN-SYN) pattern for QUIC to establish direct connections through NAT devices.
Features: - Proper cancellation of in-progress punch attempts - Adaptive timing based on NAT type and previous attempts - Tracks active punches via gen_server state - Supports both sync and async execution
QUIC Hole Punching Approach: Unlike TCP's explicit SYN packets, QUIC uses encrypted handshakes. The hole punching strategy is:
1. Both peers start QUIC connect() at the same coordinated time 2. Initial packets "punch" holes in both NATs 3. One peer's connection will succeed (race condition) 4. The other peer retries connecting through the opened hole
NAT Behavior Considerations: - EI mapping: External address is consistent - easy hole punch - HD mapping: Must target specific host - coordinate addresses - PP allocation: Same port - single target port - PC allocation: Sequential ports - try predicted range - RD allocation: Random ports - harder to predict, try range
Adaptive Timing: - Symmetric NAT: Longer timeouts, more port attempts - Restricted NAT: Standard timeouts - Full Cone: Fast timeouts, single port
Summary
Functions
Cancel an ongoing hole punch attempt.
Execute a hole punch attempt synchronously. Blocks until connection established or timeout.
Execute hole punch asynchronously. Returns immediately, caller receives result via message.
Get list of active punch attempts (for debugging/monitoring).
Start the hole punch executor.
Types
-type nat_type() :: full_cone | restricted | port_restricted | symmetric | unknown.
-type punch_opts() :: #{target_host := binary() | string(), target_ports := [inet:port_number()], local_port => inet:port_number(), session_id := binary(), punch_time => integer(), role => initiator | target, local_nat_type => nat_type(), remote_nat_type => nat_type()}.
-type punch_result() :: {ok, quicer:connection_handle()} | {error, timeout | unreachable | all_ports_failed | cancelled}.
Functions
-spec cancel(reference()) -> ok | {error, not_found}.
Cancel an ongoing hole punch attempt.
-spec execute(binary(), punch_opts(), timeout()) -> punch_result().
Execute a hole punch attempt synchronously. Blocks until connection established or timeout.
-spec execute_async(binary(), punch_opts(), pid()) -> reference().
Execute hole punch asynchronously. Returns immediately, caller receives result via message.
Get list of active punch attempts (for debugging/monitoring).
Start the hole punch executor.