From dbdc6bdf023572ea6366535ef44338fcca6b38e9 Mon Sep 17 00:00:00 2001 From: Ondrej Sery Date: Tue, 5 Sep 2023 13:55:14 +0200 Subject: [PATCH] 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. --- AUTHORS.txt | 1 + tcp_packet_conn.go | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/AUTHORS.txt b/AUTHORS.txt index 30b95db..751b533 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -46,6 +46,7 @@ Michael MacDonald Mikhail Bragin Miroslav Šedivý Nevio Vesic +Ondrej Sery Ori Bernstein Raja Subramanian Rasmus Hanning diff --git a/tcp_packet_conn.go b/tcp_packet_conn.go index 0b6d9d8..934ebd5 100644 --- a/tcp_packet_conn.go +++ b/tcp_packet_conn.go @@ -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 {