github.com/rootless-containers/rootlesskit/v2@v2.3.4/pkg/port/builtin/parent/udp/udp.go (about) 1 package udp 2 3 import ( 4 "fmt" 5 "io" 6 "net" 7 "os" 8 "strconv" 9 10 "github.com/rootless-containers/rootlesskit/v2/pkg/port" 11 "github.com/rootless-containers/rootlesskit/v2/pkg/port/builtin/msg" 12 "github.com/rootless-containers/rootlesskit/v2/pkg/port/builtin/parent/udp/udpproxy" 13 ) 14 15 func Run(socketPath string, spec port.Spec, stopCh <-chan struct{}, stoppedCh chan error, logWriter io.Writer) error { 16 addr, err := net.ResolveUDPAddr(spec.Proto, net.JoinHostPort(spec.ParentIP, strconv.Itoa(spec.ParentPort))) 17 if err != nil { 18 return err 19 } 20 c, err := net.ListenUDP(spec.Proto, addr) 21 if err != nil { 22 return err 23 } 24 udpp := &udpproxy.UDPProxy{ 25 LogWriter: logWriter, 26 Listener: c, 27 BackendDial: func() (*net.UDPConn, error) { 28 // get fd from the child as an SCM_RIGHTS cmsg 29 fd, err := msg.ConnectToChildWithRetry(socketPath, spec, 10) 30 if err != nil { 31 return nil, err 32 } 33 f := os.NewFile(uintptr(fd), "") 34 defer f.Close() 35 fc, err := net.FileConn(f) 36 if err != nil { 37 return nil, err 38 } 39 uc, ok := fc.(*net.UDPConn) 40 if !ok { 41 return nil, fmt.Errorf("file conn doesn't implement *net.UDPConn: %+v", fc) 42 } 43 return uc, nil 44 }, 45 } 46 go udpp.Run() 47 go func() { 48 for { 49 select { 50 case <-stopCh: 51 // udpp.Close closes ln as well 52 udpp.Close() 53 stoppedCh <- nil 54 close(stoppedCh) 55 return 56 } 57 } 58 }() 59 // no wait 60 return nil 61 }