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  }