github.com/endocode/docker@v1.4.2-0.20160113120958-46eb4700391e/api/client/hijack.go (about)

     1  package client
     2  
     3  import (
     4  	"io"
     5  	"os"
     6  
     7  	"github.com/Sirupsen/logrus"
     8  	"github.com/docker/docker/pkg/stdcopy"
     9  	"github.com/docker/docker/pkg/term"
    10  	"github.com/docker/engine-api/types"
    11  )
    12  
    13  func (cli *DockerCli) holdHijackedConnection(setRawTerminal bool, inputStream io.ReadCloser, outputStream, errorStream io.Writer, resp types.HijackedResponse) error {
    14  	var (
    15  		err      error
    16  		oldState *term.State
    17  	)
    18  	if inputStream != nil && setRawTerminal && cli.isTerminalIn && os.Getenv("NORAW") == "" {
    19  		oldState, err = term.SetRawTerminal(cli.inFd)
    20  		if err != nil {
    21  			return err
    22  		}
    23  		defer term.RestoreTerminal(cli.inFd, oldState)
    24  	}
    25  
    26  	receiveStdout := make(chan error, 1)
    27  	if outputStream != nil || errorStream != nil {
    28  		go func() {
    29  			defer func() {
    30  				if inputStream != nil {
    31  					if setRawTerminal && cli.isTerminalIn {
    32  						term.RestoreTerminal(cli.inFd, oldState)
    33  					}
    34  					inputStream.Close()
    35  				}
    36  			}()
    37  
    38  			// When TTY is ON, use regular copy
    39  			if setRawTerminal && outputStream != nil {
    40  				_, err = io.Copy(outputStream, resp.Reader)
    41  			} else {
    42  				_, err = stdcopy.StdCopy(outputStream, errorStream, resp.Reader)
    43  			}
    44  			logrus.Debugf("[hijack] End of stdout")
    45  			receiveStdout <- err
    46  		}()
    47  	}
    48  
    49  	stdinDone := make(chan struct{})
    50  	go func() {
    51  		if inputStream != nil {
    52  			io.Copy(resp.Conn, inputStream)
    53  			logrus.Debugf("[hijack] End of stdin")
    54  		}
    55  
    56  		if err := resp.CloseWrite(); err != nil {
    57  			logrus.Debugf("Couldn't send EOF: %s", err)
    58  		}
    59  		close(stdinDone)
    60  	}()
    61  
    62  	select {
    63  	case err := <-receiveStdout:
    64  		if err != nil {
    65  			logrus.Debugf("Error receiveStdout: %s", err)
    66  			return err
    67  		}
    68  	case <-stdinDone:
    69  		if outputStream != nil || errorStream != nil {
    70  			if err := <-receiveStdout; err != nil {
    71  				logrus.Debugf("Error receiveStdout: %s", err)
    72  				return err
    73  			}
    74  		}
    75  	}
    76  
    77  	return nil
    78  }