diff --git a/app/dns/nameserver_quic.go b/app/dns/nameserver_quic.go index 52040058163..7665405dae5 100644 --- a/app/dns/nameserver_quic.go +++ b/app/dns/nameserver_quic.go @@ -37,7 +37,7 @@ type QUICNameServer struct { reqID uint32 name string destination net.Destination - session quic.Session + connection quic.Connection } // NewQUICNameServer creates DNS-over-QUIC client object for local resolving @@ -191,7 +191,7 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP conn, err := s.openStream(dnsCtx) if err != nil { - newError("failed to open quic session").Base(err).AtError().WriteToLog() + newError("failed to open quic connection").Base(err).AtError().WriteToLog() return } @@ -315,7 +315,7 @@ func (s *QUICNameServer) QueryIP(ctx context.Context, domain string, clientIP ne } } -func isActive(s quic.Session) bool { +func isActive(s quic.Connection) bool { select { case <-s.Context().Done(): return false @@ -324,17 +324,17 @@ func isActive(s quic.Session) bool { } } -func (s *QUICNameServer) getSession(ctx context.Context) (quic.Session, error) { - var session quic.Session +func (s *QUICNameServer) getConnection(ctx context.Context) (quic.Connection, error) { + var conn quic.Connection s.RLock() - session = s.session - if session != nil && isActive(session) { + conn = s.connection + if conn != nil && isActive(conn) { s.RUnlock() - return session, nil + return conn, nil } - if session != nil { - // we're recreating the session, let's create a new one - _ = session.CloseWithError(0, "") + if conn != nil { + // we're recreating the connection, let's create a new one + _ = conn.CloseWithError(0, "") } s.RUnlock() @@ -342,42 +342,42 @@ func (s *QUICNameServer) getSession(ctx context.Context) (quic.Session, error) { defer s.Unlock() var err error - session, err = s.openSession(ctx) + conn, err = s.openConnection(ctx) if err != nil { // This does not look too nice, but QUIC (or maybe quic-go) // doesn't seem stable enough. // Maybe retransmissions aren't fully implemented in quic-go? // Anyways, the simple solution is to make a second try when - // it fails to open the QUIC session. - session, err = s.openSession(ctx) + // it fails to open the QUIC connection. + conn, err = s.openConnection(ctx) if err != nil { return nil, err } } - s.session = session - return session, nil + s.connection = conn + return conn, nil } -func (s *QUICNameServer) openSession(ctx context.Context) (quic.Session, error) { +func (s *QUICNameServer) openConnection(ctx context.Context) (quic.Connection, error) { tlsConfig := tls.Config{} quicConfig := &quic.Config{ HandshakeIdleTimeout: handshakeIdleTimeout, } - session, err := quic.DialAddrContext(ctx, s.destination.NetAddr(), tlsConfig.GetTLSConfig(tls.WithNextProto("http/1.1", http2.NextProtoTLS, NextProtoDQ)), quicConfig) + conn, err := quic.DialAddrContext(ctx, s.destination.NetAddr(), tlsConfig.GetTLSConfig(tls.WithNextProto("http/1.1", http2.NextProtoTLS, NextProtoDQ)), quicConfig) if err != nil { return nil, err } - return session, nil + return conn, nil } func (s *QUICNameServer) openStream(ctx context.Context) (quic.Stream, error) { - session, err := s.getSession(ctx) + conn, err := s.getConnection(ctx) if err != nil { return nil, err } // open a new stream - return session.OpenStreamSync(ctx) + return conn.OpenStreamSync(ctx) } diff --git a/go.mod b/go.mod index 78f1d8185d7..7c8f62ad688 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/google/go-cmp v0.5.7 github.com/gorilla/websocket v1.5.0 github.com/jhump/protoreflect v1.12.0 - github.com/lucas-clemente/quic-go v0.26.0 + github.com/lucas-clemente/quic-go v0.27.0 github.com/marten-seemann/qtls-go1-16 v0.1.5 github.com/marten-seemann/qtls-go1-17 v0.1.1 github.com/marten-seemann/qtls-go1-18 v0.1.1 diff --git a/go.sum b/go.sum index 893e291a063..8a352a6df04 100644 --- a/go.sum +++ b/go.sum @@ -216,8 +216,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= -github.com/lucas-clemente/quic-go v0.26.0 h1:ALBQXr9UJ8A1LyzvceX4jd9QFsHvlI0RR6BkV16o00A= -github.com/lucas-clemente/quic-go v0.26.0/go.mod h1:AzgQoPda7N+3IqMMMkywBKggIFo2KT6pfnlrQ2QieeI= +github.com/lucas-clemente/quic-go v0.27.0 h1:v6WY87q9zD4dKASbG8hy/LpzAVNzEQzw8sEIeloJsc4= +github.com/lucas-clemente/quic-go v0.27.0/go.mod h1:AzgQoPda7N+3IqMMMkywBKggIFo2KT6pfnlrQ2QieeI= github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc= github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40/go.mod h1:vy1vK6wD6j7xX6O6hXe621WabdtNkou2h7uRtTfRMyg= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= diff --git a/transport/internet/quic/dialer.go b/transport/internet/quic/dialer.go index c2d90d67423..bc5e0ac3fb8 100644 --- a/transport/internet/quic/dialer.go +++ b/transport/internet/quic/dialer.go @@ -14,39 +14,39 @@ import ( "github.com/v2fly/v2ray-core/v5/transport/internet/tls" ) -type sessionContext struct { +type connectionContext struct { rawConn *sysConn - session quic.Session + conn quic.Connection } -var errSessionClosed = newError("session closed") +var errConnectionClosed = newError("connection closed") -func (c *sessionContext) openStream(destAddr net.Addr) (*interConn, error) { - if !isActive(c.session) { - return nil, errSessionClosed +func (c *connectionContext) openStream(destAddr net.Addr) (*interConn, error) { + if !isActive(c.conn) { + return nil, errConnectionClosed } - stream, err := c.session.OpenStream() + stream, err := c.conn.OpenStream() if err != nil { return nil, err } conn := &interConn{ stream: stream, - local: c.session.LocalAddr(), + local: c.conn.LocalAddr(), remote: destAddr, } return conn, nil } -type clientSessions struct { - access sync.Mutex - sessions map[net.Destination][]*sessionContext - cleanup *task.Periodic +type clientConnections struct { + access sync.Mutex + conns map[net.Destination][]*connectionContext + cleanup *task.Periodic } -func isActive(s quic.Session) bool { +func isActive(s quic.Connection) bool { select { case <-s.Context().Done(): return false @@ -55,31 +55,31 @@ func isActive(s quic.Session) bool { } } -func removeInactiveSessions(sessions []*sessionContext) []*sessionContext { - activeSessions := make([]*sessionContext, 0, len(sessions)) - for _, s := range sessions { - if isActive(s.session) { - activeSessions = append(activeSessions, s) +func removeInactiveConnections(conns []*connectionContext) []*connectionContext { + activeConnections := make([]*connectionContext, 0, len(conns)) + for _, s := range conns { + if isActive(s.conn) { + activeConnections = append(activeConnections, s) continue } - if err := s.session.CloseWithError(0, ""); err != nil { - newError("failed to close session").Base(err).WriteToLog() + if err := s.conn.CloseWithError(0, ""); err != nil { + newError("failed to close connection").Base(err).WriteToLog() } if err := s.rawConn.Close(); err != nil { newError("failed to close raw connection").Base(err).WriteToLog() } } - if len(activeSessions) < len(sessions) { - return activeSessions + if len(activeConnections) < len(conns) { + return activeConnections } - return sessions + return conns } -func openStream(sessions []*sessionContext, destAddr net.Addr) *interConn { - for _, s := range sessions { - if !isActive(s.session) { +func openStream(conns []*connectionContext, destAddr net.Addr) *interConn { + for _, s := range conns { + if !isActive(s.conn) { continue } @@ -94,50 +94,50 @@ func openStream(sessions []*sessionContext, destAddr net.Addr) *interConn { return nil } -func (s *clientSessions) cleanSessions() error { +func (s *clientConnections) cleanConnections() error { s.access.Lock() defer s.access.Unlock() - if len(s.sessions) == 0 { + if len(s.conns) == 0 { return nil } - newSessionMap := make(map[net.Destination][]*sessionContext) + newConnMap := make(map[net.Destination][]*connectionContext) - for dest, sessions := range s.sessions { - sessions = removeInactiveSessions(sessions) - if len(sessions) > 0 { - newSessionMap[dest] = sessions + for dest, conns := range s.conns { + conns = removeInactiveConnections(conns) + if len(conns) > 0 { + newConnMap[dest] = conns } } - s.sessions = newSessionMap + s.conns = newConnMap return nil } -func (s *clientSessions) openConnection(destAddr net.Addr, config *Config, tlsConfig *tls.Config, sockopt *internet.SocketConfig) (internet.Connection, error) { +func (s *clientConnections) openConnection(destAddr net.Addr, config *Config, tlsConfig *tls.Config, sockopt *internet.SocketConfig) (internet.Connection, error) { s.access.Lock() defer s.access.Unlock() - if s.sessions == nil { - s.sessions = make(map[net.Destination][]*sessionContext) + if s.conns == nil { + s.conns = make(map[net.Destination][]*connectionContext) } dest := net.DestinationFromAddr(destAddr) - var sessions []*sessionContext - if s, found := s.sessions[dest]; found { - sessions = s + var conns []*connectionContext + if s, found := s.conns[dest]; found { + conns = s } if true { - conn := openStream(sessions, destAddr) + conn := openStream(conns, destAddr) if conn != nil { return conn, nil } } - sessions = removeInactiveSessions(sessions) + conns = removeInactiveConnections(conns) rawConn, err := internet.ListenSystemPacket(context.Background(), &net.UDPAddr{ IP: []byte{0, 0, 0, 0}, @@ -154,33 +154,33 @@ func (s *clientSessions) openConnection(destAddr net.Addr, config *Config, tlsCo KeepAlive: true, } - conn, err := wrapSysConn(rawConn.(*net.UDPConn), config) + sysConn, err := wrapSysConn(rawConn.(*net.UDPConn), config) if err != nil { rawConn.Close() return nil, err } - session, err := quic.DialContext(context.Background(), conn, destAddr, "", tlsConfig.GetTLSConfig(tls.WithDestination(dest)), quicConfig) + conn, err := quic.DialContext(context.Background(), sysConn, destAddr, "", tlsConfig.GetTLSConfig(tls.WithDestination(dest)), quicConfig) if err != nil { - conn.Close() + sysConn.Close() return nil, err } - context := &sessionContext{ - session: session, - rawConn: conn, + context := &connectionContext{ + conn: conn, + rawConn: sysConn, } - s.sessions[dest] = append(sessions, context) + s.conns[dest] = append(conns, context) return context.openStream(destAddr) } -var client clientSessions +var client clientConnections func init() { - client.sessions = make(map[net.Destination][]*sessionContext) + client.conns = make(map[net.Destination][]*connectionContext) client.cleanup = &task.Periodic{ Interval: time.Minute, - Execute: client.cleanSessions, + Execute: client.cleanConnections, } common.Must(client.cleanup.Start()) } diff --git a/transport/internet/quic/hub.go b/transport/internet/quic/hub.go index a771cdb2209..e310198653c 100644 --- a/transport/internet/quic/hub.go +++ b/transport/internet/quic/hub.go @@ -22,17 +22,17 @@ type Listener struct { addConn internet.ConnHandler } -func (l *Listener) acceptStreams(session quic.Session) { +func (l *Listener) acceptStreams(conn quic.Connection) { for { - stream, err := session.AcceptStream(context.Background()) + stream, err := conn.AcceptStream(context.Background()) if err != nil { newError("failed to accept stream").Base(err).WriteToLog() select { - case <-session.Context().Done(): + case <-conn.Context().Done(): return case <-l.done.Wait(): - if err := session.CloseWithError(0, ""); err != nil { - newError("failed to close session").Base(err).WriteToLog() + if err := conn.CloseWithError(0, ""); err != nil { + newError("failed to close connection").Base(err).WriteToLog() } return default: @@ -43,8 +43,8 @@ func (l *Listener) acceptStreams(session quic.Session) { conn := &interConn{ stream: stream, - local: session.LocalAddr(), - remote: session.RemoteAddr(), + local: conn.LocalAddr(), + remote: conn.RemoteAddr(), } l.addConn(conn) @@ -55,7 +55,7 @@ func (l *Listener) keepAccepting() { for { conn, err := l.listener.Accept(context.Background()) if err != nil { - newError("failed to accept QUIC sessions").Base(err).WriteToLog() + newError("failed to accept QUIC connections").Base(err).WriteToLog() if l.done.Done() { break }