stream handles setting up the IO and then begins streaming stdin/stdout to/from the hijacked connection, blocking until it is either done reading output, the user inputs the detach key sequence when in TTY mode, or when the given context is cancelled.
(ctx context.Context)
| 59 | // output, the user inputs the detach key sequence when in TTY mode, or when |
| 60 | // the given context is cancelled. |
| 61 | func (h *hijackedIOStreamer) stream(ctx context.Context) error { |
| 62 | restoreInput, err := h.setupInput() |
| 63 | if err != nil { |
| 64 | return fmt.Errorf("unable to setup input stream: %s", err) |
| 65 | } |
| 66 | |
| 67 | defer restoreInput() |
| 68 | |
| 69 | outputDone := h.beginOutputStream(restoreInput) |
| 70 | inputDone, detached := h.beginInputStream(restoreInput) |
| 71 | |
| 72 | select { |
| 73 | case err := <-outputDone: |
| 74 | return err |
| 75 | case <-inputDone: |
| 76 | // Input stream has closed. |
| 77 | if h.outputStream != nil || h.errorStream != nil { |
| 78 | // Wait for output to complete streaming. |
| 79 | select { |
| 80 | case err := <-outputDone: |
| 81 | return err |
| 82 | case <-ctx.Done(): |
| 83 | return ctx.Err() |
| 84 | } |
| 85 | } |
| 86 | return nil |
| 87 | case err := <-detached: |
| 88 | // Got a detach key sequence. |
| 89 | return err |
| 90 | case <-ctx.Done(): |
| 91 | return ctx.Err() |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | func (h *hijackedIOStreamer) setupInput() (restore func(), _ error) { |
| 96 | if h.inputStream == nil || !h.tty { |
no test coverage detected