github.com/sagernet/sing@v0.2.6/common/network/thread.go (about) 1 package network 2 3 import ( 4 "github.com/sagernet/sing/common" 5 "github.com/sagernet/sing/common/buf" 6 M "github.com/sagernet/sing/common/metadata" 7 ) 8 9 type ThreadUnsafeWriter interface { 10 WriteIsThreadUnsafe() 11 } 12 13 type ThreadSafeReader interface { 14 ReadBufferThreadSafe() (buffer *buf.Buffer, err error) 15 } 16 17 type ThreadSafePacketReader interface { 18 ReadPacketThreadSafe() (buffer *buf.Buffer, addr M.Socksaddr, err error) 19 } 20 21 func IsUnsafeWriter(writer any) bool { 22 _, isUnsafe := common.Cast[ThreadUnsafeWriter](writer) 23 return isUnsafe 24 } 25 26 func IsSafeReader(reader any) ThreadSafeReader { 27 if safeReader, isSafe := reader.(ThreadSafeReader); isSafe { 28 return safeReader 29 } 30 if upstream, hasUpstream := reader.(ReaderWithUpstream); !hasUpstream || !upstream.ReaderReplaceable() { 31 return nil 32 } 33 if upstream, hasUpstream := reader.(common.WithUpstream); hasUpstream { 34 return IsSafeReader(upstream.Upstream()) 35 } 36 if upstream, hasUpstream := reader.(WithUpstreamReader); hasUpstream { 37 return IsSafeReader(upstream.UpstreamReader()) 38 } 39 return nil 40 } 41 42 func IsSafePacketReader(reader any) ThreadSafePacketReader { 43 if safeReader, isSafe := reader.(ThreadSafePacketReader); isSafe { 44 return safeReader 45 } 46 if upstream, hasUpstream := reader.(ReaderWithUpstream); !hasUpstream || !upstream.ReaderReplaceable() { 47 return nil 48 } 49 if upstream, hasUpstream := reader.(common.WithUpstream); hasUpstream { 50 return IsSafePacketReader(upstream.Upstream()) 51 } 52 if upstream, hasUpstream := reader.(WithUpstreamReader); hasUpstream { 53 return IsSafePacketReader(upstream.UpstreamReader()) 54 } 55 return nil 56 } 57 58 const DefaultHeadroom = 1024 59 60 type FrontHeadroom interface { 61 FrontHeadroom() int 62 } 63 64 type RearHeadroom interface { 65 RearHeadroom() int 66 } 67 68 type LazyHeadroom interface { 69 LazyHeadroom() bool 70 } 71 72 func CalculateFrontHeadroom(writer any) int { 73 var headroom int 74 for { 75 if writer == nil { 76 break 77 } 78 if lazyRoom, isLazy := writer.(LazyHeadroom); isLazy && lazyRoom.LazyHeadroom() { 79 return DefaultHeadroom 80 } 81 if headroomWriter, needHeadroom := writer.(FrontHeadroom); needHeadroom { 82 headroom += headroomWriter.FrontHeadroom() 83 } 84 if upstreamWriter, hasUpstreamWriter := writer.(WithUpstreamWriter); hasUpstreamWriter { 85 writer = upstreamWriter.UpstreamWriter() 86 } else if upstream, hasUpstream := writer.(common.WithUpstream); hasUpstream { 87 writer = upstream.Upstream() 88 } else { 89 break 90 } 91 } 92 return headroom 93 } 94 95 func CalculateRearHeadroom(writer any) int { 96 var headroom int 97 for { 98 if writer == nil { 99 break 100 } 101 if lazyRoom, isLazy := writer.(LazyHeadroom); isLazy && lazyRoom.LazyHeadroom() { 102 return DefaultHeadroom 103 } 104 if headroomWriter, needHeadroom := writer.(RearHeadroom); needHeadroom { 105 headroom += headroomWriter.RearHeadroom() 106 } 107 if upstreamWriter, hasUpstreamWriter := writer.(WithUpstreamWriter); hasUpstreamWriter { 108 writer = upstreamWriter.UpstreamWriter() 109 } else if upstream, hasUpstream := writer.(common.WithUpstream); hasUpstream { 110 writer = upstream.Upstream() 111 } else { 112 break 113 } 114 } 115 return headroom 116 } 117 118 type ReaderWithMTU interface { 119 ReaderMTU() int 120 } 121 122 type WriterWithMTU interface { 123 WriterMTU() int 124 } 125 126 func CalculateMTU(reader any, writer any) int { 127 readerMTU := calculateReaderMTU(reader) 128 writerMTU := calculateWriterMTU(writer) 129 if readerMTU > writerMTU { 130 return readerMTU 131 } 132 if writerMTU > buf.BufferSize { 133 return 0 134 } 135 return writerMTU 136 } 137 138 func calculateReaderMTU(reader any) int { 139 var mtu int 140 for { 141 if reader == nil { 142 break 143 } 144 if lazyRoom, isLazy := reader.(LazyHeadroom); isLazy && lazyRoom.LazyHeadroom() { 145 return 0 146 } 147 if withMTU, haveMTU := reader.(ReaderWithMTU); haveMTU { 148 upstreamMTU := withMTU.ReaderMTU() 149 if upstreamMTU > mtu { 150 mtu = upstreamMTU 151 } 152 } 153 if upstreamReader, hasUpstreamReader := reader.(WithUpstreamReader); hasUpstreamReader { 154 reader = upstreamReader.UpstreamReader() 155 } else if upstream, hasUpstream := reader.(common.WithUpstream); hasUpstream { 156 reader = upstream.Upstream() 157 } else { 158 break 159 } 160 } 161 return mtu 162 } 163 164 func calculateWriterMTU(writer any) int { 165 var mtu int 166 for { 167 if writer == nil { 168 break 169 } 170 if lazyRoom, isLazy := writer.(LazyHeadroom); isLazy && lazyRoom.LazyHeadroom() { 171 return 0 172 } 173 if withMTU, haveMTU := writer.(WriterWithMTU); haveMTU { 174 upstreamMTU := withMTU.WriterMTU() 175 if mtu == 0 || upstreamMTU > 0 && upstreamMTU < mtu { 176 mtu = upstreamMTU 177 } 178 } 179 if upstreamWriter, hasUpstreamWriter := writer.(WithUpstreamWriter); hasUpstreamWriter { 180 writer = upstreamWriter.UpstreamWriter() 181 } else if upstream, hasUpstream := writer.(common.WithUpstream); hasUpstream { 182 writer = upstream.Upstream() 183 } else { 184 break 185 } 186 } 187 return mtu 188 }