mirror of
https://github.com/tailscale/tailscale.git
synced 2026-09-22 11:35:12 -04:00
types/nettype: add HalfCloser type
We have multiple situations where we have a `net.Conn` representing a TCP connection for a proxy and we need access to the underlying `CloseWrite()` and `CloseRead()` functions to properly pass through half-closes (see #16462, #20883). Add an interface we can cast to in order to get access to these functions. Updates #20883. Signed-off-by: Naman Sood <mail@nsood.in>
This commit is contained in:
1 parent
16d19a7e5e
commit
35848427ce
2 files changed
+16
-12
No files matched your search
@@ -63,3 +63,14 @@ type ConnPacketConn interface {
|
||||
net.Conn
|
||||
net.PacketConn
|
||||
}
|
||||
|
||||
// HalfCloser is an interface to abstract around various Conn types that
|
||||
// allow closing of the read and write streams independently of each other.
|
||||
// It is normally used as a typecast for a `net.Conn` to get access to these
|
||||
// functions. If you use it for this purpose, you should either be absolutely
|
||||
// certain that the `net.Conn` you have represents a half-closable connection
|
||||
// (eg. TCP or unix socket), or check for and handle a failure to cast.
|
||||
type HalfCloser interface {
|
||||
CloseRead() error
|
||||
CloseWrite() error
|
||||
}
|
||||
@@ -1762,13 +1762,6 @@ func (ns *Impl) acceptTCP(r *tcp.ForwarderRequest) {
|
||||
}
|
||||
}
|
||||
|
||||
// tcpCloser is an interface to abstract around various TCPConn types that
|
||||
// allow closing of the read and write streams independently of each other.
|
||||
type tcpCloser interface {
|
||||
CloseRead() error
|
||||
CloseWrite() error
|
||||
}
|
||||
|
||||
func (ns *Impl) forwardTCP(getClient func(...tcpip.SettableSocketOption) *gonet.TCPConn, clientRemoteIP netip.Addr, wq *waiter.Queue, dialAddr netip.AddrPort, isLocal bool) (handled bool) {
|
||||
dialAddrStr := dialAddr.String()
|
||||
if debugNetstack() {
|
||||
@@ -1841,7 +1834,7 @@ func (ns *Impl) forwardTCP(getClient func(...tcpip.SettableSocketOption) *gonet.
|
||||
// from stdDialer.DialContext (which has the requisite functions),
|
||||
// or nil from hangDialer in tests (in which case we would have
|
||||
// errored out by now), so this conversion should always succeed.
|
||||
backendTCPCloser, backendIsTCPCloser := backend.(tcpCloser)
|
||||
backendHalfCloser, backendIsHalfCloser := backend.(nettype.HalfCloser)
|
||||
connClosed := make(chan error, 2)
|
||||
go func() {
|
||||
_, err := io.Copy(backend, client)
|
||||
@@ -1850,8 +1843,8 @@ func (ns *Impl) forwardTCP(getClient func(...tcpip.SettableSocketOption) *gonet.
|
||||
}
|
||||
connClosed <- err
|
||||
err = nil
|
||||
if backendIsTCPCloser {
|
||||
err = backendTCPCloser.CloseWrite()
|
||||
if backendIsHalfCloser {
|
||||
err = backendHalfCloser.CloseWrite()
|
||||
}
|
||||
err = errors.Join(err, client.CloseRead())
|
||||
if err != nil {
|
||||
@@ -1865,8 +1858,8 @@ func (ns *Impl) forwardTCP(getClient func(...tcpip.SettableSocketOption) *gonet.
|
||||
}
|
||||
connClosed <- err
|
||||
err = nil
|
||||
if backendIsTCPCloser {
|
||||
err = backendTCPCloser.CloseRead()
|
||||
if backendIsHalfCloser {
|
||||
err = backendHalfCloser.CloseRead()
|
||||
}
|
||||
err = errors.Join(err, client.CloseWrite())
|
||||
if err != nil {
|
||||
|
||||
Reference in new issue
Block a user