github.com/v2fly/v2ray-core/v4@v4.45.2/transport/internet/quic/hub.go (about) 1 //go:build !confonly 2 // +build !confonly 3 4 package quic 5 6 import ( 7 "context" 8 "time" 9 10 "github.com/lucas-clemente/quic-go" 11 12 "github.com/v2fly/v2ray-core/v4/common" 13 "github.com/v2fly/v2ray-core/v4/common/net" 14 "github.com/v2fly/v2ray-core/v4/common/protocol/tls/cert" 15 "github.com/v2fly/v2ray-core/v4/common/signal/done" 16 "github.com/v2fly/v2ray-core/v4/transport/internet" 17 "github.com/v2fly/v2ray-core/v4/transport/internet/tls" 18 ) 19 20 // Listener is an internet.Listener that listens for TCP connections. 21 type Listener struct { 22 rawConn *sysConn 23 listener quic.Listener 24 done *done.Instance 25 addConn internet.ConnHandler 26 } 27 28 func (l *Listener) acceptStreams(conn quic.Connection) { 29 for { 30 stream, err := conn.AcceptStream(context.Background()) 31 if err != nil { 32 newError("failed to accept stream").Base(err).WriteToLog() 33 select { 34 case <-conn.Context().Done(): 35 return 36 case <-l.done.Wait(): 37 if err := conn.CloseWithError(0, ""); err != nil { 38 newError("failed to close connection").Base(err).WriteToLog() 39 } 40 return 41 default: 42 time.Sleep(time.Second) 43 continue 44 } 45 } 46 47 conn := &interConn{ 48 stream: stream, 49 local: conn.LocalAddr(), 50 remote: conn.RemoteAddr(), 51 } 52 53 l.addConn(conn) 54 } 55 } 56 57 func (l *Listener) keepAccepting() { 58 for { 59 conn, err := l.listener.Accept(context.Background()) 60 if err != nil { 61 newError("failed to accept QUIC connections").Base(err).WriteToLog() 62 if l.done.Done() { 63 break 64 } 65 time.Sleep(time.Second) 66 continue 67 } 68 go l.acceptStreams(conn) 69 } 70 } 71 72 // Addr implements internet.Listener.Addr. 73 func (l *Listener) Addr() net.Addr { 74 return l.listener.Addr() 75 } 76 77 // Close implements internet.Listener.Close. 78 func (l *Listener) Close() error { 79 l.done.Close() 80 l.listener.Close() 81 l.rawConn.Close() 82 return nil 83 } 84 85 // Listen creates a new Listener based on configurations. 86 func Listen(ctx context.Context, address net.Address, port net.Port, streamSettings *internet.MemoryStreamConfig, handler internet.ConnHandler) (internet.Listener, error) { 87 if address.Family().IsDomain() { 88 return nil, newError("domain address is not allows for listening quic") 89 } 90 91 tlsConfig := tls.ConfigFromStreamSettings(streamSettings) 92 if tlsConfig == nil { 93 tlsConfig = &tls.Config{ 94 Certificate: []*tls.Certificate{tls.ParseCertificate(cert.MustGenerate(nil, cert.DNSNames(internalDomain), cert.CommonName(internalDomain)))}, 95 } 96 } 97 98 config := streamSettings.ProtocolSettings.(*Config) 99 rawConn, err := internet.ListenSystemPacket(context.Background(), &net.UDPAddr{ 100 IP: address.IP(), 101 Port: int(port), 102 }, streamSettings.SocketSettings) 103 if err != nil { 104 return nil, err 105 } 106 107 quicConfig := &quic.Config{ 108 ConnectionIDLength: 12, 109 HandshakeIdleTimeout: time.Second * 8, 110 MaxIdleTimeout: time.Second * 45, 111 MaxIncomingStreams: 32, 112 MaxIncomingUniStreams: -1, 113 KeepAlive: true, 114 } 115 116 conn, err := wrapSysConn(rawConn, config) 117 if err != nil { 118 conn.Close() 119 return nil, err 120 } 121 122 qListener, err := quic.Listen(conn, tlsConfig.GetTLSConfig(), quicConfig) 123 if err != nil { 124 conn.Close() 125 return nil, err 126 } 127 128 listener := &Listener{ 129 done: done.New(), 130 rawConn: conn, 131 listener: qListener, 132 addConn: handler, 133 } 134 135 go listener.keepAccepting() 136 137 return listener, nil 138 } 139 140 func init() { 141 common.Must(internet.RegisterTransportListener(protocolName, Listen)) 142 }