hijack.go 1.8 KB

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