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