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 }