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