From 3049a7ff16f487aab94288fc58222c2b540e22a6 Mon Sep 17 00:00:00 2001 From: abhi Date: Fri, 23 Mar 2018 22:36:39 -0700 Subject: [PATCH] Getting rid of socat Signed-off-by: abhi --- pkg/server/sandbox_portforward.go | 56 +++++++++++-------------------- 1 file changed, 20 insertions(+), 36 deletions(-) diff --git a/pkg/server/sandbox_portforward.go b/pkg/server/sandbox_portforward.go index 137b20f48..e40e8f95a 100644 --- a/pkg/server/sandbox_portforward.go +++ b/pkg/server/sandbox_portforward.go @@ -17,11 +17,10 @@ limitations under the License. package server import ( - "bytes" "fmt" "io" - "os/exec" - "strings" + "net" + "sync" "github.com/containernetworking/plugins/pkg/ns" "github.com/pkg/errors" @@ -58,46 +57,31 @@ func (c *criService) portForward(id string, port int32, stream io.ReadWriteClose return errors.Errorf("failed to find network namespace fo sandbox %q in store", id) } - socat, err := exec.LookPath("socat") - if err != nil { - return errors.Wrap(err, "failed to find socat") - } - - // Check following links for meaning of the options: - // * socat: https://linux.die.net/man/1/socat - args := []string{"-", fmt.Sprintf("TCP4:localhost:%d", port)} - logrus.Infof("Executing port forwarding command: %s %s", socat, strings.Join(args, " ")) err = s.NetNS.GetNs().Do(func(_ ns.NetNS) error { - cmd := exec.Command(socat, args...) - cmd.Stdout = stream - - stderr := new(bytes.Buffer) - cmd.Stderr = stderr - - // If we use Stdin, command.Run() won't return until the goroutine that's copying - // from stream finishes. Unfortunately, if you have a client like telnet connected - // via port forwarding, as long as the user's telnet client is connected to the user's - // local listener that port forwarding sets up, the telnet session never exits. This - // means that even if socat has finished running, command.Run() won't ever return - // (because the client still has the connection and stream open). - // - // The work around is to use StdinPipe(), as Wait() (called by Run()) closes the pipe - // when the command (socat) exits. - in, err := cmd.StdinPipe() + var wg sync.WaitGroup + client, err := net.Dial("tcp4", fmt.Sprintf("localhost:%d", port)) if err != nil { - return errors.Wrap(err, "failed to create stdin pipe") + return errors.Wrap(err, "failed to dial") } + defer client.Close() + + wg.Add(1) go func() { - if _, err := io.Copy(in, stream); err != nil { - logrus.WithError(err).Errorf("Failed to copy port forward input for %q port %d", id, port) + if _, err := io.Copy(client, stream); err != nil { + logrus.WithError(err).Errorf("Failed to copy port forward input from %q port %d", id, port) } - in.Close() - logrus.Debugf("Finish copy port forward input for %q port %d: %v", id, port) + wg.Done() }() + wg.Add(1) + go func() { + if _, err := io.Copy(stream, client); err != nil { + logrus.WithError(err).Errorf("Failed to copy port forward output for %q port %d", id, port) + } + wg.Done() + }() + wg.Wait() + logrus.Infof("Finish copy port forward input for %q port %d: %v", id, port) - if err := cmd.Run(); err != nil { - return errors.Wrapf(err, "socat command returns error, stderr: %q", stderr.String()) - } return nil }) if err != nil {