dialer.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. package quic
  2. import (
  3. "context"
  4. "sync"
  5. "v2ray.com/core/transport/internet/tls"
  6. quic "github.com/lucas-clemente/quic-go"
  7. "v2ray.com/core/common"
  8. "v2ray.com/core/common/net"
  9. "v2ray.com/core/transport/internet"
  10. )
  11. type clientSessions struct {
  12. access sync.Mutex
  13. sessions map[net.Destination]quic.Session
  14. }
  15. func (s *clientSessions) getSession(destAddr net.Addr, tlsConfig *tls.Config, sockopt *internet.SocketConfig) (quic.Session, error) {
  16. s.access.Lock()
  17. defer s.access.Unlock()
  18. if s.sessions == nil {
  19. s.sessions = make(map[net.Destination]quic.Session)
  20. }
  21. dest := net.DestinationFromAddr(destAddr)
  22. if session, found := s.sessions[dest]; found {
  23. return session, nil
  24. }
  25. conn, err := internet.ListenSystemPacket(context.Background(), &net.UDPAddr{
  26. IP: []byte{0, 0, 0, 0},
  27. Port: 0,
  28. }, sockopt)
  29. if err != nil {
  30. return nil, err
  31. }
  32. config := &quic.Config{
  33. Versions: []quic.VersionNumber{quic.VersionMilestone0_10_0},
  34. ConnectionIDLength: 12,
  35. KeepAlive: true,
  36. }
  37. session, err := quic.DialContext(context.Background(), conn, destAddr, "", tlsConfig.GetTLSConfig(tls.WithDestination(dest)), config)
  38. if err != nil {
  39. return nil, err
  40. }
  41. s.sessions[dest] = session
  42. return session, nil
  43. }
  44. var client clientSessions
  45. func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (internet.Connection, error) {
  46. tlsConfig := tls.ConfigFromStreamSettings(streamSettings)
  47. if tlsConfig == nil {
  48. return nil, newError("TLS not enabled for QUIC")
  49. }
  50. destAddr, err := net.ResolveUDPAddr("udp", dest.NetAddr())
  51. if err != nil {
  52. return nil, err
  53. }
  54. session, err := client.getSession(destAddr, tlsConfig, streamSettings.SocketSettings)
  55. if err != nil {
  56. return nil, err
  57. }
  58. conn, err := session.OpenStreamSync()
  59. if err != nil {
  60. return nil, err
  61. }
  62. return &interConn{
  63. stream: conn,
  64. local: session.LocalAddr(),
  65. remote: destAddr,
  66. }, nil
  67. }
  68. func init() {
  69. common.Must(internet.RegisterTransportDialer(protocolName, Dial))
  70. }