sing/common/network/thread.go
2024-11-05 18:43:04 +08:00

219 lines
5.6 KiB
Go

package network
import (
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/buf"
M "github.com/sagernet/sing/common/metadata"
)
type ThreadUnsafeWriter interface {
WriteIsThreadUnsafe()
}
// Deprecated: Use ReadWaiter interface instead.
type ThreadSafeReader interface {
// Deprecated: Use ReadWaiter interface instead.
ReadBufferThreadSafe() (buffer *buf.Buffer, err error)
}
// Deprecated: Use ReadWaiter interface instead.
type ThreadSafePacketReader interface {
ReadPacketThreadSafe() (buffer *buf.Buffer, addr M.Socksaddr, err error)
}
func IsUnsafeWriter(writer any) bool {
_, isUnsafe := common.Cast[ThreadUnsafeWriter](writer)
return isUnsafe
}
// Deprecated: Use ReadWaiter interface instead.
func IsSafeReader(reader any) ThreadSafeReader {
if safeReader, isSafe := reader.(ThreadSafeReader); isSafe {
return safeReader
}
if upstream, hasUpstream := reader.(ReaderWithUpstream); !hasUpstream || !upstream.ReaderReplaceable() {
return nil
}
if upstream, hasUpstream := reader.(common.WithUpstream); hasUpstream {
return IsSafeReader(upstream.Upstream())
}
if upstream, hasUpstream := reader.(WithUpstreamReader); hasUpstream {
return IsSafeReader(upstream.UpstreamReader())
}
return nil
}
// Deprecated: Use ReadWaiter interface instead.
func IsSafePacketReader(reader any) ThreadSafePacketReader {
if safeReader, isSafe := reader.(ThreadSafePacketReader); isSafe {
return safeReader
}
if upstream, hasUpstream := reader.(ReaderWithUpstream); !hasUpstream || !upstream.ReaderReplaceable() {
return nil
}
if upstream, hasUpstream := reader.(common.WithUpstream); hasUpstream {
return IsSafePacketReader(upstream.Upstream())
}
if upstream, hasUpstream := reader.(WithUpstreamReader); hasUpstream {
return IsSafePacketReader(upstream.UpstreamReader())
}
return nil
}
const DefaultHeadroom = 1024
type FrontHeadroom interface {
FrontHeadroom() int
}
type RearHeadroom interface {
RearHeadroom() int
}
type LazyHeadroom interface {
LazyHeadroom() bool
}
func CalculateFrontHeadroom(writer any) int {
var headroom int
for {
if writer == nil {
break
}
if lazyRoom, isLazy := writer.(LazyHeadroom); isLazy && lazyRoom.LazyHeadroom() {
return DefaultHeadroom
}
if headroomWriter, needHeadroom := writer.(FrontHeadroom); needHeadroom {
headroom += headroomWriter.FrontHeadroom()
}
if upstreamWriter, hasUpstreamWriter := writer.(WithUpstreamWriter); hasUpstreamWriter {
writer = upstreamWriter.UpstreamWriter()
} else if upstream, hasUpstream := writer.(common.WithUpstream); hasUpstream {
writer = upstream.Upstream()
} else {
break
}
}
return headroom
}
func calculateReaderFrontHeadroom(reader any) int {
var headroom int
for {
if reader == nil {
break
}
if lazyRoom, isLazy := reader.(LazyHeadroom); isLazy && lazyRoom.LazyHeadroom() {
return DefaultHeadroom
}
if headroomWriter, needHeadroom := reader.(FrontHeadroom); needHeadroom {
headroom += headroomWriter.FrontHeadroom()
}
if upstreamWriter, hasUpstreamWriter := reader.(WithUpstreamReader); hasUpstreamWriter {
reader = upstreamWriter.UpstreamReader()
} else if upstream, hasUpstream := reader.(common.WithUpstream); hasUpstream {
reader = upstream.Upstream()
} else {
break
}
}
return headroom
}
func CalculateRearHeadroom(writer any) int {
var headroom int
for {
if writer == nil {
break
}
if lazyRoom, isLazy := writer.(LazyHeadroom); isLazy && lazyRoom.LazyHeadroom() {
return DefaultHeadroom
}
if headroomWriter, needHeadroom := writer.(RearHeadroom); needHeadroom {
headroom += headroomWriter.RearHeadroom()
}
if upstreamWriter, hasUpstreamWriter := writer.(WithUpstreamWriter); hasUpstreamWriter {
writer = upstreamWriter.UpstreamWriter()
} else if upstream, hasUpstream := writer.(common.WithUpstream); hasUpstream {
writer = upstream.Upstream()
} else {
break
}
}
return headroom
}
type ReaderWithMTU interface {
ReaderMTU() int
}
type WriterWithMTU interface {
WriterMTU() int
}
func CalculateMTU(reader any, writer any) int {
readerMTU := calculateReaderMTU(reader)
writerMTU := calculateWriterMTU(writer)
if readerMTU == 0 && writerMTU == 0 || readerMTU > buf.BufferSize || writerMTU > buf.BufferSize {
return 0
}
readerHeadroom := calculateReaderFrontHeadroom(reader)
if readerMTU > writerMTU {
return readerMTU + readerHeadroom
} else {
return writerMTU + readerHeadroom
}
}
func calculateReaderMTU(reader any) int {
var mtu int
for {
if reader == nil {
break
}
if lazyRoom, isLazy := reader.(LazyHeadroom); isLazy && lazyRoom.LazyHeadroom() {
return 0
}
if withMTU, haveMTU := reader.(ReaderWithMTU); haveMTU {
upstreamMTU := withMTU.ReaderMTU()
if upstreamMTU > mtu {
mtu = upstreamMTU
}
}
if upstreamReader, hasUpstreamReader := reader.(WithUpstreamReader); hasUpstreamReader {
reader = upstreamReader.UpstreamReader()
} else if upstream, hasUpstream := reader.(common.WithUpstream); hasUpstream {
reader = upstream.Upstream()
} else {
break
}
}
return mtu
}
func calculateWriterMTU(writer any) int {
var mtu int
for {
if writer == nil {
break
}
if lazyRoom, isLazy := writer.(LazyHeadroom); isLazy && lazyRoom.LazyHeadroom() {
return 0
}
if withMTU, haveMTU := writer.(WriterWithMTU); haveMTU {
upstreamMTU := withMTU.WriterMTU()
if mtu == 0 || upstreamMTU > 0 && upstreamMTU < mtu {
mtu = upstreamMTU
}
}
if upstreamWriter, hasUpstreamWriter := writer.(WithUpstreamWriter); hasUpstreamWriter {
writer = upstreamWriter.UpstreamWriter()
} else if upstream, hasUpstream := writer.(common.WithUpstream); hasUpstream {
writer = upstream.Upstream()
} else {
break
}
}
return mtu
}