67
common/ktls/ktls_close.go
Normal file
67
common/ktls/ktls_close.go
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux && go1.25 && !without_badtls
|
||||
|
||||
package ktls
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (c *Conn) Close() error {
|
||||
if !c.kernelTx {
|
||||
return c.Conn.Close()
|
||||
}
|
||||
|
||||
// Interlock with Conn.Write above.
|
||||
var x int32
|
||||
for {
|
||||
x = c.rawConn.ActiveCall.Load()
|
||||
if x&1 != 0 {
|
||||
return net.ErrClosed
|
||||
}
|
||||
if c.rawConn.ActiveCall.CompareAndSwap(x, x|1) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if x != 0 {
|
||||
// io.Writer and io.Closer should not be used concurrently.
|
||||
// If Close is called while a Write is currently in-flight,
|
||||
// interpret that as a sign that this Close is really just
|
||||
// being used to break the Write and/or clean up resources and
|
||||
// avoid sending the alertCloseNotify, which may block
|
||||
// waiting on handshakeMutex or the c.out mutex.
|
||||
return c.conn.Close()
|
||||
}
|
||||
|
||||
var alertErr error
|
||||
if c.rawConn.IsHandshakeComplete.Load() {
|
||||
if err := c.closeNotify(); err != nil {
|
||||
alertErr = fmt.Errorf("tls: failed to send closeNotify alert (but connection was closed anyway): %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := c.conn.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
return alertErr
|
||||
}
|
||||
|
||||
func (c *Conn) closeNotify() error {
|
||||
c.rawConn.Out.Lock()
|
||||
defer c.rawConn.Out.Unlock()
|
||||
|
||||
if !*c.rawConn.CloseNotifySent {
|
||||
// Set a Write Deadline to prevent possibly blocking forever.
|
||||
c.SetWriteDeadline(time.Now().Add(time.Second * 5))
|
||||
*c.rawConn.CloseNotifyErr = c.sendAlertLocked(alertCloseNotify)
|
||||
*c.rawConn.CloseNotifySent = true
|
||||
// Any subsequent writes will fail.
|
||||
c.SetWriteDeadline(time.Now())
|
||||
}
|
||||
return *c.rawConn.CloseNotifyErr
|
||||
}
|
||||
Reference in New Issue
Block a user