ktls_close.go 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. // Copyright 2009 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. //go:build linux && go1.25 && badlinkname
  5. package ktls
  6. import (
  7. "fmt"
  8. "net"
  9. "time"
  10. )
  11. func (c *Conn) Close() error {
  12. if !c.kernelTx {
  13. return c.Conn.Close()
  14. }
  15. // Interlock with Conn.Write above.
  16. var x int32
  17. for {
  18. x = c.rawConn.ActiveCall.Load()
  19. if x&1 != 0 {
  20. return net.ErrClosed
  21. }
  22. if c.rawConn.ActiveCall.CompareAndSwap(x, x|1) {
  23. break
  24. }
  25. }
  26. if x != 0 {
  27. // io.Writer and io.Closer should not be used concurrently.
  28. // If Close is called while a Write is currently in-flight,
  29. // interpret that as a sign that this Close is really just
  30. // being used to break the Write and/or clean up resources and
  31. // avoid sending the alertCloseNotify, which may block
  32. // waiting on handshakeMutex or the c.out mutex.
  33. return c.conn.Close()
  34. }
  35. var alertErr error
  36. if c.rawConn.IsHandshakeComplete.Load() {
  37. if err := c.closeNotify(); err != nil {
  38. alertErr = fmt.Errorf("tls: failed to send closeNotify alert (but connection was closed anyway): %w", err)
  39. }
  40. }
  41. if err := c.conn.Close(); err != nil {
  42. return err
  43. }
  44. return alertErr
  45. }
  46. func (c *Conn) closeNotify() error {
  47. c.rawConn.Out.Lock()
  48. defer c.rawConn.Out.Unlock()
  49. if !*c.rawConn.CloseNotifySent {
  50. // Set a Write Deadline to prevent possibly blocking forever.
  51. c.SetWriteDeadline(time.Now().Add(time.Second * 5))
  52. *c.rawConn.CloseNotifyErr = c.sendAlertLocked(alertCloseNotify)
  53. *c.rawConn.CloseNotifySent = true
  54. // Any subsequent writes will fail.
  55. c.SetWriteDeadline(time.Now())
  56. }
  57. return *c.rawConn.CloseNotifyErr
  58. }