github.com/adityamillind98/moby@v23.0.0-rc.4+incompatible/libnetwork/portmapper/proxy_linux.go (about) 1 package portmapper 2 3 import ( 4 "fmt" 5 "io" 6 "net" 7 "os" 8 "os/exec" 9 "strconv" 10 "syscall" 11 "time" 12 ) 13 14 const userlandProxyCommandName = "docker-proxy" 15 16 func newProxyCommand(proto string, hostIP net.IP, hostPort int, containerIP net.IP, containerPort int, proxyPath string) (userlandProxy, error) { 17 path := proxyPath 18 if proxyPath == "" { 19 cmd, err := exec.LookPath(userlandProxyCommandName) 20 if err != nil { 21 return nil, err 22 } 23 path = cmd 24 } 25 26 args := []string{ 27 path, 28 "-proto", proto, 29 "-host-ip", hostIP.String(), 30 "-host-port", strconv.Itoa(hostPort), 31 "-container-ip", containerIP.String(), 32 "-container-port", strconv.Itoa(containerPort), 33 } 34 35 return &proxyCommand{ 36 cmd: &exec.Cmd{ 37 Path: path, 38 Args: args, 39 SysProcAttr: &syscall.SysProcAttr{ 40 Pdeathsig: syscall.SIGTERM, // send a sigterm to the proxy if the daemon process dies 41 }, 42 }, 43 }, nil 44 } 45 46 // proxyCommand wraps an exec.Cmd to run the userland TCP and UDP 47 // proxies as separate processes. 48 type proxyCommand struct { 49 cmd *exec.Cmd 50 } 51 52 func (p *proxyCommand) Start() error { 53 r, w, err := os.Pipe() 54 if err != nil { 55 return fmt.Errorf("proxy unable to open os.Pipe %s", err) 56 } 57 defer r.Close() 58 p.cmd.ExtraFiles = []*os.File{w} 59 if err := p.cmd.Start(); err != nil { 60 return err 61 } 62 w.Close() 63 64 errchan := make(chan error, 1) 65 go func() { 66 buf := make([]byte, 2) 67 r.Read(buf) 68 69 if string(buf) != "0\n" { 70 errStr, err := io.ReadAll(r) 71 if err != nil { 72 errchan <- fmt.Errorf("Error reading exit status from userland proxy: %v", err) 73 return 74 } 75 76 errchan <- fmt.Errorf("Error starting userland proxy: %s", errStr) 77 return 78 } 79 errchan <- nil 80 }() 81 82 select { 83 case err := <-errchan: 84 return err 85 case <-time.After(16 * time.Second): 86 return fmt.Errorf("Timed out proxy starting the userland proxy") 87 } 88 } 89 90 func (p *proxyCommand) Stop() error { 91 if p.cmd.Process != nil { 92 if err := p.cmd.Process.Signal(os.Interrupt); err != nil { 93 return err 94 } 95 return p.cmd.Wait() 96 } 97 return nil 98 }