force_close.go 1.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. package v2rayhttp
  2. import (
  3. "net/http"
  4. "reflect"
  5. "sync"
  6. "unsafe"
  7. E "github.com/sagernet/sing/common/exceptions"
  8. "golang.org/x/net/http2"
  9. )
  10. type clientConnPool struct {
  11. t *http2.Transport
  12. mu sync.Mutex
  13. conns map[string][]*http2.ClientConn // key is host:port
  14. }
  15. type efaceWords struct {
  16. typ unsafe.Pointer
  17. data unsafe.Pointer
  18. }
  19. func ResetTransport(rawTransport http.RoundTripper) http.RoundTripper {
  20. switch transport := rawTransport.(type) {
  21. case *http.Transport:
  22. transport.CloseIdleConnections()
  23. return transport.Clone()
  24. case *http2.Transport:
  25. connPool := transportConnPool(transport)
  26. p := (*clientConnPool)((*efaceWords)(unsafe.Pointer(&connPool)).data)
  27. p.mu.Lock()
  28. defer p.mu.Unlock()
  29. for _, vv := range p.conns {
  30. for _, cc := range vv {
  31. cc.Close()
  32. }
  33. }
  34. return transport
  35. default:
  36. panic(E.New("unknown transport type: ", reflect.TypeOf(transport)))
  37. }
  38. }
  39. //go:linkname transportConnPool golang.org/x/net/http2.(*Transport).connPool
  40. func transportConnPool(t *http2.Transport) http2.ClientConnPool