Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions driver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,29 @@ func (d *Driver) RevokeTrust(nodeID uint32) (map[string]interface{}, error) {
return d.jsonRPC(msg, cmdHandshakeOK, "revoke")
}

// PreferDirect asks the daemon to drop the existing tunnel to the peer
// and any sticky routing state (cached endpoint, cached resolve, unpinned
// relay flag), then re-resolve from the registry and prefer a direct UDP
// path on the next dial. Returns the new routing state the daemon arrived
// at — typically {"node_id": N, "relay_active": false, "pinned": false,
// "real_addr": "..."} when a direct path was found, or relay_active=true
// when the registry's relay_only flag is authoritative or the punch
// failed.
//
// Useful when stream traffic (pilotctl send-file) is failing on a relay
// path while small UDP (pilotctl ping) still works — typical symptom of
// a beacon-mediated tunnel that established once and then stuck.
//
// Backward compatibility: an old daemon (no CmdPreferDirect) returns an
// "unknown command" error — callers should treat that as "best-effort
// hint" and proceed with the normal dial, not abort the operation.
func (d *Driver) PreferDirect(nodeID uint32) (map[string]interface{}, error) {
msg := make([]byte, 5)
msg[0] = cmdPreferDirect
binary.BigEndian.PutUint32(msg[1:5], nodeID)
return d.jsonRPC(msg, cmdPreferDirectOK, "prefer_direct")
}

// ResolveHostname resolves a hostname to node info via the daemon.
func (d *Driver) ResolveHostname(hostname string) (map[string]interface{}, error) {
msg := make([]byte, 1+len(hostname))
Expand Down
10 changes: 9 additions & 1 deletion driver/ipc.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ const (
cmdRotateKeyOK byte = 0x26
cmdBroadcast byte = 0x29
cmdBroadcastOK byte = 0x2A
// cmdPreferDirect asks the daemon to drop the existing tunnel to a
// peer (and any cached endpoint / sticky relay flag) and re-resolve
// + redial fresh — preferring a direct UDP path. Useful when a peer
// got stuck on the beacon relay after an unlucky punch and stream
// traffic (send-file) is failing while small messages (ping) work.
cmdPreferDirect byte = 0x2D
cmdPreferDirectOK byte = 0x2E
)

// Network sub-commands (must match daemon SubNetwork* constants)
Expand Down Expand Up @@ -184,7 +191,8 @@ func (c *ipcClient) readLoop() {
case cmdBindOK, cmdDialOK, cmdError, cmdInfoOK, cmdHandshakeOK,
cmdResolveHostnameOK, cmdSetHostnameOK, cmdSetVisibilityOK,
cmdDeregisterOK, cmdSetTagsOK, cmdSetWebhookOK, cmdNetworkOK,
cmdHealthOK, cmdManagedOK, cmdRotateKeyOK, cmdBroadcastOK:
cmdHealthOK, cmdManagedOK, cmdRotateKeyOK, cmdBroadcastOK,
cmdPreferDirectOK:
// Known response cmds: route to pending for the in-flight sendAndWait.
select {
case c.pending <- &pendingResponse{cmd: cmd, payload: append([]byte(nil), payload...)}:
Expand Down
Loading