diff options
author | Sam Whited <sam@samwhited.com> | 2022-03-11 13:22:29 -0500 |
---|---|---|
committer | Sam Whited <sam@samwhited.com> | 2022-03-15 09:26:50 -0400 |
commit | 2d95d4d069124df4a4e2473fc23ad3feed19905d (patch) | |
tree | 4e53db9f07cfda2e17745a6870f294db2d4eb756 /vendor/github.com/apparentlymart | |
parent | c8dc651f72c09ce252cee729bfc09d8ca6744c36 (diff) |
Remove vendor from git
Previously we saved the vendor tree in version control, making any
commit that changed a dependency rather large.
Go Modules gives us most of the advantages of vendoring except that if a
dependency which is not stored on the proxy is deleted we would lose
access to it.
For now, we can remove the vendor tree and when we get CI working again
we can possibly generate and save the vendor tree as a build artifact.
Signed-off-by: Sam Whited <sam@samwhited.com>
Diffstat (limited to 'vendor/github.com/apparentlymart')
6 files changed, 0 insertions, 860 deletions
diff --git a/vendor/github.com/apparentlymart/go-openvpn-mgmt/demux/demuxer.go b/vendor/github.com/apparentlymart/go-openvpn-mgmt/demux/demuxer.go deleted file mode 100644 index c57964e..0000000 --- a/vendor/github.com/apparentlymart/go-openvpn-mgmt/demux/demuxer.go +++ /dev/null @@ -1,63 +0,0 @@ -package demux - -import ( - "bufio" - "io" -) - -var readErrSynthEvent = []byte("FATAL:Error reading from OpenVPN") - -// Demultiplex reads from the given io.Reader, assumed to be the client -// end of an OpenVPN Management Protocol connection, and splits it into -// distinct messages from OpenVPN. -// -// It then writes the raw message buffers into either replyCh or eventCh -// depending on whether each message is a reply to a client command or -// an asynchronous event notification. -// -// The buffers written to replyCh are entire raw message lines (without the -// trailing newlines), while the buffers written to eventCh are the raw -// event strings with the prototcol's leading '>' indicator omitted. -// -// The caller should usually provide buffered channels of sufficient buffer -// depth so that the reply channel will not be starved by slow event -// processing. -// -// Once the io.Reader signals EOF, eventCh will be closed, then replyCh -// will be closed, and then this function will return. -// -// As a special case, if a non-EOF error occurs while reading from the -// io.Reader then a synthetic "FATAL" event will be written to eventCh -// before the two buffers are closed and the function returns. This -// synthetic message will have the error message "Error reading from OpenVPN". -func Demultiplex(r io.Reader, replyCh, eventCh chan<- []byte) { - scanner := bufio.NewScanner(r) - for scanner.Scan() { - buf := scanner.Bytes() - - if len(buf) < 1 { - // Should never happen but we'll be robust and ignore this, - // rather than crashing below. - continue - } - - // Asynchronous messages always start with > to differentiate - // them from replies. - if buf[0] == '>' { - // Trim off the > when we post the message, since it's - // redundant after we've demuxed. - eventCh <- buf[1:] - } else { - replyCh <- buf - } - } - - if err := scanner.Err(); err != nil { - // Generate a synthetic FATAL event so that the caller can - // see that the connection was not gracefully closed. - eventCh <- readErrSynthEvent - } - - close(eventCh) - close(replyCh) -} diff --git a/vendor/github.com/apparentlymart/go-openvpn-mgmt/demux/doc.go b/vendor/github.com/apparentlymart/go-openvpn-mgmt/demux/doc.go deleted file mode 100644 index 263a267..0000000 --- a/vendor/github.com/apparentlymart/go-openvpn-mgmt/demux/doc.go +++ /dev/null @@ -1,12 +0,0 @@ -// Package demux implements low-level demultiplexing of the stream of -// messages sent from OpenVPN on the management channel. -// -// OpenVPN's protocol includes two different kinds of message from the OpenVPN -// process: replies to commands sent by the management client, and asynchronous -// event notifications. -// -// This package's purpose is to split these messages into two separate streams, -// so that functions executing command/response sequences can just block -// on the reply channel while an event loop elsewhere deals with any async -// events that might show up. -package demux diff --git a/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/client.go b/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/client.go deleted file mode 100644 index 7768004..0000000 --- a/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/client.go +++ /dev/null @@ -1,303 +0,0 @@ -package openvpn - -import ( - "bytes" - "fmt" - "io" - "net" - "strconv" - "time" - - "github.com/apparentlymart/go-openvpn-mgmt/demux" -) - -var newline = []byte{'\n'} -var successPrefix = []byte("SUCCESS: ") -var errorPrefix = []byte("ERROR: ") -var endMessage = []byte("END") - -type MgmtClient struct { - wr io.Writer - replies <-chan []byte -} - -// NewClient creates a new MgmtClient that communicates via the given -// io.ReadWriter and emits events on the given channel. -// -// eventCh should be a buffered channel with a sufficient buffer depth -// such that it cannot be filled under the expected event volume. Event -// volume depends on which events are enabled and how they are configured; -// some of the event-enabling functions have further discussion how frequently -// events are likely to be emitted, but the caller should also factor in -// how long its own event *processing* will take, since slow event -// processing will create back-pressure that could cause this buffer to -// fill faster. -// -// It probably goes without saying given the previous paragraph, but the -// caller *must* constantly read events from eventCh to avoid its buffer -// becoming full. Events and replies are received on the same channel -// from OpenVPN, so if writing to eventCh blocks then this will also block -// responses from the client's various command methods. -// -// eventCh will be closed to signal the closing of the client connection, -// whether due to graceful shutdown or to an error. In the case of error, -// a FatalEvent will be emitted on the channel as the last event before it -// is closed. Connection errors may also concurrently surface as error -// responses from the client's various command methods, should an error -// occur while we await a reply. -func NewClient(conn io.ReadWriter, eventCh chan<- Event) *MgmtClient { - replyCh := make(chan []byte) - rawEventCh := make(chan []byte) // not buffered because eventCh should be - - go demux.Demultiplex(conn, replyCh, rawEventCh) - - // Get raw events and upgrade them into proper event types before - // passing them on to the caller's event channel. - go func() { - for raw := range rawEventCh { - eventCh <- upgradeEvent(raw) - } - close(eventCh) - }() - - return &MgmtClient{ - // replyCh acts as the reader for our ReadWriter, so we only - // need to retain the io.Writer for it, so we can send commands. - wr: conn, - replies: replyCh, - } -} - -// Dial is a convenience wrapper around NewClient that handles the common -// case of opening an TCP/IP socket to an OpenVPN management port and creating -// a client for it. -// -// See the NewClient docs for discussion about the requirements for eventCh. -// -// OpenVPN will create a suitable management port if launched with the -// following command line option: -// -// --management <ipaddr> <port> -// -// Address may an IPv4 address, an IPv6 address, or a hostname that resolves -// to either of these, followed by a colon and then a port number. -// -// When running on Unix systems it's possible to instead connect to a Unix -// domain socket. To do this, pass an absolute path to the socket as -// the target address, having run OpenVPN with the following options: -// -// --management /path/to/socket unix -// -func Dial(addr string, eventCh chan<- Event) (*MgmtClient, error) { - proto := "tcp" - if len(addr) > 0 && addr[0] == '/' { - proto = "unix" - } - conn, err := net.Dial(proto, addr) - if err != nil { - return nil, err - } - - return NewClient(conn, eventCh), nil -} - -// HoldRelease instructs OpenVPN to release any management hold preventing -// it from proceeding, but to retain the state of the hold flag such that -// the daemon will hold again if it needs to reconnect for any reason. -// -// OpenVPN can be instructed to activate a management hold on startup by -// running it with the following option: -// -// --management-hold -// -// Instructing OpenVPN to hold gives your client a chance to connect and -// do any necessary configuration before a connection proceeds, thus avoiding -// the problem of missed events. -// -// When OpenVPN begins holding, or when a new management client connects while -// a hold is already in effect, a HoldEvent will be emitted on the event -// channel. -func (c *MgmtClient) HoldRelease() error { - _, err := c.simpleCommand("hold release") - return err -} - -// SetStateEvents either enables or disables asynchronous events for changes -// in the OpenVPN connection state. -// -// When enabled, a StateEvent will be emitted from the event channel each -// time the connection state changes. See StateEvent for more information -// on the event structure. -func (c *MgmtClient) SetStateEvents(on bool) error { - var err error - if on { - _, err = c.simpleCommand("state on") - } else { - _, err = c.simpleCommand("state off") - } - return err -} - -// SetEchoEvents either enables or disables asynchronous events for "echo" -// commands sent from a remote server to our managed OpenVPN client. -// -// When enabled, an EchoEvent will be emitted from the event channel each -// time the server sends an echo command. See EchoEvent for more information. -func (c *MgmtClient) SetEchoEvents(on bool) error { - var err error - if on { - _, err = c.simpleCommand("echo on") - } else { - _, err = c.simpleCommand("echo off") - } - return err -} - -// SetByteCountEvents either enables or disables ongoing asynchronous events -// for information on OpenVPN bandwidth usage. -// -// When enabled, a ByteCountEvent will be emitted at given time interval, -// (which may only be whole seconds) describing how many bytes have been -// transferred in each direction See ByteCountEvent for more information. -// -// Set the time interval to zero in order to disable byte count events. -func (c *MgmtClient) SetByteCountEvents(interval time.Duration) error { - msg := fmt.Sprintf("bytecount %d", int(interval.Seconds())) - _, err := c.simpleCommand(msg) - return err -} - -// SendSignal sends a signal to the OpenVPN process via the management -// channel. In effect this causes the OpenVPN process to send a signal to -// itself on our behalf. -// -// OpenVPN accepts a subset of the usual UNIX signal names, including -// "SIGHUP", "SIGTERM", "SIGUSR1" and "SIGUSR2". See the OpenVPN manual -// page for the meaning of each. -// -// Behavior is undefined if the given signal name is not entirely uppercase -// letters. In particular, including newlines in the string is likely to -// cause very unpredictable behavior. -func (c *MgmtClient) SendSignal(name string) error { - msg := fmt.Sprintf("signal %q", name) - _, err := c.simpleCommand(msg) - return err -} - -// LatestState retrieves the most recent StateEvent from the server. This -// can either be used to poll the state or it can be used to determine the -// initial state after calling SetStateEvents(true) but before the first -// state event is delivered. -func (c *MgmtClient) LatestState() (*StateEvent, error) { - err := c.sendCommand([]byte("state")) - if err != nil { - return nil, err - } - - payload, err := c.readCommandResponsePayload() - if err != nil { - return nil, err - } - - if len(payload) != 1 { - return nil, fmt.Errorf("Malformed OpenVPN 'state' response") - } - - return &StateEvent{ - body: payload[0], - }, nil -} - -// Pid retrieves the process id of the connected OpenVPN process. -func (c *MgmtClient) Pid() (int, error) { - raw, err := c.simpleCommand("pid") - if err != nil { - return 0, err - } - - if !bytes.HasPrefix(raw, []byte("pid=")) { - return 0, fmt.Errorf("malformed response from OpenVPN") - } - - pid, err := strconv.Atoi(string(raw[4:])) - if err != nil { - return 0, fmt.Errorf("error parsing pid from OpenVPN: %s", err) - } - - return pid, nil -} - -func (c *MgmtClient) sendCommand(cmd []byte) error { - _, err := c.wr.Write(cmd) - if err != nil { - return err - } - _, err = c.wr.Write(newline) - return err -} - -// sendCommandPayload can be called after sendCommand for -// commands that expect a multi-line input payload. -// -// The buffer given in 'payload' *must* end with a newline, -// or else the protocol will be broken. -func (c *MgmtClient) sendCommandPayload(payload []byte) error { - _, err := c.wr.Write(payload) - if err != nil { - return err - } - _, err = c.wr.Write(endMessage) - if err != nil { - return err - } - _, err = c.wr.Write(newline) - return err -} - -func (c *MgmtClient) readCommandResult() ([]byte, error) { - reply, ok := <-c.replies - if !ok { - return nil, fmt.Errorf("connection closed while awaiting result") - } - - if bytes.HasPrefix(reply, successPrefix) { - result := reply[len(successPrefix):] - return result, nil - } - - if bytes.HasPrefix(reply, errorPrefix) { - message := reply[len(errorPrefix):] - return nil, ErrorFromServer(message) - } - - return nil, fmt.Errorf("malformed result message") -} - -func (c *MgmtClient) readCommandResponsePayload() ([][]byte, error) { - lines := make([][]byte, 0, 10) - - for { - line, ok := <-c.replies - if !ok { - // We'll give the caller whatever we got before the connection - // closed, in case it's useful for debugging. - return lines, fmt.Errorf("connection closed before END recieved") - } - - if bytes.Equal(line, endMessage) { - break - } - - lines = append(lines, line) - } - - return lines, nil -} - -func (c *MgmtClient) simpleCommand(cmd string) ([]byte, error) { - err := c.sendCommand([]byte(cmd)) - if err != nil { - return nil, err - } - return c.readCommandResult() -} diff --git a/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/error.go b/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/error.go deleted file mode 100644 index 554e2ef..0000000 --- a/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/error.go +++ /dev/null @@ -1,11 +0,0 @@ -package openvpn - -type ErrorFromServer []byte - -func (err ErrorFromServer) Error() string { - return string(err) -} - -func (err ErrorFromServer) String() string { - return string(err) -} diff --git a/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/event.go b/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/event.go deleted file mode 100644 index 66625f3..0000000 --- a/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/event.go +++ /dev/null @@ -1,299 +0,0 @@ -package openvpn - -import ( - "bytes" - "fmt" - "strconv" -) - -var eventSep = []byte(":") -var fieldSep = []byte(",") -var byteCountEventKW = []byte("BYTECOUNT") -var byteCountCliEventKW = []byte("BYTECOUNT_CLI") -var clientEventKW = []byte("CLIENT") -var echoEventKW = []byte("ECHO") -var fatalEventKW = []byte("FATAL") -var holdEventKW = []byte("HOLD") -var infoEventKW = []byte("INFO") -var logEventKW = []byte("LOG") -var needOkEventKW = []byte("NEED-OK") -var needStrEventKW = []byte("NEED-STR") -var passwordEventKW = []byte("PASSWORD") -var stateEventKW = []byte("STATE") - -type Event interface { - String() string -} - -// UnknownEvent represents an event of a type that this package doesn't -// know about. -// -// Future versions of this library may learn about new event types, so a -// caller should exercise caution when making use of events of this type -// to access unsupported behavior. Backward-compatibility is *not* -// guaranteed for events of this type. -type UnknownEvent struct { - keyword []byte - body []byte -} - -func (e *UnknownEvent) Type() string { - return string(e.keyword) -} - -func (e *UnknownEvent) Body() string { - return string(e.body) -} - -func (e *UnknownEvent) String() string { - return fmt.Sprintf("%s: %s", e.keyword, e.body) -} - -// MalformedEvent represents a message from the OpenVPN process that is -// presented as an event but does not comply with the expected event syntax. -// -// Events of this type should never be seen but robust callers will accept -// and ignore them, possibly generating some kind of debugging message. -// -// One reason for potentially seeing events of this type is when the target -// program is actually not an OpenVPN process at all, but in fact this client -// has been connected to a different sort of server by mistake. -type MalformedEvent struct { - raw []byte -} - -func (e *MalformedEvent) String() string { - return fmt.Sprintf("Malformed Event %q", e.raw) -} - -// HoldEvent is a notification that the OpenVPN process is in a management -// hold and will not continue connecting until the hold is released, e.g. -// by calling client.HoldRelease() -type HoldEvent struct { - body []byte -} - -func (e *HoldEvent) String() string { - return string(e.body) -} - -// StateEvent is a notification of a change of connection state. It can be -// used, for example, to detect if the OpenVPN connection has been interrupted -// and the OpenVPN process is attempting to reconnect. -type StateEvent struct { - body []byte - - // bodyParts is populated only on first request, giving us the - // separate comma-separated elements of the message. Not all - // fields are populated for all states. - bodyParts [][]byte -} - -func (e *StateEvent) RawTimestamp() string { - parts := e.parts() - return string(parts[0]) -} - -func (e *StateEvent) NewState() string { - parts := e.parts() - return string(parts[1]) -} - -func (e *StateEvent) Description() string { - parts := e.parts() - return string(parts[2]) -} - -// LocalTunnelAddr returns the IP address of the local interface within -// the tunnel, as a string that can be parsed using net.ParseIP. -// -// This field is only populated for events whose NewState returns -// either ASSIGN_IP or CONNECTED. -func (e *StateEvent) LocalTunnelAddr() string { - parts := e.parts() - return string(parts[3]) -} - -// RemoteAddr returns the non-tunnel IP address of the remote -// system that has connected to the local OpenVPN process. -// -// This field is only populated for events whose NewState returns -// CONNECTED. -func (e *StateEvent) RemoteAddr() string { - parts := e.parts() - return string(parts[4]) -} - -func (e *StateEvent) String() string { - newState := e.NewState() - switch newState { - case "ASSIGN_IP": - return fmt.Sprintf("%s: %s", newState, e.LocalTunnelAddr()) - case "CONNECTED": - return fmt.Sprintf("%s: %s", newState, e.RemoteAddr()) - default: - desc := e.Description() - if desc != "" { - return fmt.Sprintf("%s: %s", newState, desc) - } else { - return newState - } - } -} - -func (e *StateEvent) parts() [][]byte { - if e.bodyParts == nil { - // State messages currently have only five segments, but - // we'll ask for 5 so any additional fields that might show - // up in newer versions will gather in an element we're - // not actually using. - e.bodyParts = bytes.SplitN(e.body, fieldSep, 6) - - // Prevent crash if the server has sent us a malformed - // status message. This should never actually happen if - // the server is behaving itself. - if len(e.bodyParts) < 5 { - expanded := make([][]byte, 5) - copy(expanded, e.bodyParts) - e.bodyParts = expanded - } - } - return e.bodyParts -} - -// EchoEvent is emitted by an OpenVPN process running in client mode when -// an "echo" command is pushed to it by the server it has connected to. -// -// The format of the echo message is free-form, since this message type is -// intended to pass application-specific data from the server-side config -// into whatever client is consuming the management prototcol. -// -// This event is emitted only if the management client has turned on events -// of this type using client.SetEchoEvents(true) -type EchoEvent struct { - body []byte -} - -func (e *EchoEvent) RawTimestamp() string { - sepIndex := bytes.Index(e.body, fieldSep) - if sepIndex == -1 { - return "" - } - return string(e.body[:sepIndex]) -} - -func (e *EchoEvent) Message() string { - sepIndex := bytes.Index(e.body, fieldSep) - if sepIndex == -1 { - return "" - } - return string(e.body[sepIndex+1:]) -} - -func (e *EchoEvent) String() string { - return fmt.Sprintf("ECHO: %s", e.Message()) -} - -// ByteCountEvent represents a periodic snapshot of data transfer in bytes -// on a VPN connection. -// -// For OpenVPN *servers*, events are emitted for each client and the method -// ClientId identifies thet client. -// -// For other OpenVPN modes, events are emitted only once per interval for the -// single connection managed by the target process, and ClientId returns -// the empty string. -type ByteCountEvent struct { - hasClient bool - body []byte - - // populated on first call to parts() - bodyParts [][]byte -} - -func (e *ByteCountEvent) ClientId() string { - if !e.hasClient { - return "" - } - - return string(e.parts()[0]) -} - -func (e *ByteCountEvent) BytesIn() int { - index := 0 - if e.hasClient { - index = 1 - } - str := string(e.parts()[index]) - val, _ := strconv.Atoi(str) - // Ignore error, since this should never happen if OpenVPN is - // behaving itself. - return val -} - -func (e *ByteCountEvent) BytesOut() int { - index := 1 - if e.hasClient { - index = 2 - } - str := string(e.parts()[index]) - val, _ := strconv.Atoi(str) - // Ignore error, since this should never happen if OpenVPN is - // behaving itself. - return val -} - -func (e *ByteCountEvent) String() string { - if e.hasClient { - return fmt.Sprintf("Client %s: %d in, %d out", e.ClientId(), e.BytesIn(), e.BytesOut()) - } else { - return fmt.Sprintf("%d in, %d out", e.BytesIn(), e.BytesOut()) - } -} - -func (e *ByteCountEvent) parts() [][]byte { - if e.bodyParts == nil { - e.bodyParts = bytes.SplitN(e.body, fieldSep, 4) - - wantCount := 2 - if e.hasClient { - wantCount = 3 - } - - // Prevent crash if the server has sent us a malformed - // message. This should never actually happen if the - // server is behaving itself. - if len(e.bodyParts) < wantCount { - expanded := make([][]byte, wantCount) - copy(expanded, e.bodyParts) - e.bodyParts = expanded - } - } - return e.bodyParts -} - -func upgradeEvent(raw []byte) Event { - splitIdx := bytes.Index(raw, eventSep) - if splitIdx == -1 { - // Should never happen, but we'll handle it robustly if it does. - return &MalformedEvent{raw} - } - - keyword := raw[:splitIdx] - body := raw[splitIdx+1:] - - switch { - case bytes.Equal(keyword, stateEventKW): - return &StateEvent{body: body} - case bytes.Equal(keyword, holdEventKW): - return &HoldEvent{body} - case bytes.Equal(keyword, echoEventKW): - return &EchoEvent{body} - case bytes.Equal(keyword, byteCountEventKW): - return &ByteCountEvent{hasClient: false, body: body} - case bytes.Equal(keyword, byteCountCliEventKW): - return &ByteCountEvent{hasClient: true, body: body} - default: - return &UnknownEvent{keyword, body} - } -} diff --git a/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/server.go b/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/server.go deleted file mode 100644 index d7defd4..0000000 --- a/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/server.go +++ /dev/null @@ -1,172 +0,0 @@ -package openvpn - -import ( - "net" - "time" -) - -// MgmtListener accepts incoming connections from OpenVPN. -// -// The primary way to instantiate this type is via the function Listen. -// See its documentation for more information. -type MgmtListener struct { - l net.Listener -} - -// NewMgmtListener constructs a MgmtListener from an already-established -// net.Listener. In most cases it will be more convenient to use -// the function Listen. -func NewMgmtListener(l net.Listener) *MgmtListener { - return &MgmtListener{l} -} - -// Listen opens a listen port and awaits incoming connections from OpenVPN -// processes. -// -// OpenVPN will behave in this manner when launched with the following options: -// -// --management ipaddr port --management-client -// -// Note that in this case the terminology is slightly confusing, since from -// the standpoint of TCP/IP it is OpenVPN that is the client and our program -// that is the server, but once the connection is established the channel -// is indistinguishable from the situation where OpenVPN exposed a management -// *server* and we connected to it. Thus we still refer to our program as -// the "client" and OpenVPN as the "server" once the connection is established. -// -// When running on Unix systems it's possible to instead listen on a Unix -// domain socket. To do this, pass an absolute path to the socket as -// the listen address, and then run OpenVPN with the following options: -// -// --management /path/to/socket unix --management-client -// -func Listen(laddr string) (*MgmtListener, error) { - proto := "tcp" - if len(laddr) > 0 && laddr[0] == '/' { - proto = "unix" - } - listener, err := net.Listen(proto, laddr) - if err != nil { - return nil, err - } - - return NewMgmtListener(listener), nil -} - -// Accept waits for and returns the next connection. -func (l *MgmtListener) Accept() (*IncomingConn, error) { - conn, err := l.l.Accept() - if err != nil { - return nil, err - } - - return &IncomingConn{conn}, nil -} - -// Close closes the listener. Any blocked Accept operations -// will be blocked and each will return an error. -func (l *MgmtListener) Close() error { - return l.l.Close() -} - -// Addr returns the listener's network address. -func (l *MgmtListener) Addr() net.Addr { - return l.l.Addr() -} - -// Serve will await new connections and call the given handler -// for each. -// -// Serve does not return unless the listen port is closed; a non-nil -// error is always returned. -func (l *MgmtListener) Serve(handler IncomingConnHandler) error { - defer l.Close() - - var tempDelay time.Duration - - for { - incoming, err := l.Accept() - if err != nil { - if ne, ok := err.(net.Error); ok && ne.Temporary() { - if tempDelay == 0 { - tempDelay = 5 * time.Millisecond - } else { - tempDelay *= 2 - } - if max := 1 * time.Second; tempDelay > max { - tempDelay = max - } - - // Wait a while before we try again. - time.Sleep(tempDelay) - continue - } else { - // Listen socket is permanently closed or errored, - // so it's time for us to exit. - return err - } - } - - // always reset our retry delay once we successfully read - tempDelay = 0 - - go handler.ServeOpenVPNMgmt(*incoming) - } -} - -type IncomingConn struct { - conn net.Conn -} - -// Open initiates communication with the connected OpenVPN process, -// and establishes the channel on which events will be delivered. -// -// See the documentation for NewClient for discussion about the requirements -// for eventCh. -func (ic IncomingConn) Open(eventCh chan<- Event) *MgmtClient { - return NewClient(ic.conn, eventCh) -} - -// Close abruptly closes the socket connected to the OpenVPN process. -// -// This is a rather abrasive way to close the channel, intended for rejecting -// unwanted incoming clients that may or may not speak the OpenVPN protocol. -// -// Once communication is accepted and established, it is generally better -// to close the connection gracefully using commands on the client returned -// from Open. -func (ic IncomingConn) Close() error { - return ic.conn.Close() -} - -type IncomingConnHandler interface { - ServeOpenVPNMgmt(IncomingConn) -} - -// IncomingConnHandlerFunc is an adapter to allow the use of ordinary -// functions as connection handlers. -// -// Given a function with the appropriate signature, IncomingConnHandlerFunc(f) -// is an IncomingConnHandler that calls f. -type IncomingConnHandlerFunc func(IncomingConn) - -func (f IncomingConnHandlerFunc) ServeOpenVPNMgmt(i IncomingConn) { - f(i) -} - -// ListenAndServe creates a MgmtListener for the given listen address -// and then calls AcceptAndServe on it. -// -// This is just a convenience wrapper. See the AcceptAndServe method for -// more details. Just as with AcceptAndServe, this function does not return -// except on error; in addition to the error cases handled by AcceptAndServe, -// this function may also fail if the listen socket cannot be established -// in the first place. -func ListenAndServe(laddr string, handler IncomingConnHandler) error { - listener, err := Listen(laddr) - if err != nil { - return err - } - - return listener.Serve(handler) -} |