Files
teleport/lib/client/tncon/buffer.go
T
Noah Stride 02b4f8575f Configure linter to catch British 🇬🇧 spellings 🇺🇸 🦅 📖 (#14363)
* configure golangci-lint misspell to check for anglicized spellings

* Americanize spellings

* fix aws constant value with british spelling 🇬🇧

* update api types with americanized spellings

* use american spellings .cloudbuild/scripts
2022-07-14 10:51:23 +00:00

70 lines
1.5 KiB
Go

// Copyright (c) 2020 Leonid Titov. All rights reserved.
// MIT license.
// Version 2020-12-23
package tncon
import (
"io"
)
// bufferedChannelPipe is a synchronous buffered pipe implemented with a channel. This pipe
// is much more efficient than the standard io.Pipe, and can keep up with real-time
// shell output, which is needed for the lib/client/tncon implementation.
//
// Derived from https://github.com/latitov/milkthisbuffer/blob/main/milkthisbuffer.go
type bufferedChannelPipe struct {
ch chan byte
closed chan struct{}
}
func newBufferedChannelPipe(len int) *bufferedChannelPipe {
return &bufferedChannelPipe{
ch: make(chan byte, len),
closed: make(chan struct{}),
}
}
// Write will write all of p to the buffer unless the buffer is closed
func (b *bufferedChannelPipe) Write(p []byte) (n int, err error) {
for n = 0; n < len(p); n++ {
select {
// blocking behavior
case b.ch <- p[n]:
case <-b.closed:
return n, io.EOF
}
}
return n, nil
}
// Read will always read at least one byte from the buffer unless the buffer is closed
func (b *bufferedChannelPipe) Read(p []byte) (n int, err error) {
if len(p) == 0 {
return 0, nil
}
// blocking behavior
select {
case p[0] = <-b.ch:
case <-b.closed:
return 0, io.EOF
}
for n = 1; n < len(p); n++ {
select {
case p[n] = <-b.ch:
case <-b.closed:
return n, io.EOF
default:
return n, nil
}
}
return n, nil
}
func (b *bufferedChannelPipe) Close() error {
close(b.closed)
return nil
}