github.com/flowerwrong/netstack@v0.0.0-20191009141956-e5848263af28/tcpip/transport/udp/forwarder.go (about) 1 // Copyright 2019 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package udp 16 17 import ( 18 "github.com/FlowerWrong/netstack/tcpip" 19 "github.com/FlowerWrong/netstack/tcpip/buffer" 20 "github.com/FlowerWrong/netstack/tcpip/stack" 21 "github.com/FlowerWrong/netstack/waiter" 22 ) 23 24 // Forwarder is a session request forwarder, which allows clients to decide 25 // what to do with a session request, for example: ignore it, or process it. 26 // 27 // The canonical way of using it is to pass the Forwarder.HandlePacket function 28 // to stack.SetTransportProtocolHandler. 29 type Forwarder struct { 30 handler func(*ForwarderRequest) 31 32 stack *stack.Stack 33 } 34 35 // NewForwarder allocates and initializes a new forwarder. 36 func NewForwarder(s *stack.Stack, handler func(*ForwarderRequest)) *Forwarder { 37 return &Forwarder{ 38 stack: s, 39 handler: handler, 40 } 41 } 42 43 // HandlePacket handles all packets. 44 // 45 // This function is expected to be passed as an argument to the 46 // stack.SetTransportProtocolHandler function. 47 func (f *Forwarder) HandlePacket(r *stack.Route, id stack.TransportEndpointID, netHeader buffer.View, vv buffer.VectorisedView) bool { 48 f.handler(&ForwarderRequest{ 49 stack: f.stack, 50 route: r, 51 id: id, 52 vv: vv, 53 }) 54 55 return true 56 } 57 58 // ForwarderRequest represents a session request received by the forwarder and 59 // passed to the client. Clients may optionally create an endpoint to represent 60 // it via CreateEndpoint. 61 type ForwarderRequest struct { 62 stack *stack.Stack 63 route *stack.Route 64 id stack.TransportEndpointID 65 vv buffer.VectorisedView 66 } 67 68 // ID returns the 4-tuple (src address, src port, dst address, dst port) that 69 // represents the session request. 70 func (r *ForwarderRequest) ID() stack.TransportEndpointID { 71 return r.id 72 } 73 74 // CreateEndpoint creates a connected UDP endpoint for the session request. 75 func (r *ForwarderRequest) CreateEndpoint(queue *waiter.Queue) (tcpip.Endpoint, *tcpip.Error) { 76 ep := newEndpoint(r.stack, r.route.NetProto, queue) 77 if err := r.stack.RegisterTransportEndpoint(r.route.NICID(), []tcpip.NetworkProtocolNumber{r.route.NetProto}, ProtocolNumber, r.id, ep, ep.reusePort, ep.bindToDevice); err != nil { 78 ep.Close() 79 return nil, err 80 } 81 82 ep.id = r.id 83 ep.route = r.route.Clone() 84 ep.dstPort = r.id.RemotePort 85 ep.regNICID = r.route.NICID() 86 87 ep.state = StateConnected 88 89 ep.rcvMu.Lock() 90 ep.rcvReady = true 91 ep.rcvMu.Unlock() 92 93 ep.HandlePacket(r.route, r.id, r.vv) 94 95 return ep, nil 96 }