@@ -17,11 +17,10 @@ limitations under the License.
1717package server
1818
1919import (
20- "bytes"
2120 "fmt"
2221 "io"
23- "os/exec "
24- "strings "
22+ "net "
23+ "sync "
2524
2625 "github.com/containernetworking/plugins/pkg/ns"
2726 "github.com/pkg/errors"
@@ -58,46 +57,31 @@ func (c *criService) portForward(id string, port int32, stream io.ReadWriteClose
5857 return errors .Errorf ("failed to find network namespace fo sandbox %q in store" , id )
5958 }
6059
61- socat , err := exec .LookPath ("socat" )
62- if err != nil {
63- return errors .Wrap (err , "failed to find socat" )
64- }
65-
66- // Check following links for meaning of the options:
67- // * socat: https://linux.die.net/man/1/socat
68- args := []string {"-" , fmt .Sprintf ("TCP4:localhost:%d" , port )}
69- logrus .Infof ("Executing port forwarding command: %s %s" , socat , strings .Join (args , " " ))
7060 err = s .NetNS .GetNs ().Do (func (_ ns.NetNS ) error {
71- cmd := exec .Command (socat , args ... )
72- cmd .Stdout = stream
73-
74- stderr := new (bytes.Buffer )
75- cmd .Stderr = stderr
76-
77- // If we use Stdin, command.Run() won't return until the goroutine that's copying
78- // from stream finishes. Unfortunately, if you have a client like telnet connected
79- // via port forwarding, as long as the user's telnet client is connected to the user's
80- // local listener that port forwarding sets up, the telnet session never exits. This
81- // means that even if socat has finished running, command.Run() won't ever return
82- // (because the client still has the connection and stream open).
83- //
84- // The work around is to use StdinPipe(), as Wait() (called by Run()) closes the pipe
85- // when the command (socat) exits.
86- in , err := cmd .StdinPipe ()
61+ var wg sync.WaitGroup
62+ client , err := net .Dial ("tcp4" , fmt .Sprintf ("localhost:%d" , port ))
8763 if err != nil {
88- return errors .Wrap (err , "failed to create stdin pipe " )
64+ return errors .Wrap (err , "failed to dial " )
8965 }
66+ defer client .Close ()
67+
68+ wg .Add (1 )
9069 go func () {
91- if _ , err := io .Copy (in , stream ); err != nil {
92- logrus .WithError (err ).Errorf ("Failed to copy port forward input for %q port %d" , id , port )
70+ if _ , err := io .Copy (client , stream ); err != nil {
71+ logrus .WithError (err ).Errorf ("Failed to copy port forward input from %q port %d" , id , port )
9372 }
94- in .Close ()
95- logrus .Debugf ("Finish copy port forward input for %q port %d: %v" , id , port )
73+ wg .Done ()
9674 }()
75+ wg .Add (1 )
76+ go func () {
77+ if _ , err := io .Copy (stream , client ); err != nil {
78+ logrus .WithError (err ).Errorf ("Failed to copy port forward output for %q port %d" , id , port )
79+ }
80+ wg .Done ()
81+ }()
82+ wg .Wait ()
83+ logrus .Infof ("Finish copy port forward input for %q port %d: %v" , id , port )
9784
98- if err := cmd .Run (); err != nil {
99- return errors .Wrapf (err , "socat command returns error, stderr: %q" , stderr .String ())
100- }
10185 return nil
10286 })
10387 if err != nil {
0 commit comments