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