Documentation
¶
Index ¶
- Constants
- func GetIPv4BroadcastAddress(ipNet *net.IPNet) net.IP
- type Device
- func (d *Device) BatchSize() int
- func (d *Device) Close() error
- func (d *Device) GetTempPacket() *Packet
- func (d *Device) InterfaceName() (string, error)
- func (d *Device) LocalIP() net.IP
- func (d *Device) PutTempPacket(data *Packet)
- func (d *Device) ReadTUNPackets(packetsHandler func([]*Packet))
- func (d *Device) WriteBufs(bufs [][]byte) error
- func (d *Device) WritePacket(data *Packet, senderIP net.IP) error
- type GatewayDir
- type Packet
- type SwappableTUN
- func (w *SwappableTUN) BatchSize() int
- func (w *SwappableTUN) Close() error
- func (w *SwappableTUN) Events() <-chan tun.Event
- func (w *SwappableTUN) File() *os.File
- func (w *SwappableTUN) MTU() (int, error)
- func (w *SwappableTUN) Name() (string, error)
- func (w *SwappableTUN) Read(bufs [][]byte, sizes []int, offset int) (int, error)
- func (w *SwappableTUN) Swap(newDev tun.Device) error
- func (w *SwappableTUN) Write(bufs [][]byte, offset int) (int, error)
Constants ¶
const ( IPProtocolTCP = 6 IPProtocolUDP = 17 )
const ( InterfaceMTU = 3500 // MaxPacketBodySize is the largest tunnel packet body (an IP packet, without // the internal TUN header offset) that Packet.Buffer can hold. Peers must not // send larger frames: protocol.ReadPacketHeader rejects oversized ones up front and // Packet.ReadFrom refuses to overflow the buffer. MaxPacketBodySize = maxContentSize - tunPacketOffset )
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Device ¶
type Device struct {
// contains filtered or unexported fields
}
func (*Device) GetTempPacket ¶
func (*Device) InterfaceName ¶
func (*Device) LocalIP ¶ added in v0.18.0
LocalIP returns the awl IP assigned to this device. Set once in NewDevice.
func (*Device) PutTempPacket ¶
func (*Device) ReadTUNPackets ¶ added in v0.15.0
func (*Device) WriteBufs ¶ added in v0.18.0
WriteBufs writes a prepared batch of TUN packets in a single tun.Write syscall. The caller is responsible for IP rewrites and checksum recalculation on the underlying *Packet objects before building bufs via Packet.Buf.
Empty bufs is a no-op. After writing, every entry is set to nil to release the underlying buffer for GC; the caller should reuse the same backing array (len=0, cap=batchSize) across calls to avoid per-batch allocation.
type GatewayDir ¶ added in v0.18.0
type GatewayDir uint8
GatewayDir tags a tunnel packet's intent with respect to VPN gateway mode.
const ( // GatewayDirNone is a regular awl peer-to-peer packet. Receiver applies the // standard full src/dst rewrite. GatewayDirNone GatewayDir = iota // GatewayDirForward is sent client → server: the sender asks the receiver, // who must be acting as a VPN gateway server for the sender, to forward // this packet to the internet via NAT. Receiver rewrites only src. GatewayDirForward // GatewayDirReturn is sent server → client: the sender (the gateway server) // is delivering a NAT-returned packet from the internet back to the client. // Receiver rewrites only dst. GatewayDirReturn )
type Packet ¶
type Packet struct {
Buffer [maxContentSize]byte
Packet []byte
Src net.IP
Dst net.IP
IsIPv6 bool
GatewayDir GatewayDir
IPProtocol byte
}
func (*Packet) Buf ¶ added in v0.18.0
Buf returns the slice of data.Buffer that includes the TUN header offset and the parsed packet body, ready to be appended into a bufs slice for tun.Write.
func (*Packet) RecalculateChecksum ¶
func (data *Packet) RecalculateChecksum()
type SwappableTUN ¶ added in v0.18.0
type SwappableTUN struct {
// contains filtered or unexported fields
}
SwappableTUN wraps a tun.Device and lets the underlying device be replaced at runtime ("hot swap") without disturbing any of its consumers. It exists so that platforms which cannot mutate routing on a live interface (Android, where routing is owned by VpnService.Builder and a route change requires a fresh VpnService.establish() and therefore a new tun fd) can switch the TUN in place while the rest of awl — the libp2p host, service.Tunnel, the ReadTUNPackets loop — keeps running untouched.
The swap is fully hidden behind the tun.Device contract:
Read never surfaces a swap as an error. When the current inner device is closed by Swap, the in-flight Read unblocks with os.ErrClosed; Read detects that the device pointer has moved and transparently retries on the new inner. os.ErrClosed is propagated to the caller only when the whole SwappableTUN is closed (real shutdown) — which is exactly when the ReadTUNPackets loop should exit.
Events() returns a single stable channel owned by the wrapper. A forwarder goroutine copies events from whichever inner device is current and only closes the wrapper's channel when the wrapper itself is closed, so a swap does not terminate the consumer's range loop.
BatchSize is captured once at construction and returned unchanged, as the tun.Device contract requires it to be constant for the device's lifetime (ReadTUNPackets sizes its buffers from it exactly once).
Concurrency: Read/Write run lock-free and may be called concurrently with Swap and Close. Swap and Close are assumed NOT to run concurrently with each other — on Android both are driven serially by the host app over a single MethodChannel task queue. The lock-free Read/Write hot path is the only one that matters for performance, hence atomic.Pointer rather than a mutex.
func NewSwappableTUN ¶ added in v0.18.0
func NewSwappableTUN(initial tun.Device) *SwappableTUN
NewSwappableTUN wraps initial as the starting inner device. initial must be non-nil. The wrapper takes ownership of initial: Close (or a subsequent Swap) will close it.
func (*SwappableTUN) BatchSize ¶ added in v0.18.0
func (w *SwappableTUN) BatchSize() int
BatchSize returns the value captured at construction. It must not change over the device's lifetime; all inner devices on a given platform share the same preferred batch size, so this is safe across swaps.
func (*SwappableTUN) Close ¶ added in v0.18.0
func (w *SwappableTUN) Close() error
Close marks the wrapper closed and closes the current inner device. Closing the inner device closes its event channel, which makes the forwarder goroutine close the wrapper's event channel and exit. Idempotent.
func (*SwappableTUN) Events ¶ added in v0.18.0
func (w *SwappableTUN) Events() <-chan tun.Event
Events returns the wrapper-owned channel. It stays open across swaps and is closed only when the wrapper is closed.
func (*SwappableTUN) File ¶ added in v0.18.0
func (w *SwappableTUN) File() *os.File
func (*SwappableTUN) MTU ¶ added in v0.18.0
func (w *SwappableTUN) MTU() (int, error)
func (*SwappableTUN) Name ¶ added in v0.18.0
func (w *SwappableTUN) Name() (string, error)
func (*SwappableTUN) Swap ¶ added in v0.18.0
func (w *SwappableTUN) Swap(newDev tun.Device) error
Swap replaces the current inner device with newDev and closes the old one. Closing the old device unblocks any in-flight Read/Write so it can retry on newDev. The pointer is swapped BEFORE the old device is closed: this ordering guarantees that when the unblocked Read observes os.ErrClosed it will already see the updated pointer and retry rather than mistake the swap for a real shutdown.
If the wrapper is already closed, newDev is closed and os.ErrClosed returned.