lab.nexedi.com/kirr/go123@v0.0.0-20240207185015-8299741fa871/xnet/virtnet/interfaces.go (about) 1 // Copyright (C) 2018-2020 Nexedi SA and Contributors. 2 // Kirill Smelkov <kirr@nexedi.com> 3 // 4 // This program is free software: you can Use, Study, Modify and Redistribute 5 // it under the terms of the GNU General Public License version 3, or (at your 6 // option) any later version, as published by the Free Software Foundation. 7 // 8 // You can also Link and Combine this program with other software covered by 9 // the terms of any of the Free Software licenses or any of the Open Source 10 // Initiative approved licenses and Convey the resulting work. Corresponding 11 // source of such a combination shall include the source code for all other 12 // software used. 13 // 14 // This program is distributed WITHOUT ANY WARRANTY; without even the implied 15 // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 16 // 17 // See COPYING file for full licensing terms. 18 // See https://www.nexedi.com/licensing for rationale and options. 19 20 package virtnet 21 // interfaces that virtnet uses in its working. 22 23 import ( 24 "context" 25 "errors" 26 "fmt" 27 "net" 28 ) 29 30 // Engine is the interface for particular virtnet network implementation to be 31 // used by SubNetwork. 32 // 33 // A virtnet network implementation should provide Engine instance to 34 // SubNetwork when creating it. The subnetwork will use provided engine for its 35 // operations. 36 // 37 // It should be safe to access Engine from multiple goroutines simultaneously. 38 type Engine interface { 39 // VNetNewHost creates resources for host and announces it to registry. 40 // 41 // VNetNewHost should create resources for new host and announce 42 // hostname to provided registry. When announcing it should encode in 43 // hostdata a way for VNetDial - potentially run on another subnetwork 44 // - to find out where to connect to when dialing to this host. 45 // 46 // On error the returned error will be wrapped by virtnet with "new 47 // host" operation and hostname. 48 VNetNewHost(ctx context.Context, hostname string, registry Registry) error 49 50 // VNetDial creates outbound virtnet connection. 51 // 52 // VNetDial, given destination virtnet address and destination 53 // hostdata, should establish connection to destination. It should let 54 // remote side know that its peer virtnet address is src. 55 // 56 // On success net.Conn that will be handling data exchange via its 57 // Read/Write should be returned. This net.Conn will be wrapped by 58 // virtnet with overwritten LocalAddr and RemoteAddr to be src and 59 // addrAccept correspondingly. 60 // 61 // On error the returned error will be wrapped by virtnet with 62 // corresponding net.OpError{"dial", src, dst}. 63 // 64 // Virtnet always passes to VNetDial src and dst with the same network 65 // name that was used when creating corresponding SubNetwork. 66 VNetDial(ctx context.Context, src, dst *Addr, dsthostdata string) (_ net.Conn, addrAccept *Addr, _ error) 67 68 // Close shuts down subnetwork engine. 69 // 70 // Close should close engine resources and return corresponding error. 71 // 72 // There is no need to explicitly interrupt other engine operations - 73 // to those virtnet always passes ctx that is canceled before 74 // engine.Close is called. 75 Close() error 76 } 77 78 79 // Notifier is the interface to be used by particular virtnet network 80 // implementation for notifying SubNetwork. 81 // 82 // A virtnet network implementation receives instance of Notifier together with 83 // SubNetwork when creating it. The network implementation should use provided 84 // Notifier to notify the subnetwork to handle incoming events. 85 // 86 // It should be safe to access Notifier from multiple goroutines simultaneously. 87 type Notifier interface { 88 // VNetAccept notifies virtnet about incoming connection. 89 // 90 // VNetAccept, given destination virtnet address, should make decision 91 // to either accept or reject provided connection. 92 // 93 // On success the connection is pre-accepted and corresponding Accept 94 // is returned to virtnet network implementation. 95 // 96 // On error an error is returned without any "accept" prefix, e.g. 97 // ErrConnRefused. Such accept prefix should be provided by network 98 // implementation that is using VNetAccept. 99 VNetAccept(ctx context.Context, src, dst *Addr, netconn net.Conn) (*Accept, error) 100 101 // VNetDown notifies virtnet that underlying network is down. 102 // 103 // Provided err describes the cause of why the network is down. 104 VNetDown(err error) 105 } 106 107 // Accept represents successful acceptance decision from Notifier.VNetAccept . 108 // 109 // On successful accept decision corresponding virtnet-level Accept() is 110 // waiting on .Ack to continue and will check the error from there. 111 // 112 // On success the connection will be finally accepted and corresponding virtnet 113 // listener will be notified. Provided netconn will be adjusted by virtnet 114 // internally with overwritten LocalAddr and RemoteAddr to be correspondingly 115 // .Addr and src that was originally passed to VNetAccept. 116 // 117 // On error the acceptance will be canceled. 118 type Accept struct { 119 Addr *Addr // accepting with this local address 120 Ack chan error 121 } 122 123 124 // Registry represents access to a virtnet network registry. 125 // 126 // A virtnet network implementation should provide Registry instance to 127 // SubNetwork when creating it. The subnetwork will eventually use it when 128 // creating hosts via NewHost, and in turn creating outbound connections on 129 // them via Host.Dial. 130 // 131 // The registry holds information about hosts available on the network, and 132 // for each host additional data about it. Whenever host α needs to establish 133 // connection to address on host β, it queries the registry for β. 134 // Correspondingly when a host joins the network, it announces itself to the 135 // registry so that other hosts could see it. 136 // 137 // The registry could be implemented in several ways, for example: 138 // 139 // - dedicated network server, 140 // - hosts broadcasting information to each other similar to ARP, 141 // - shared memory or file, 142 // - ... 143 // 144 // It should be safe to access registry from multiple goroutines simultaneously. 145 type Registry interface { 146 // Announce announces host to registry. 147 // 148 // Returned error, if !nil, is *RegistryError with .Err describing the 149 // error cause: 150 // 151 // - ErrRegistryDown if registry cannot be accessed, 152 // - ErrHostDup if hostname was already announced, 153 // - some other error indicating e.g. IO problem. 154 Announce(ctx context.Context, hostname, hostdata string) error 155 156 // Query queries registry for host. 157 // 158 // Returned error, if !nil, is *RegistryError with .Err describing the 159 // error cause: 160 // 161 // - ErrRegistryDown if registry cannot be accessed, 162 // - ErrNoHost if hostname was not announced to registry, 163 // - some other error indicating e.g. IO problem. 164 Query(ctx context.Context, hostname string) (hostdata string, _ error) 165 166 // Close closes access to registry. 167 // 168 // Close should close registry resources and return corresponding error. 169 // 170 // There is no need to explicitly interrupt other registry operations - 171 // to those virtnet always passes ctx that is canceled before 172 // registry.Close is called. 173 Close() error 174 } 175 176 var ( 177 ErrRegistryDown = errors.New("registry is down") 178 ErrNoHost = errors.New("no such host") 179 ErrHostDup = errors.New("host already registered") 180 ) 181 182 // RegistryError represents an error of a registry operation. 183 type RegistryError struct { 184 Registry string // name of the registry 185 Op string // operation that failed 186 Args interface{} // operation arguments, if any 187 Err error // actual error that occurred during the operation 188 } 189 190 func (e *RegistryError) Error() string { 191 s := e.Registry + ": " + e.Op 192 if e.Args != nil { 193 s += fmt.Sprintf(" %q", e.Args) 194 } 195 s += ": " + e.Err.Error() 196 return s 197 } 198 199 func (e *RegistryError) Cause() error { return e.Err } 200 func (e *RegistryError) Unwrap() error { return e.Err }