mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-06-05 10:47:32 +03:00
Update sing-box core, refactor MASQUE, update XHTTP
This commit is contained in:
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/common/dialer"
|
||||
"github.com/sagernet/sing-box/common/sniff"
|
||||
tf "github.com/sagernet/sing-box/common/tlsfragment"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing/common"
|
||||
@@ -128,11 +129,12 @@ func (m *ConnectionManager) NewConnection(ctx context.Context, this N.Dialer, co
|
||||
if metadata.TLSFragment || metadata.TLSRecordFragment {
|
||||
remoteConn = tf.NewConn(remoteConn, ctx, metadata.TLSFragment, metadata.TLSRecordFragment, metadata.TLSFragmentFallbackDelay)
|
||||
}
|
||||
serverFirst := sniff.Skip(&metadata)
|
||||
var done atomic.Bool
|
||||
if m.kickWriteHandshake(ctx, conn, remoteConn, false, &done, onClose) {
|
||||
if m.kickWriteHandshake(ctx, conn, remoteConn, serverFirst, false, &done, onClose) {
|
||||
return
|
||||
}
|
||||
if m.kickWriteHandshake(ctx, remoteConn, conn, true, &done, onClose) {
|
||||
if m.kickWriteHandshake(ctx, remoteConn, conn, serverFirst, true, &done, onClose) {
|
||||
return
|
||||
}
|
||||
go m.connectionCopy(ctx, conn, remoteConn, false, &done, onClose)
|
||||
@@ -293,37 +295,43 @@ func (m *ConnectionManager) connectionCopy(ctx context.Context, source net.Conn,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *ConnectionManager) kickWriteHandshake(ctx context.Context, source net.Conn, destination net.Conn, direction bool, done *atomic.Bool, onClose N.CloseHandlerFunc) bool {
|
||||
func (m *ConnectionManager) kickWriteHandshake(ctx context.Context, source net.Conn, destination net.Conn, serverFirst bool, direction bool, done *atomic.Bool, onClose N.CloseHandlerFunc) bool {
|
||||
if !N.NeedHandshakeForWrite(destination) {
|
||||
return false
|
||||
}
|
||||
var (
|
||||
cachedBuffer *buf.Buffer
|
||||
err error
|
||||
wrotePayload bool
|
||||
)
|
||||
sourceReader, readCounters := N.UnwrapCountReader(source, nil)
|
||||
destinationWriter, writeCounters := N.UnwrapCountWriter(destination, nil)
|
||||
if cachedReader, ok := sourceReader.(N.CachedReader); ok {
|
||||
cachedBuffer = cachedReader.ReadCached()
|
||||
}
|
||||
var err error
|
||||
if cachedBuffer != nil {
|
||||
wrotePayload = true
|
||||
dataLen := cachedBuffer.Len()
|
||||
_, err = destinationWriter.Write(cachedBuffer.Bytes())
|
||||
cachedBuffer.Release()
|
||||
if err == nil {
|
||||
for _, counter := range readCounters {
|
||||
counter(int64(dataLen))
|
||||
}
|
||||
for _, counter := range writeCounters {
|
||||
counter(int64(dataLen))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if serverFirst {
|
||||
_ = destination.SetWriteDeadline(time.Now().Add(C.ReadPayloadTimeout))
|
||||
_, err = destinationWriter.Write(nil)
|
||||
_, err = destination.Write(nil)
|
||||
_ = destination.SetWriteDeadline(time.Time{})
|
||||
} else {
|
||||
var cachedBuffer *buf.Buffer
|
||||
sourceReader, readCounters := N.UnwrapCountReader(source, nil)
|
||||
destinationWriter, writeCounters := N.UnwrapCountWriter(destination, nil)
|
||||
if cachedReader, ok := sourceReader.(N.CachedReader); ok {
|
||||
cachedBuffer = cachedReader.ReadCached()
|
||||
}
|
||||
if cachedBuffer != nil {
|
||||
wrotePayload = true
|
||||
dataLen := cachedBuffer.Len()
|
||||
_, err = destinationWriter.Write(cachedBuffer.Bytes())
|
||||
cachedBuffer.Release()
|
||||
if err == nil {
|
||||
for _, counter := range readCounters {
|
||||
counter(int64(dataLen))
|
||||
}
|
||||
for _, counter := range writeCounters {
|
||||
counter(int64(dataLen))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_ = destination.SetWriteDeadline(time.Now().Add(C.ReadPayloadTimeout))
|
||||
_, err = destinationWriter.Write(nil)
|
||||
_ = destination.SetWriteDeadline(time.Time{})
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
return false
|
||||
|
||||
@@ -3,6 +3,7 @@ package route
|
||||
import (
|
||||
"context"
|
||||
"net/netip"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
@@ -78,10 +79,8 @@ func (r *Router) isLocalSource(source netip.Addr) bool {
|
||||
return true
|
||||
}
|
||||
if r.platformInterface != nil {
|
||||
for _, addr := range r.platformInterface.MyInterfaceAddress() {
|
||||
if addr == source {
|
||||
return true
|
||||
}
|
||||
if slices.Contains(r.platformInterface.MyInterfaceAddress(), source) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
for _, netInterface := range r.network.InterfaceFinder().Interfaces() {
|
||||
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
|
||||
// Deprecated: use RouteConnectionEx instead.
|
||||
func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||
done := make(chan interface{})
|
||||
done := make(chan any)
|
||||
err := r.routeConnection(ctx, conn, metadata, N.OnceClose(func(it error) {
|
||||
close(done)
|
||||
}))
|
||||
@@ -160,7 +160,7 @@ func (r *Router) routeConnection(ctx context.Context, conn net.Conn, metadata ad
|
||||
}
|
||||
|
||||
func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||
done := make(chan interface{})
|
||||
done := make(chan any)
|
||||
err := r.routePacketConnection(ctx, conn, metadata, N.OnceClose(func(it error) {
|
||||
close(done)
|
||||
}))
|
||||
|
||||
@@ -42,11 +42,11 @@ func (s ruleMatchStateSet) combine(other ruleMatchStateSet) ruleMatchStateSet {
|
||||
return 0
|
||||
}
|
||||
var combined ruleMatchStateSet
|
||||
for left := ruleMatchState(0); left < 16; left++ {
|
||||
for left := range ruleMatchState(16) {
|
||||
if !s.contains(left) {
|
||||
continue
|
||||
}
|
||||
for right := ruleMatchState(0); right < 16; right++ {
|
||||
for right := range ruleMatchState(16) {
|
||||
if !other.contains(right) {
|
||||
continue
|
||||
}
|
||||
@@ -61,7 +61,7 @@ func (s ruleMatchStateSet) withBase(base ruleMatchState) ruleMatchStateSet {
|
||||
return 0
|
||||
}
|
||||
var withBase ruleMatchStateSet
|
||||
for state := ruleMatchState(0); state < 16; state++ {
|
||||
for state := range ruleMatchState(16) {
|
||||
if !s.contains(state) {
|
||||
continue
|
||||
}
|
||||
@@ -72,7 +72,7 @@ func (s ruleMatchStateSet) withBase(base ruleMatchState) ruleMatchStateSet {
|
||||
|
||||
func (s ruleMatchStateSet) filter(allowed func(ruleMatchState) bool) ruleMatchStateSet {
|
||||
var filtered ruleMatchStateSet
|
||||
for state := ruleMatchState(0); state < 16; state++ {
|
||||
for state := range ruleMatchState(16) {
|
||||
if !s.contains(state) {
|
||||
continue
|
||||
}
|
||||
@@ -91,10 +91,6 @@ type ruleStateMatcherWithBase interface {
|
||||
matchStatesWithBase(metadata *adapter.InboundContext, base ruleMatchState) ruleMatchStateSet
|
||||
}
|
||||
|
||||
func matchHeadlessRuleStates(rule adapter.HeadlessRule, metadata *adapter.InboundContext) ruleMatchStateSet {
|
||||
return matchHeadlessRuleStatesWithBase(rule, metadata, 0)
|
||||
}
|
||||
|
||||
func matchHeadlessRuleStatesWithBase(rule adapter.HeadlessRule, metadata *adapter.InboundContext, base ruleMatchState) ruleMatchStateSet {
|
||||
if matcher, isStateMatcher := rule.(ruleStateMatcherWithBase); isStateMatcher {
|
||||
return matcher.matchStatesWithBase(metadata, base)
|
||||
@@ -108,10 +104,6 @@ func matchHeadlessRuleStatesWithBase(rule adapter.HeadlessRule, metadata *adapte
|
||||
return 0
|
||||
}
|
||||
|
||||
func matchRuleItemStates(item RuleItem, metadata *adapter.InboundContext) ruleMatchStateSet {
|
||||
return matchRuleItemStatesWithBase(item, metadata, 0)
|
||||
}
|
||||
|
||||
func matchRuleItemStatesWithBase(item RuleItem, metadata *adapter.InboundContext, base ruleMatchState) ruleMatchStateSet {
|
||||
if matcher, isStateMatcher := item.(ruleStateMatcherWithBase); isStateMatcher {
|
||||
return matcher.matchStatesWithBase(metadata, base)
|
||||
|
||||
@@ -141,7 +141,6 @@ func TestAbstractLogicalRule_And_WithRuleSetInvert(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
testCase := testCase
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
logicalRule := &abstractLogicalRule{
|
||||
|
||||
@@ -2,6 +2,7 @@ package rule
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
@@ -80,12 +81,7 @@ func (r *IPCIDRItem) Match(metadata *adapter.InboundContext) bool {
|
||||
return r.ipSet.Contains(metadata.Destination.Addr)
|
||||
}
|
||||
if len(metadata.DestinationAddresses) > 0 {
|
||||
for _, address := range metadata.DestinationAddresses {
|
||||
if r.ipSet.Contains(address) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.ContainsFunc(metadata.DestinationAddresses, r.ipSet.Contains)
|
||||
}
|
||||
return metadata.IPCIDRAcceptEmpty
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package rule
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
@@ -16,15 +17,11 @@ type DomainItem struct {
|
||||
}
|
||||
|
||||
func NewDomainItem(domains []string, domainSuffixes []string) (*DomainItem, error) {
|
||||
for _, domainItem := range domains {
|
||||
if domainItem == "" {
|
||||
return nil, E.New("domain: empty item is not allowed")
|
||||
}
|
||||
if slices.Contains(domains, "") {
|
||||
return nil, E.New("domain: empty item is not allowed")
|
||||
}
|
||||
for _, domainSuffixItem := range domainSuffixes {
|
||||
if domainSuffixItem == "" {
|
||||
return nil, E.New("domain_suffix: empty item is not allowed")
|
||||
}
|
||||
if slices.Contains(domainSuffixes, "") {
|
||||
return nil, E.New("domain_suffix: empty item is not allowed")
|
||||
}
|
||||
var description string
|
||||
if dLen := len(domains); dLen > 0 {
|
||||
|
||||
@@ -57,7 +57,6 @@ func TestRouteRuleSetMergeDestinationAddressGroup(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
testCase := testCase
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
ruleSet := newLocalRuleSetForTest("merge-destination", testCase.inner)
|
||||
@@ -223,7 +222,6 @@ func TestRouteRuleSetOuterGroupedStateMergesIntoSameGroup(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
testCase := testCase
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
ruleSet := newLocalRuleSetForTest("outer-merge-"+testCase.name, headlessDefaultRule(t, func(rule *abstractDefaultRule) {
|
||||
@@ -652,7 +650,6 @@ func TestDNSInvertAddressLimitPreLookupRegression(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
testCase := testCase
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
rule := dnsRuleForTest(func(rule *abstractDefaultRule) {
|
||||
|
||||
Reference in New Issue
Block a user