github.com/noisysockets/noisysockets@v0.21.2-0.20240515114641-7f467e651c90/internal/conn/conn.go (about)

     1  // SPDX-License-Identifier: MPL-2.0
     2  /*
     3   * Copyright (C) 2024 The Noisy Sockets Authors.
     4   *
     5   * This Source Code Form is subject to the terms of the Mozilla Public
     6   * License, v. 2.0. If a copy of the MPL was not distributed with this
     7   * file, You can obtain one at http://mozilla.org/MPL/2.0/.
     8   *
     9   * Portions of this file are based on code originally from wireguard-go,
    10   *
    11   * Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
    12   *
    13   * Permission is hereby granted, free of charge, to any person obtaining a copy of
    14   * this software and associated documentation files (the "Software"), to deal in
    15   * the Software without restriction, including without limitation the rights to
    16   * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
    17   * of the Software, and to permit persons to whom the Software is furnished to do
    18   * so, subject to the following conditions:
    19   *
    20   * The above copyright notice and this permission notice shall be included in all
    21   * copies or substantial portions of the Software.
    22   *
    23   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    24   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    25   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    26   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    27   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    28   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    29   * SOFTWARE.
    30   */
    31  
    32  // Package conn implements WireGuard's network connections.
    33  package conn
    34  
    35  import (
    36  	"errors"
    37  	"fmt"
    38  	"net/netip"
    39  	"reflect"
    40  	"runtime"
    41  	"strings"
    42  )
    43  
    44  const (
    45  	IdealBatchSize = 128 // maximum number of packets handled per read and write
    46  )
    47  
    48  // A ReceiveFunc receives at least one packet from the network and writes them
    49  // into packets. On a successful read it returns the number of elements of
    50  // sizes, packets, and endpoints that should be evaluated. Some elements of
    51  // sizes may be zero, and callers should ignore them. Callers must pass a sizes
    52  // and eps slice with a length greater than or equal to the length of packets.
    53  // These lengths must not exceed the length of the associated Bind.BatchSize().
    54  type ReceiveFunc func(packets [][]byte, sizes []int, eps []Endpoint) (n int, err error)
    55  
    56  // A Bind listens on a port for both IPv6 and IPv4 UDP traffic.
    57  //
    58  // A Bind interface may also be a PeekLookAtSocketFd or BindSocketToInterface,
    59  // depending on the platform-specific implementation.
    60  type Bind interface {
    61  	// Open puts the Bind into a listening state on a given port and reports the actual
    62  	// port that it bound to. Passing zero results in a random selection.
    63  	// fns is the set of functions that will be called to receive packets.
    64  	Open(port uint16) (fns []ReceiveFunc, actualPort uint16, err error)
    65  
    66  	// Close closes the Bind listener.
    67  	// All fns returned by Open must return net.ErrClosed after a call to Close.
    68  	Close() error
    69  
    70  	// Send writes one or more packets in bufs to address ep. The length of
    71  	// bufs must not exceed BatchSize().
    72  	Send(bufs [][]byte, ep Endpoint) error
    73  
    74  	// ParseEndpoint creates a new endpoint from a string.
    75  	ParseEndpoint(s string) (Endpoint, error)
    76  
    77  	// BatchSize is the number of buffers expected to be passed to
    78  	// the ReceiveFuncs, and the maximum expected to be passed to SendBatch.
    79  	BatchSize() int
    80  }
    81  
    82  // An Endpoint maintains the source/destination caching for a peer.
    83  //
    84  //	dst: the remote address of a peer ("endpoint" in uapi terminology)
    85  //	src: the local address from which datagrams originate going to the peer
    86  type Endpoint interface {
    87  	DstToString() string // returns the destination address (ip:port)
    88  	DstToBytes() []byte  // used for mac2 cookie calculations
    89  	DstIP() netip.Addr
    90  }
    91  
    92  var (
    93  	ErrBindAlreadyOpen   = errors.New("bind is already open")
    94  	ErrWrongEndpointType = errors.New("endpoint type does not correspond with bind type")
    95  )
    96  
    97  func (fn ReceiveFunc) PrettyName() string {
    98  	name := runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name()
    99  	// 0. cheese/taco.beansIPv6.func12.func21218-fm
   100  	name = strings.TrimSuffix(name, "-fm")
   101  	// 1. cheese/taco.beansIPv6.func12.func21218
   102  	if idx := strings.LastIndexByte(name, '/'); idx != -1 {
   103  		name = name[idx+1:]
   104  		// 2. taco.beansIPv6.func12.func21218
   105  	}
   106  	for {
   107  		var idx int
   108  		for idx = len(name) - 1; idx >= 0; idx-- {
   109  			if name[idx] < '0' || name[idx] > '9' {
   110  				break
   111  			}
   112  		}
   113  		if idx == len(name)-1 {
   114  			break
   115  		}
   116  		const dotFunc = ".func"
   117  		if !strings.HasSuffix(name[:idx+1], dotFunc) {
   118  			break
   119  		}
   120  		name = name[:idx+1-len(dotFunc)]
   121  		// 3. taco.beansIPv6.func12
   122  		// 4. taco.beansIPv6
   123  	}
   124  	if idx := strings.LastIndexByte(name, '.'); idx != -1 {
   125  		name = name[idx+1:]
   126  		// 5. beansIPv6
   127  	}
   128  	if name == "" {
   129  		return fmt.Sprintf("%p", fn)
   130  	}
   131  	if strings.HasSuffix(name, "IPv4") {
   132  		return "v4"
   133  	}
   134  	if strings.HasSuffix(name, "IPv6") {
   135  		return "v6"
   136  	}
   137  	return name
   138  }