summaryrefslogtreecommitdiff
path: root/vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/udp/udp.go
blob: 0080dd22c44ccfc476a5f79e3b73b2f6056dde30 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package udp

import (
	"io"
	"net"
	"os"
	"strconv"

	"github.com/pkg/errors"

	"github.com/rootless-containers/rootlesskit/pkg/port"
	"github.com/rootless-containers/rootlesskit/pkg/port/builtin/msg"
	"github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/udp/udpproxy"
)

func Run(socketPath string, spec port.Spec, stopCh <-chan struct{}, logWriter io.Writer) error {
	addr, err := net.ResolveUDPAddr(spec.Proto, net.JoinHostPort(spec.ParentIP, strconv.Itoa(spec.ParentPort)))
	if err != nil {
		return err
	}
	c, err := net.ListenUDP(spec.Proto, addr)
	if err != nil {
		return err
	}
	udpp := &udpproxy.UDPProxy{
		LogWriter: logWriter,
		Listener:  c,
		BackendDial: func() (*net.UDPConn, error) {
			// get fd from the child as an SCM_RIGHTS cmsg
			fd, err := msg.ConnectToChildWithRetry(socketPath, spec, 10)
			if err != nil {
				return nil, err
			}
			f := os.NewFile(uintptr(fd), "")
			defer f.Close()
			fc, err := net.FileConn(f)
			if err != nil {
				return nil, err
			}
			uc, ok := fc.(*net.UDPConn)
			if !ok {
				return nil, errors.Errorf("file conn doesn't implement *net.UDPConn: %+v", fc)
			}
			return uc, nil
		},
	}
	go udpp.Run()
	go func() {
		for {
			select {
			case <-stopCh:
				// udpp.Close closes ln as well
				udpp.Close()
				return
			}
		}
	}()
	// no wait
	return nil
}