Skip to content

Commit c3613fc

Browse files
committed
fix: echo read error after close received
1 parent 2ea151a commit c3613fc

File tree

4 files changed

+27
-2
lines changed

4 files changed

+27
-2
lines changed

Diff for: close.go

+4
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,10 @@ func (c *Conn) waitCloseHandshake() error {
206206
}
207207
defer c.readMu.unlock()
208208

209+
if c.readCloseErr != nil {
210+
return c.readCloseErr
211+
}
212+
209213
for i := int64(0); i < c.msgReader.payloadLength; i++ {
210214
_, err := c.br.ReadByte()
211215
if err != nil {

Diff for: conn.go

+2
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ type Conn struct {
6161
readHeaderBuf [8]byte
6262
readControlBuf [maxControlPayload]byte
6363
msgReader *msgReader
64+
readCloseErr error
6465

6566
// Write state.
6667
msgWriter *msgWriter
@@ -70,6 +71,7 @@ type Conn struct {
7071
writeHeader header
7172
closeSent bool
7273

74+
// CloseRead state.
7375
closeReadMu sync.Mutex
7476
closeReadCtx context.Context
7577
closeReadDone chan struct{}

Diff for: read.go

+18-1
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,15 @@ func (c *Conn) readRSV1Illegal(h header) bool {
181181
}
182182

183183
func (c *Conn) readLoop(ctx context.Context) (header, error) {
184+
if c.readCloseErr != nil {
185+
select {
186+
case <-c.closed:
187+
return header{}, net.ErrClosed
188+
default:
189+
}
190+
return header{}, c.readCloseErr
191+
}
192+
184193
for {
185194
h, err := c.readFrameHeader(ctx)
186195
if err != nil {
@@ -324,8 +333,16 @@ func (c *Conn) handleControl(ctx context.Context, h header) (err error) {
324333
return err
325334
}
326335

336+
if c.readCloseErr == nil {
337+
c.readCloseErr = ce
338+
}
339+
327340
err = fmt.Errorf("received close frame: %w", ce)
328-
c.writeClose(ce.Code, ce.Reason)
341+
if err2 := c.writeClose(ce.Code, ce.Reason); errors.Is(err2, errCloseSent) {
342+
// The close handshake has already been initiated, connection
343+
// close should be handled elsewhere.
344+
return err
345+
}
329346
c.readMu.unlock()
330347
c.close()
331348
return err

Diff for: write.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,8 @@ func (c *Conn) writeControl(ctx context.Context, opcode opcode, p []byte) error
241241
return nil
242242
}
243243

244+
var errCloseSent = errors.New("close sent")
245+
244246
// writeFrame handles all writes to the connection.
245247
func (c *Conn) writeFrame(ctx context.Context, fin bool, flate bool, opcode opcode, p []byte) (_ int, err error) {
246248
err = c.writeFrameMu.lock(ctx)
@@ -255,7 +257,7 @@ func (c *Conn) writeFrame(ctx context.Context, fin bool, flate bool, opcode opco
255257
return 0, net.ErrClosed
256258
default:
257259
}
258-
return 0, errors.New("close sent")
260+
return 0, errCloseSent
259261
}
260262

261263
select {

0 commit comments

Comments
 (0)