dialer.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. package quic
  2. import (
  3. "context"
  4. "sync"
  5. "time"
  6. "v2ray.com/core/transport/internet/tls"
  7. quic "github.com/lucas-clemente/quic-go"
  8. "v2ray.com/core/common"
  9. "v2ray.com/core/common/net"
  10. "v2ray.com/core/transport/internet"
  11. )
  12. type clientSessions struct {
  13. access sync.Mutex
  14. sessions map[net.Destination]quic.Session
  15. }
  16. func (s *clientSessions) getSession(destAddr net.Addr, config *Config, tlsConfig *tls.Config, sockopt *internet.SocketConfig) (quic.Session, error) {
  17. s.access.Lock()
  18. defer s.access.Unlock()
  19. if s.sessions == nil {
  20. s.sessions = make(map[net.Destination]quic.Session)
  21. }
  22. dest := net.DestinationFromAddr(destAddr)
  23. if session, found := s.sessions[dest]; found {
  24. select {
  25. case <-session.Context().Done():
  26. // Session has been closed. Creating a new one.
  27. default:
  28. return session, nil
  29. }
  30. }
  31. rawConn, err := internet.ListenSystemPacket(context.Background(), &net.UDPAddr{
  32. IP: []byte{0, 0, 0, 0},
  33. Port: 0,
  34. }, sockopt)
  35. if err != nil {
  36. return nil, err
  37. }
  38. quicConfig := &quic.Config{
  39. Versions: []quic.VersionNumber{quic.VersionMilestone0_10_0},
  40. ConnectionIDLength: 12,
  41. KeepAlive: true,
  42. HandshakeTimeout: time.Second * 4,
  43. IdleTimeout: time.Second * 300,
  44. MaxReceiveStreamFlowControlWindow: 128 * 1024,
  45. MaxReceiveConnectionFlowControlWindow: 512 * 1024,
  46. MaxIncomingUniStreams: -1,
  47. }
  48. conn, err := wrapSysConn(rawConn, config)
  49. if err != nil {
  50. rawConn.Close()
  51. return nil, err
  52. }
  53. session, err := quic.DialContext(context.Background(), conn, destAddr, "", tlsConfig.GetTLSConfig(tls.WithDestination(dest)), quicConfig)
  54. if err != nil {
  55. rawConn.Close()
  56. return nil, err
  57. }
  58. s.sessions[dest] = session
  59. return session, nil
  60. }
  61. var client clientSessions
  62. func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (internet.Connection, error) {
  63. tlsConfig := tls.ConfigFromStreamSettings(streamSettings)
  64. if tlsConfig == nil {
  65. tlsConfig = &tls.Config{
  66. ServerName: internalDomain,
  67. AllowInsecure: true,
  68. }
  69. }
  70. destAddr, err := net.ResolveUDPAddr("udp", dest.NetAddr())
  71. if err != nil {
  72. return nil, err
  73. }
  74. config := streamSettings.ProtocolSettings.(*Config)
  75. session, err := client.getSession(destAddr, config, tlsConfig, streamSettings.SocketSettings)
  76. if err != nil {
  77. return nil, err
  78. }
  79. conn, err := session.OpenStreamSync()
  80. if err != nil {
  81. return nil, err
  82. }
  83. return &interConn{
  84. stream: conn,
  85. local: session.LocalAddr(),
  86. remote: destAddr,
  87. }, nil
  88. }
  89. func init() {
  90. common.Must(internet.RegisterTransportDialer(protocolName, Dial))
  91. }