Only report closure errors for the last connection

Safari and iOS Chrome (WebKit) sometimes open multiple TCP
connections that end up being part of the same tcpPacketConn
object in TCPMuxDefault. After some time, the extra connection
is closed even though the main one is still operational. In this
case, the entire peer connection gets disconnected. Instead, we
probably only want to close the entire connection only once there
is no other open TCP connection (this PR).

To be honest, I am not sure why Safari and iOS Chrome do this.
However, there is probably no chance fixing it there.
This commit is contained in:
Ondrej Sery
2023-09-07 22:21:13 -07:00
committed by David Zhao
parent 9590b7987a
commit dbdc6bdf02
2 changed files with 8 additions and 3 deletions
+1
View File
@@ -46,6 +46,7 @@ Michael MacDonald <mike.macdonald@savantsystems.com>
Mikhail Bragin <misha@wiretrustee.com>
Miroslav Šedivý <sedivy.miro@gmail.com>
Nevio Vesic <nevio@subspace.com>
Ondrej Sery <sery.ondra@gmail.com>
Ori Bernstein <ori@eigenstate.org>
Raja Subramanian <raja.gobi@tutanota.com>
Rasmus Hanning <rasmus@hanning.se>
+7 -3
View File
@@ -161,8 +161,11 @@ func (t *tcpPacketConn) startReading(conn net.Conn) {
n, err := readStreamingPacket(conn, buf)
if err != nil {
t.params.Logger.Warnf("Failed to read streaming packet: %s", err)
t.handleRecv(streamingPacket{nil, conn.RemoteAddr(), err})
t.removeConn(conn)
last := t.removeConn(conn)
// Only propagate connection closure errors if no other open connection exists.
if last || !(errors.Is(err, io.EOF) || errors.Is(err, net.ErrClosed)) {
t.handleRecv(streamingPacket{nil, conn.RemoteAddr(), err})
}
return
}
@@ -245,13 +248,14 @@ func (t *tcpPacketConn) closeAndLogError(closer io.Closer) {
}
}
func (t *tcpPacketConn) removeConn(conn net.Conn) {
func (t *tcpPacketConn) removeConn(conn net.Conn) bool {
t.mu.Lock()
defer t.mu.Unlock()
t.closeAndLogError(conn)
delete(t.conns, conn.RemoteAddr().String())
return len(t.conns) == 0
}
func (t *tcpPacketConn) Close() error {