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  }