Compare commits

...
2 Commits
Author SHA1 Message Date
Fangliding eebbec5849 udp 2026-10-14 16:39:23 +08:00
Fangliding 79551872bd SS2022: Correct interrupt behavior and UDP conn change 2026-10-14 16:24:11 +08:00
6 changed files with 54 additions and 41 deletions
+7 -1
View File
@@ -169,12 +169,18 @@ func (i *Inbound) processUDP(ctx context.Context, conn stat.Connection, dispatch
} }
sessionItem.Unlock() sessionItem.Unlock()
} }
link, err := sessionItem.EnsureLink(ctx, conn, decoded.Destination, dispatcher, i.policyManager, func(dest net.Destination, payload []byte) ([]byte, error) { link := sessionItem.link.Load()
if link != nil {
sessionItem.UpdateConn(conn)
} else {
var err error
link, err = sessionItem.EnsureLink(ctx, conn, decoded.Destination, dispatcher, i.policyManager, func(dest net.Destination, payload []byte) ([]byte, error) {
return i.udpCodec.EncodeServerPacket(decoded.SessionID, dest, payload) return i.udpCodec.EncodeServerPacket(decoded.SessionID, dest, payload)
}) })
if err != nil { if err != nil {
continue continue
} }
}
payloadBuf := buf.New() payloadBuf := buf.New()
payloadBuf.Write(decoded.Payload) payloadBuf.Write(decoded.Payload)
+7 -1
View File
@@ -336,12 +336,18 @@ func (i *MultiUserInbound) processUDP(ctx context.Context, conn stat.Connection,
} }
sessionItem.Unlock() sessionItem.Unlock()
link, err := sessionItem.EnsureLink(ctx, conn, decoded.Destination, dispatcher, i.policyManager, func(replyDest net.Destination, payload []byte) ([]byte, error) { link := sessionItem.link.Load()
if link != nil {
sessionItem.UpdateConn(conn)
} else {
var err error
link, err = sessionItem.EnsureLink(ctx, conn, decoded.Destination, dispatcher, i.policyManager, func(replyDest net.Destination, payload []byte) ([]byte, error) {
return i.encodeServerUDPPacket(sessionID, userPSK, replyDest, payload) return i.encodeServerUDPPacket(sessionID, userPSK, replyDest, payload)
}) })
if err != nil { if err != nil {
continue continue
} }
}
pBuf := buf.New() pBuf := buf.New()
pBuf.Write(decoded.Payload) pBuf.Write(decoded.Payload)
+7 -1
View File
@@ -253,11 +253,17 @@ func (i *RelayInbound) processUDP(ctx context.Context, conn stat.Connection, dis
} }
sessionItem.Unlock() sessionItem.Unlock()
} }
link, err := sessionItem.EnsureLink(ctx, conn, dest, dispatcher, i.policyManager, nil) link := sessionItem.link.Load()
if link != nil {
sessionItem.UpdateConn(conn)
} else {
var err error
link, err = sessionItem.EnsureLink(ctx, conn, dest, dispatcher, i.policyManager, nil)
if err != nil { if err != nil {
b.Release() b.Release()
continue continue
} }
}
_ = link.Writer.WriteMultiBuffer(buf.MultiBuffer{b}) _ = link.Writer.WriteMultiBuffer(buf.MultiBuffer{b})
} }
+4 -4
View File
@@ -169,8 +169,8 @@ func (o *Outbound) Process(ctx context.Context, link *transport.Link, dialer int
return buf.Copy(responseReader, link.Writer, buf.UpdateActivity(timer)) return buf.Copy(responseReader, link.Writer, buf.UpdateActivity(timer))
} }
responseDoneAndCloseWriter := task.OnSuccess(responseDone, task.Close(link.Writer)) responseDonePost := task.OnSuccess(responseDone, task.Close(link.Writer))
if err := task.Run(ctx, requestDone, responseDoneAndCloseWriter); err != nil { if err := task.Run(ctx, requestDone, responseDonePost); err != nil {
return errors.New("connection ends").Base(err) return errors.New("connection ends").Base(err)
} }
@@ -212,8 +212,8 @@ func (o *Outbound) Process(ctx context.Context, link *transport.Link, dialer int
return nil return nil
} }
responseDoneAndCloseWriter := task.OnSuccess(responseDone, task.Close(link.Writer)) responseDonePost := task.OnSuccess(responseDone, task.Close(link.Writer))
if err := task.Run(ctx, requestDone, responseDoneAndCloseWriter); err != nil { if err := task.Run(ctx, requestDone, responseDonePost); err != nil {
return errors.New("connection ends").Base(err) return errors.New("connection ends").Base(err)
} }
+5 -18
View File
@@ -18,12 +18,8 @@ import (
) )
func (s *ServerUDPSession) UpdateConn(conn stat.Connection) { func (s *ServerUDPSession) UpdateConn(conn stat.Connection) {
if s.currentConn.Load() == nil {
s.currentConn.Store(conn) s.currentConn.Store(conn)
}
if s.timer != nil {
s.timer.Update() s.timer.Update()
}
} }
func (s *ServerUDPSession) WriteToClient(b []byte) error { func (s *ServerUDPSession) WriteToClient(b []byte) error {
@@ -57,19 +53,16 @@ func (s *ServerUDPSession) EnsureLink(
policyManager policy.Manager, policyManager policy.Manager,
responseEncoder func(dest net.Destination, payload []byte) ([]byte, error), responseEncoder func(dest net.Destination, payload []byte) ([]byte, error),
) (*transport.Link, error) { ) (*transport.Link, error) {
s.UpdateConn(conn)
if link := s.link.Load(); link != nil {
return link, nil
}
s.Lock() s.Lock()
defer s.Unlock() defer s.Unlock()
if link := s.link.Load(); link != nil { if link := s.link.Load(); link != nil {
s.UpdateConn(conn)
return link, nil return link, nil
} }
s.currentConn.Store(conn)
sessCtx, cancel := context.WithCancel(ctx) sessCtx, cancel := context.WithCancel(ctx)
inbound := session.InboundFromContext(sessCtx) inbound := session.InboundFromContext(sessCtx)
if inbound != nil && s.User != nil { if inbound != nil && s.User != nil {
@@ -94,7 +87,6 @@ func (s *ServerUDPSession) EnsureLink(
return nil, err return nil, err
} }
s.link.Store(link)
sessionPolicy := policyManager.ForLevel(level) sessionPolicy := policyManager.ForLevel(level)
s.timer = signal.CancelAfterInactivity(sessCtx, func() { s.timer = signal.CancelAfterInactivity(sessCtx, func() {
if s.manager != nil { if s.manager != nil {
@@ -103,6 +95,7 @@ func (s *ServerUDPSession) EnsureLink(
s.Close() s.Close()
cancel() cancel()
}, sessionPolicy.Timeouts.ConnectionIdle) }, sessionPolicy.Timeouts.ConnectionIdle)
s.link.Store(link)
go handleUDPResponse(s, link, dest, responseEncoder) go handleUDPResponse(s, link, dest, responseEncoder)
return link, nil return link, nil
@@ -118,19 +111,13 @@ func ResetTCPConn(conn net.Conn) {
} }
func handleUDPResponse(s *ServerUDPSession, link *transport.Link, fallbackDest net.Destination, encode func(dest net.Destination, payload []byte) ([]byte, error)) { func handleUDPResponse(s *ServerUDPSession, link *transport.Link, fallbackDest net.Destination, encode func(dest net.Destination, payload []byte) ([]byte, error)) {
defer func() { defer s.timer.SetTimeout(0)
if s.timer != nil {
s.timer.SetTimeout(0)
}
}()
for { for {
resMb, err := link.Reader.ReadMultiBuffer() resMb, err := link.Reader.ReadMultiBuffer()
if err != nil { if err != nil {
return return
} }
if s.timer != nil {
s.timer.Update() s.timer.Update()
}
for i, rb := range resMb { for i, rb := range resMb {
b := rb.Bytes() b := rb.Bytes()
if encode != nil { if encode != nil {
+10 -2
View File
@@ -11,6 +11,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/antireplay" "github.com/xtls/xray-core/common/antireplay"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
@@ -629,6 +630,7 @@ func InitServerStream(conn net.Conn, method *CipherMethod, psk, saltSlice []byte
func TransportTCP(ctx context.Context, sessionPolicy policy.Session, reader buf.Reader, writer buf.Writer, link *transport.Link) error { func TransportTCP(ctx context.Context, sessionPolicy policy.Session, reader buf.Reader, writer buf.Writer, link *transport.Link) error {
ctx, cancel := context.WithCancel(ctx) ctx, cancel := context.WithCancel(ctx)
timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle) timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
defer timer.SetTimeout(0)
ctx = policy.ContextWithBufferPolicy(ctx, sessionPolicy.Buffer) ctx = policy.ContextWithBufferPolicy(ctx, sessionPolicy.Buffer)
requestDone := func() error { requestDone := func() error {
@@ -644,6 +646,12 @@ func TransportTCP(ctx context.Context, sessionPolicy policy.Session, reader buf.
return buf.Copy(link.Reader, writer, buf.UpdateActivity(timer)) return buf.Copy(link.Reader, writer, buf.UpdateActivity(timer))
} }
responseDoneAndCloseWriter := task.OnSuccess(responseDone, task.Close(link.Writer)) requestDoneAndCloseWriter := task.OnSuccess(requestDone, task.Close(link.Writer))
return task.Run(ctx, requestDone, responseDoneAndCloseWriter) if err := task.Run(ctx, requestDoneAndCloseWriter, responseDone); err != nil {
common.Interrupt(link.Reader)
common.Interrupt(link.Writer)
return errors.New("connection ends").Base(err)
}
return nil
} }