From 4794021bb8c697f107e6a2689bb9096eabb17888 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 22 Dec 2020 11:12:54 -0800 Subject: [PATCH] device: add Device.ListenPort and Device.SetListenPort This is a sample commit for a possible way to make a Go API that lives alongside UAPI. The general idea is to add Device and Peer methods corresponding to UAPI directives, including a way to look up a peer from a device based on a public key, as in UAPI. The UAPI code then deals with parsing and generating textual input/output, and calls the Go methods to do the work. This commit also contains a bug fix for a racy access of device.net.port I will send an independently commit that fixes those directly in UAPI. This commit is NOT meant to be merged as-is. Signed-off-by: Josh Bleecher Snyder --- device/device.go | 22 +++++++++++++++++++++- device/uapi.go | 11 +++-------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/device/device.go b/device/device.go index 5f128fc..f7885ce 100644 --- a/device/device.go +++ b/device/device.go @@ -90,6 +90,23 @@ type Device struct { } } +// ListenPort returns the port that device is listening on. +// It returns 0 if the device is not listening on any ports. +func (device *Device) ListenPort() uint16 { + device.net.Lock() + defer device.net.Unlock() + return device.net.port +} + +// SetListenPort sets the port that the device is listening on. +// The new port is bound immediately. +func (device *Device) SetListenPort(port uint16) error { + device.net.Lock() + defer device.net.Unlock() + device.net.port = port + return device.bindUpdateLocked() +} + // An encryptionQueue is a channel of QueueOutboundElements awaiting encryption. // An encryptionQueue is ref-counted using its wg field. // An encryptionQueue created with newEncryptionQueue has one reference. @@ -490,9 +507,12 @@ func (device *Device) BindSetMark(mark uint32) error { } func (device *Device) BindUpdate() error { - device.net.Lock() defer device.net.Unlock() + return device.bindUpdateLocked() +} + +func (device *Device) bindUpdateLocked() error { // close existing sockets diff --git a/device/uapi.go b/device/uapi.go index 2843a4c..3575c11 100644 --- a/device/uapi.go +++ b/device/uapi.go @@ -58,8 +58,8 @@ func (device *Device) IpcGetOperation(w io.StringWriter) error { send("private_key=" + device.staticIdentity.privateKey.ToHex()) } - if device.net.port != 0 { - send(fmt.Sprintf("listen_port=%d", device.net.port)) + if port := device.ListenPort(); port != 0 { + send(fmt.Sprintf("listen_port=%d", port)) } if device.net.fwmark != 0 { @@ -162,12 +162,7 @@ func (device *Device) IpcSetOperation(r io.Reader) error { // update port and rebind logDebug.Println("UAPI: Updating listen port") - - device.net.Lock() - device.net.port = uint16(port) - device.net.Unlock() - - if err := device.BindUpdate(); err != nil { + if err := device.SetListenPort(uint16(port)); err != nil { logError.Println("Failed to set listen_port:", err) return &IPCError{ipc.IpcErrorPortInUse} }