zrepl/transport/tls/tls_wire_adaptor.go
Christian Schwarz 796c5ad42d rpc rewrite: control RPCs using gRPC + separate RPC for data transfer
transport/ssh: update go-netssh to new version
    => supports CloseWrite and Deadlines
    => build: require Go 1.11 (netssh requires it)
2019-03-13 13:53:48 +01:00

48 lines
1.6 KiB
Go

package tls
import (
"crypto/tls"
"fmt"
"net"
"os"
)
// adapts a tls.Conn and its underlying net.TCPConn into a valid transport.Wire
type transportWireAdaptor struct {
*tls.Conn
tcpConn *net.TCPConn
}
func newWireAdaptor(tlsConn *tls.Conn, tcpConn *net.TCPConn) transportWireAdaptor {
return transportWireAdaptor{tlsConn, tcpConn}
}
// CloseWrite implements transport.Wire.CloseWrite which is different from *tls.Conn.CloseWrite:
// the former requires that the other side observes io.EOF, but *tls.Conn.CloseWrite does not
// close the underlying connection so no io.EOF would be observed.
func (w transportWireAdaptor) CloseWrite() error {
if err := w.Conn.CloseWrite(); err != nil {
// TODO log error
fmt.Fprintf(os.Stderr, "transport/tls.CloseWrite() error: %s\n", err)
}
return w.tcpConn.CloseWrite()
}
// Close implements transport.Wire.Close which is different from a *tls.Conn.Close:
// At the time of writing (Go 1.11), closing tls.Conn closes the TCP connection immediately,
// which results in io.ErrUnexpectedEOF on the other side.
// We assume that w.Conn has a deadline set for the close, so the CloseWrite will time out if it blocks,
// falling through to the actual Close()
func (w transportWireAdaptor) Close() error {
// var buf [1<<15]byte
// w.Conn.Write(buf[:])
// CloseWrite will send a TLS alert record down the line which
// in the Go implementation acts like a flush...?
// if err := w.Conn.CloseWrite(); err != nil {
// // TODO log error
// fmt.Fprintf(os.Stderr, "transport/tls.Close() close write error: %s\n", err)
// }
// time.Sleep(1 * time.Second)
return w.Conn.Close()
}