Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chore: bump github.com/lucas-clemente/quic-go from 0.26.0 to 0.27.0 #1716

Merged
merged 2 commits into from Apr 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
42 changes: 21 additions & 21 deletions app/dns/nameserver_quic.go
Expand Up @@ -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
Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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
Expand All @@ -324,60 +324,60 @@ 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()

s.Lock()
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)
}
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Expand Up @@ -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=
Expand Down
106 changes: 53 additions & 53 deletions transport/internet/quic/dialer.go
Expand Up @@ -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
Expand All @@ -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
}

Expand All @@ -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},
Expand All @@ -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())
}
Expand Down
16 changes: 8 additions & 8 deletions transport/internet/quic/hub.go
Expand Up @@ -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:
Expand All @@ -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)
Expand All @@ -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
}
Expand Down