mirror of
https://github.com/SagerNet/sing-box.git
synced 2025-06-13 21:54:13 +08:00
Merge branch 'SagerNet:dev-next' into dev-next
This commit is contained in:
commit
3174785d58
4
Makefile
4
Makefile
@ -89,8 +89,8 @@ lib:
|
|||||||
|
|
||||||
lib_install:
|
lib_install:
|
||||||
go get -v -d
|
go get -v -d
|
||||||
go install -v github.com/sagernet/gomobile/cmd/gomobile@v0.0.0-20230413023804-244d7ff07035
|
go install -v github.com/sagernet/gomobile/cmd/gomobile@v0.0.0-20230701084532-493ee2e45182
|
||||||
go install -v github.com/sagernet/gomobile/cmd/gobind@v0.0.0-20230413023804-244d7ff07035
|
go install -v github.com/sagernet/gomobile/cmd/gobind@v0.0.0-20230701084532-493ee2e45182
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf bin dist sing-box
|
rm -rf bin dist sing-box
|
||||||
|
@ -31,6 +31,7 @@ type Tracker interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type OutboundGroup interface {
|
type OutboundGroup interface {
|
||||||
|
Outbound
|
||||||
Now() string
|
Now() string
|
||||||
All() []string
|
All() []string
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,13 @@ import (
|
|||||||
"net/netip"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/sagernet/sing-dns"
|
"github.com/sagernet/sing-dns"
|
||||||
|
"github.com/sagernet/sing/common/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FakeIPStore interface {
|
type FakeIPStore interface {
|
||||||
Service
|
Service
|
||||||
Contains(address netip.Addr) bool
|
Contains(address netip.Addr) bool
|
||||||
Create(domain string, strategy dns.DomainStrategy) (netip.Addr, error)
|
Create(domain string, isIPv6 bool) (netip.Addr, error)
|
||||||
Lookup(address netip.Addr) (string, bool)
|
Lookup(address netip.Addr) (string, bool)
|
||||||
Reset() error
|
Reset() error
|
||||||
}
|
}
|
||||||
@ -18,7 +19,9 @@ type FakeIPStorage interface {
|
|||||||
FakeIPMetadata() *FakeIPMetadata
|
FakeIPMetadata() *FakeIPMetadata
|
||||||
FakeIPSaveMetadata(metadata *FakeIPMetadata) error
|
FakeIPSaveMetadata(metadata *FakeIPMetadata) error
|
||||||
FakeIPStore(address netip.Addr, domain string) error
|
FakeIPStore(address netip.Addr, domain string) error
|
||||||
|
FakeIPStoreAsync(address netip.Addr, domain string, logger logger.Logger)
|
||||||
FakeIPLoad(address netip.Addr) (string, bool)
|
FakeIPLoad(address netip.Addr) (string, bool)
|
||||||
|
FakeIPLoadDomain(domain string, isIPv6 bool) (netip.Addr, bool)
|
||||||
FakeIPReset() error
|
FakeIPReset() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,12 +4,6 @@ type PreStarter interface {
|
|||||||
PreStart() error
|
PreStart() error
|
||||||
}
|
}
|
||||||
|
|
||||||
func PreStart(starter any) error {
|
type PostStarter interface {
|
||||||
if preService, ok := starter.(PreStarter); ok {
|
PostStart() error
|
||||||
err := preService.PreStart()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
19
box.go
19
box.go
@ -211,12 +211,14 @@ func (s *Box) Start() error {
|
|||||||
|
|
||||||
func (s *Box) preStart() error {
|
func (s *Box) preStart() error {
|
||||||
for serviceName, service := range s.preServices {
|
for serviceName, service := range s.preServices {
|
||||||
|
if preService, isPreService := service.(adapter.PreStarter); isPreService {
|
||||||
s.logger.Trace("pre-start ", serviceName)
|
s.logger.Trace("pre-start ", serviceName)
|
||||||
err := adapter.PreStart(service)
|
err := preService.PreStart()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(err, "pre-starting ", serviceName)
|
return E.Cause(err, "pre-starting ", serviceName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
err := s.startOutbounds()
|
err := s.startOutbounds()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -249,13 +251,26 @@ func (s *Box) start() error {
|
|||||||
return E.Cause(err, "initialize inbound/", in.Type(), "[", tag, "]")
|
return E.Cause(err, "initialize inbound/", in.Type(), "[", tag, "]")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Box) postStart() error {
|
||||||
for serviceName, service := range s.postServices {
|
for serviceName, service := range s.postServices {
|
||||||
s.logger.Trace("starting ", service)
|
s.logger.Trace("starting ", service)
|
||||||
err = service.Start()
|
err := service.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(err, "start ", serviceName)
|
return E.Cause(err, "start ", serviceName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for serviceName, service := range s.outbounds {
|
||||||
|
if lateService, isLateService := service.(adapter.PostStarter); isLateService {
|
||||||
|
s.logger.Trace("post-starting ", service)
|
||||||
|
err := lateService.PostStart()
|
||||||
|
if err != nil {
|
||||||
|
return E.Cause(err, "post-start ", serviceName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ func buildiOS() {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
copyPath := filepath.Join("..", "sing-box-for-ios")
|
copyPath := filepath.Join("..", "sing-box-for-apple")
|
||||||
if rw.FileExists(copyPath) {
|
if rw.FileExists(copyPath) {
|
||||||
targetDir := filepath.Join(copyPath, "Libbox.xcframework")
|
targetDir := filepath.Join(copyPath, "Libbox.xcframework")
|
||||||
targetDir, _ = filepath.Abs(targetDir)
|
targetDir, _ = filepath.Abs(targetDir)
|
||||||
|
@ -55,7 +55,7 @@ func WrapQUIC(err error) error {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if Contains(err, "canceled with error code 0") {
|
if Contains(err, "canceled by local with error code 0") {
|
||||||
return net.ErrClosed
|
return net.ErrClosed
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
@ -1,87 +0,0 @@
|
|||||||
package debugio
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/log"
|
|
||||||
"github.com/sagernet/sing/common/buf"
|
|
||||||
"github.com/sagernet/sing/common/bufio"
|
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
|
||||||
N "github.com/sagernet/sing/common/network"
|
|
||||||
)
|
|
||||||
|
|
||||||
type LogConn struct {
|
|
||||||
N.ExtendedConn
|
|
||||||
logger log.Logger
|
|
||||||
prefix string
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewLogConn(conn net.Conn, logger log.Logger, prefix string) N.ExtendedConn {
|
|
||||||
return &LogConn{bufio.NewExtendedConn(conn), logger, prefix}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *LogConn) Read(p []byte) (n int, err error) {
|
|
||||||
n, err = c.ExtendedConn.Read(p)
|
|
||||||
if n > 0 {
|
|
||||||
c.logger.Debug(c.prefix, " read ", buf.EncodeHexString(p[:n]))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *LogConn) Write(p []byte) (n int, err error) {
|
|
||||||
c.logger.Debug(c.prefix, " write ", buf.EncodeHexString(p))
|
|
||||||
return c.ExtendedConn.Write(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *LogConn) ReadBuffer(buffer *buf.Buffer) error {
|
|
||||||
err := c.ExtendedConn.ReadBuffer(buffer)
|
|
||||||
if err == nil {
|
|
||||||
c.logger.Debug(c.prefix, " read buffer ", buf.EncodeHexString(buffer.Bytes()))
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *LogConn) WriteBuffer(buffer *buf.Buffer) error {
|
|
||||||
c.logger.Debug(c.prefix, " write buffer ", buf.EncodeHexString(buffer.Bytes()))
|
|
||||||
return c.ExtendedConn.WriteBuffer(buffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *LogConn) Upstream() any {
|
|
||||||
return c.ExtendedConn
|
|
||||||
}
|
|
||||||
|
|
||||||
type LogPacketConn struct {
|
|
||||||
N.NetPacketConn
|
|
||||||
logger log.Logger
|
|
||||||
prefix string
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewLogPacketConn(conn net.PacketConn, logger log.Logger, prefix string) N.NetPacketConn {
|
|
||||||
return &LogPacketConn{bufio.NewPacketConn(conn), logger, prefix}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *LogPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
|
||||||
n, addr, err = c.NetPacketConn.ReadFrom(p)
|
|
||||||
if n > 0 {
|
|
||||||
c.logger.Debug(c.prefix, " read from ", addr, " ", buf.EncodeHexString(p[:n]))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *LogPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
|
||||||
c.logger.Debug(c.prefix, " write to ", addr, " ", buf.EncodeHexString(p))
|
|
||||||
return c.NetPacketConn.WriteTo(p, addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *LogPacketConn) ReadPacket(buffer *buf.Buffer) (destination M.Socksaddr, err error) {
|
|
||||||
destination, err = c.NetPacketConn.ReadPacket(buffer)
|
|
||||||
if err == nil {
|
|
||||||
c.logger.Debug(c.prefix, " read packet from ", destination, " ", buf.EncodeHexString(buffer.Bytes()))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *LogPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
|
|
||||||
c.logger.Debug(c.prefix, " write packet to ", destination, " ", buf.EncodeHexString(buffer.Bytes()))
|
|
||||||
return c.NetPacketConn.WritePacket(buffer, destination)
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
package debugio
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
|
|
||||||
"github.com/sagernet/sing/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
func PrintUpstream(obj any) {
|
|
||||||
for obj != nil {
|
|
||||||
fmt.Println(reflect.TypeOf(obj))
|
|
||||||
if u, ok := obj.(common.WithUpstream); !ok {
|
|
||||||
break
|
|
||||||
} else {
|
|
||||||
obj = u.Upstream()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
package debugio
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/sagernet/sing/common/buf"
|
|
||||||
"github.com/sagernet/sing/common/bufio"
|
|
||||||
N "github.com/sagernet/sing/common/network"
|
|
||||||
)
|
|
||||||
|
|
||||||
type RaceConn struct {
|
|
||||||
N.ExtendedConn
|
|
||||||
readAccess sync.Mutex
|
|
||||||
writeAccess sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewRaceConn(conn net.Conn) N.ExtendedConn {
|
|
||||||
return &RaceConn{ExtendedConn: bufio.NewExtendedConn(conn)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *RaceConn) Read(p []byte) (n int, err error) {
|
|
||||||
c.readAccess.Lock()
|
|
||||||
defer c.readAccess.Unlock()
|
|
||||||
return c.ExtendedConn.Read(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *RaceConn) Write(p []byte) (n int, err error) {
|
|
||||||
c.writeAccess.Lock()
|
|
||||||
defer c.writeAccess.Unlock()
|
|
||||||
return c.ExtendedConn.Write(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *RaceConn) ReadBuffer(buffer *buf.Buffer) error {
|
|
||||||
c.readAccess.Lock()
|
|
||||||
defer c.readAccess.Unlock()
|
|
||||||
return c.ExtendedConn.ReadBuffer(buffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *RaceConn) WriteBuffer(buffer *buf.Buffer) error {
|
|
||||||
c.writeAccess.Lock()
|
|
||||||
defer c.writeAccess.Unlock()
|
|
||||||
return c.ExtendedConn.WriteBuffer(buffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *RaceConn) Upstream() any {
|
|
||||||
return c.ExtendedConn
|
|
||||||
}
|
|
@ -128,13 +128,6 @@ func (c *slowOpenConn) NeedHandshake() bool {
|
|||||||
return c.conn == nil
|
return c.conn == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *slowOpenConn) ReadFrom(r io.Reader) (n int64, err error) {
|
|
||||||
if c.conn != nil {
|
|
||||||
return bufio.Copy(c.conn, r)
|
|
||||||
}
|
|
||||||
return bufio.ReadFrom0(c, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *slowOpenConn) WriteTo(w io.Writer) (n int64, err error) {
|
func (c *slowOpenConn) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
if c.conn == nil {
|
if c.conn == nil {
|
||||||
select {
|
select {
|
||||||
|
@ -15,7 +15,6 @@ import (
|
|||||||
"unicode"
|
"unicode"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/sagernet/sing/common"
|
|
||||||
"github.com/sagernet/sing/common/buf"
|
"github.com/sagernet/sing/common/buf"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
@ -82,9 +81,7 @@ func resolveSocketByNetlink(network string, source netip.AddrPort, destination n
|
|||||||
return 0, 0, E.Cause(err, "write netlink request")
|
return 0, 0, E.Cause(err, "write netlink request")
|
||||||
}
|
}
|
||||||
|
|
||||||
_buffer := buf.StackNew()
|
buffer := buf.New()
|
||||||
defer common.KeepAlive(_buffer)
|
|
||||||
buffer := common.Dup(_buffer)
|
|
||||||
defer buffer.Release()
|
defer buffer.Release()
|
||||||
|
|
||||||
n, err := syscall.Read(socket, buffer.FreeBytes())
|
n, err := syscall.Read(socket, buffer.FreeBytes())
|
||||||
|
@ -26,9 +26,7 @@ func StreamDomainNameQuery(readCtx context.Context, reader io.Reader) (*adapter.
|
|||||||
if length == 0 {
|
if length == 0 {
|
||||||
return nil, os.ErrInvalid
|
return nil, os.ErrInvalid
|
||||||
}
|
}
|
||||||
_buffer := buf.StackNewSize(int(length))
|
buffer := buf.NewSize(int(length))
|
||||||
defer common.KeepAlive(_buffer)
|
|
||||||
buffer := common.Dup(_buffer)
|
|
||||||
defer buffer.Release()
|
defer buffer.Release()
|
||||||
|
|
||||||
readCtx, cancel := context.WithTimeout(readCtx, time.Millisecond*100)
|
readCtx, cancel := context.WithTimeout(readCtx, time.Millisecond*100)
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
"github.com/sagernet/sing/common/x/list"
|
||||||
)
|
)
|
||||||
|
|
||||||
type History struct {
|
type History struct {
|
||||||
@ -20,6 +21,7 @@ type History struct {
|
|||||||
type HistoryStorage struct {
|
type HistoryStorage struct {
|
||||||
access sync.RWMutex
|
access sync.RWMutex
|
||||||
delayHistory map[string]*History
|
delayHistory map[string]*History
|
||||||
|
callbacks list.List[func()]
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHistoryStorage() *HistoryStorage {
|
func NewHistoryStorage() *HistoryStorage {
|
||||||
@ -28,6 +30,18 @@ func NewHistoryStorage() *HistoryStorage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *HistoryStorage) AddListener(listener func()) *list.Element[func()] {
|
||||||
|
s.access.Lock()
|
||||||
|
defer s.access.Unlock()
|
||||||
|
return s.callbacks.PushBack(listener)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *HistoryStorage) RemoveListener(element *list.Element[func()]) {
|
||||||
|
s.access.Lock()
|
||||||
|
defer s.access.Unlock()
|
||||||
|
s.callbacks.Remove(element)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *HistoryStorage) LoadURLTestHistory(tag string) *History {
|
func (s *HistoryStorage) LoadURLTestHistory(tag string) *History {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
return nil
|
return nil
|
||||||
@ -39,14 +53,24 @@ func (s *HistoryStorage) LoadURLTestHistory(tag string) *History {
|
|||||||
|
|
||||||
func (s *HistoryStorage) DeleteURLTestHistory(tag string) {
|
func (s *HistoryStorage) DeleteURLTestHistory(tag string) {
|
||||||
s.access.Lock()
|
s.access.Lock()
|
||||||
defer s.access.Unlock()
|
|
||||||
delete(s.delayHistory, tag)
|
delete(s.delayHistory, tag)
|
||||||
|
s.access.Unlock()
|
||||||
|
s.notifyUpdated()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HistoryStorage) StoreURLTestHistory(tag string, history *History) {
|
func (s *HistoryStorage) StoreURLTestHistory(tag string, history *History) {
|
||||||
s.access.Lock()
|
s.access.Lock()
|
||||||
defer s.access.Unlock()
|
|
||||||
s.delayHistory[tag] = history
|
s.delayHistory[tag] = history
|
||||||
|
s.access.Unlock()
|
||||||
|
s.notifyUpdated()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *HistoryStorage) notifyUpdated() {
|
||||||
|
s.access.RLock()
|
||||||
|
defer s.access.RUnlock()
|
||||||
|
for element := s.callbacks.Front(); element != nil; element = element.Next() {
|
||||||
|
element.Value()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func URLTest(ctx context.Context, link string, detour N.Dialer) (t uint16, err error) {
|
func URLTest(ctx context.Context, link string, detour N.Dialer) (t uint16, err error) {
|
||||||
|
@ -1,3 +1,11 @@
|
|||||||
|
#### 1.3.1-beta.2
|
||||||
|
|
||||||
|
* Fix bugs and update dependencies
|
||||||
|
|
||||||
|
#### 1.3.1-beta.1
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
#### 1.3.0
|
#### 1.3.0
|
||||||
|
|
||||||
* Fix bugs and update dependencies
|
* Fix bugs and update dependencies
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package cachefile
|
package cachefile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/netip"
|
||||||
"os"
|
"os"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
@ -16,6 +18,8 @@ var _ adapter.ClashCacheFile = (*CacheFile)(nil)
|
|||||||
type CacheFile struct {
|
type CacheFile struct {
|
||||||
DB *bbolt.DB
|
DB *bbolt.DB
|
||||||
cacheID []byte
|
cacheID []byte
|
||||||
|
saveAccess sync.RWMutex
|
||||||
|
saveCache map[netip.Addr]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func Open(path string, cacheID string) (*CacheFile, error) {
|
func Open(path string, cacheID string) (*CacheFile, error) {
|
||||||
@ -36,7 +40,11 @@ func Open(path string, cacheID string) (*CacheFile, error) {
|
|||||||
if cacheID != "" {
|
if cacheID != "" {
|
||||||
cacheIDBytes = append([]byte{0}, []byte(cacheID)...)
|
cacheIDBytes = append([]byte{0}, []byte(cacheID)...)
|
||||||
}
|
}
|
||||||
return &CacheFile{db, cacheIDBytes}, nil
|
return &CacheFile{
|
||||||
|
DB: db,
|
||||||
|
cacheID: cacheIDBytes,
|
||||||
|
saveCache: make(map[netip.Addr]string),
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CacheFile) bucket(t *bbolt.Tx, key []byte) *bbolt.Bucket {
|
func (c *CacheFile) bucket(t *bbolt.Tx, key []byte) *bbolt.Bucket {
|
||||||
|
@ -5,12 +5,16 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing/common/logger"
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
|
||||||
"go.etcd.io/bbolt"
|
"go.etcd.io/bbolt"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
bucketFakeIP = []byte("fakeip")
|
bucketFakeIP = []byte("fakeip")
|
||||||
|
bucketFakeIPDomain4 = []byte("fakeip_domain4")
|
||||||
|
bucketFakeIPDomain6 = []byte("fakeip_domain6")
|
||||||
keyMetadata = []byte("metadata")
|
keyMetadata = []byte("metadata")
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -53,11 +57,44 @@ func (c *CacheFile) FakeIPStore(address netip.Addr, domain string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return bucket.Put(address.AsSlice(), []byte(domain))
|
err = bucket.Put(address.AsSlice(), []byte(domain))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if address.Is4() {
|
||||||
|
bucket, err = tx.CreateBucketIfNotExists(bucketFakeIPDomain4)
|
||||||
|
} else {
|
||||||
|
bucket, err = tx.CreateBucketIfNotExists(bucketFakeIPDomain6)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return bucket.Put([]byte(domain), address.AsSlice())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *CacheFile) FakeIPStoreAsync(address netip.Addr, domain string, logger logger.Logger) {
|
||||||
|
c.saveAccess.Lock()
|
||||||
|
c.saveCache[address] = domain
|
||||||
|
c.saveAccess.Unlock()
|
||||||
|
go func() {
|
||||||
|
err := c.FakeIPStore(address, domain)
|
||||||
|
if err != nil {
|
||||||
|
logger.Warn("save FakeIP address pair: ", err)
|
||||||
|
}
|
||||||
|
c.saveAccess.Lock()
|
||||||
|
delete(c.saveCache, address)
|
||||||
|
c.saveAccess.Unlock()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
func (c *CacheFile) FakeIPLoad(address netip.Addr) (string, bool) {
|
func (c *CacheFile) FakeIPLoad(address netip.Addr) (string, bool) {
|
||||||
|
c.saveAccess.RLock()
|
||||||
|
cachedDomain, cached := c.saveCache[address]
|
||||||
|
c.saveAccess.RUnlock()
|
||||||
|
if cached {
|
||||||
|
return cachedDomain, true
|
||||||
|
}
|
||||||
var domain string
|
var domain string
|
||||||
_ = c.DB.View(func(tx *bbolt.Tx) error {
|
_ = c.DB.View(func(tx *bbolt.Tx) error {
|
||||||
bucket := tx.Bucket(bucketFakeIP)
|
bucket := tx.Bucket(bucketFakeIP)
|
||||||
@ -70,8 +107,34 @@ func (c *CacheFile) FakeIPLoad(address netip.Addr) (string, bool) {
|
|||||||
return domain, domain != ""
|
return domain, domain != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *CacheFile) FakeIPLoadDomain(domain string, isIPv6 bool) (netip.Addr, bool) {
|
||||||
|
var address netip.Addr
|
||||||
|
_ = c.DB.View(func(tx *bbolt.Tx) error {
|
||||||
|
var bucket *bbolt.Bucket
|
||||||
|
if isIPv6 {
|
||||||
|
bucket = tx.Bucket(bucketFakeIPDomain6)
|
||||||
|
} else {
|
||||||
|
bucket = tx.Bucket(bucketFakeIPDomain4)
|
||||||
|
}
|
||||||
|
if bucket == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
address = M.AddrFromIP(bucket.Get([]byte(domain)))
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return address, address.IsValid()
|
||||||
|
}
|
||||||
|
|
||||||
func (c *CacheFile) FakeIPReset() error {
|
func (c *CacheFile) FakeIPReset() error {
|
||||||
return c.DB.Batch(func(tx *bbolt.Tx) error {
|
return c.DB.Batch(func(tx *bbolt.Tx) error {
|
||||||
return tx.DeleteBucket(bucketFakeIP)
|
err := tx.DeleteBucket(bucketFakeIP)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = tx.DeleteBucket(bucketFakeIPDomain4)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return tx.DeleteBucket(bucketFakeIPDomain6)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
F "github.com/sagernet/sing/common/format"
|
F "github.com/sagernet/sing/common/format"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
"github.com/sagernet/sing/service"
|
||||||
"github.com/sagernet/sing/service/filemanager"
|
"github.com/sagernet/sing/service/filemanager"
|
||||||
"github.com/sagernet/websocket"
|
"github.com/sagernet/websocket"
|
||||||
|
|
||||||
@ -68,13 +69,16 @@ func NewServer(ctx context.Context, router adapter.Router, logFactory log.Observ
|
|||||||
Handler: chiRouter,
|
Handler: chiRouter,
|
||||||
},
|
},
|
||||||
trafficManager: trafficManager,
|
trafficManager: trafficManager,
|
||||||
urlTestHistory: urltest.NewHistoryStorage(),
|
|
||||||
mode: strings.ToLower(options.DefaultMode),
|
mode: strings.ToLower(options.DefaultMode),
|
||||||
storeSelected: options.StoreSelected,
|
storeSelected: options.StoreSelected,
|
||||||
storeFakeIP: options.StoreFakeIP,
|
storeFakeIP: options.StoreFakeIP,
|
||||||
externalUIDownloadURL: options.ExternalUIDownloadURL,
|
externalUIDownloadURL: options.ExternalUIDownloadURL,
|
||||||
externalUIDownloadDetour: options.ExternalUIDownloadDetour,
|
externalUIDownloadDetour: options.ExternalUIDownloadDetour,
|
||||||
}
|
}
|
||||||
|
server.urlTestHistory = service.PtrFromContext[urltest.HistoryStorage](ctx)
|
||||||
|
if server.urlTestHistory == nil {
|
||||||
|
server.urlTestHistory = urltest.NewHistoryStorage()
|
||||||
|
}
|
||||||
if server.mode == "" {
|
if server.mode == "" {
|
||||||
server.mode = "rule"
|
server.mode = "rule"
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,9 @@ package libbox
|
|||||||
const (
|
const (
|
||||||
CommandLog int32 = iota
|
CommandLog int32 = iota
|
||||||
CommandStatus
|
CommandStatus
|
||||||
CommandServiceStop
|
|
||||||
CommandServiceReload
|
CommandServiceReload
|
||||||
CommandCloseConnections
|
CommandCloseConnections
|
||||||
|
CommandGroup
|
||||||
|
CommandSelectOutbound
|
||||||
|
CommandURLTest
|
||||||
)
|
)
|
||||||
|
@ -26,6 +26,13 @@ type CommandClientHandler interface {
|
|||||||
Disconnected(message string)
|
Disconnected(message string)
|
||||||
WriteLog(message string)
|
WriteLog(message string)
|
||||||
WriteStatus(message *StatusMessage)
|
WriteStatus(message *StatusMessage)
|
||||||
|
WriteGroups(message OutboundGroupIterator)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStandaloneCommandClient(sharedDirectory string) *CommandClient {
|
||||||
|
return &CommandClient{
|
||||||
|
sharedDirectory: sharedDirectory,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCommandClient(sharedDirectory string, handler CommandClientHandler, options *CommandClientOptions) *CommandClient {
|
func NewCommandClient(sharedDirectory string, handler CommandClientHandler, options *CommandClientOptions) *CommandClient {
|
||||||
@ -36,16 +43,16 @@ func NewCommandClient(sharedDirectory string, handler CommandClientHandler, opti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func clientConnect(sharedDirectory string) (net.Conn, error) {
|
func (c *CommandClient) directConnect() (net.Conn, error) {
|
||||||
return net.DialUnix("unix", nil, &net.UnixAddr{
|
return net.DialUnix("unix", nil, &net.UnixAddr{
|
||||||
Name: filepath.Join(sharedDirectory, "command.sock"),
|
Name: filepath.Join(c.sharedDirectory, "command.sock"),
|
||||||
Net: "unix",
|
Net: "unix",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CommandClient) Connect() error {
|
func (c *CommandClient) Connect() error {
|
||||||
common.Close(c.conn)
|
common.Close(c.conn)
|
||||||
conn, err := clientConnect(c.sharedDirectory)
|
conn, err := c.directConnect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -65,6 +72,13 @@ func (c *CommandClient) Connect() error {
|
|||||||
}
|
}
|
||||||
c.handler.Connected()
|
c.handler.Connected()
|
||||||
go c.handleStatusConn(conn)
|
go c.handleStatusConn(conn)
|
||||||
|
case CommandGroup:
|
||||||
|
err = binary.Write(conn, binary.BigEndian, c.options.StatusInterval)
|
||||||
|
if err != nil {
|
||||||
|
return E.Cause(err, "write interval")
|
||||||
|
}
|
||||||
|
c.handler.Connected()
|
||||||
|
go c.handleGroupConn(conn)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,8 @@ import (
|
|||||||
"github.com/sagernet/sing-box/common/dialer/conntrack"
|
"github.com/sagernet/sing-box/common/dialer/conntrack"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ClientCloseConnections(sharedDirectory string) error {
|
func (c *CommandClient) CloseConnections() error {
|
||||||
conn, err := clientConnect(sharedDirectory)
|
conn, err := c.directConnect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
228
experimental/libbox/command_group.go
Normal file
228
experimental/libbox/command_group.go
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
package libbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/common/urltest"
|
||||||
|
"github.com/sagernet/sing-box/outbound"
|
||||||
|
"github.com/sagernet/sing/common/rw"
|
||||||
|
"github.com/sagernet/sing/service"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OutboundGroup struct {
|
||||||
|
Tag string
|
||||||
|
Type string
|
||||||
|
Selectable bool
|
||||||
|
Selected string
|
||||||
|
items []*OutboundGroupItem
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *OutboundGroup) GetItems() OutboundGroupItemIterator {
|
||||||
|
return newIterator(g.items)
|
||||||
|
}
|
||||||
|
|
||||||
|
type OutboundGroupIterator interface {
|
||||||
|
Next() *OutboundGroup
|
||||||
|
HasNext() bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type OutboundGroupItem struct {
|
||||||
|
Tag string
|
||||||
|
Type string
|
||||||
|
URLTestTime int64
|
||||||
|
URLTestDelay int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type OutboundGroupItemIterator interface {
|
||||||
|
Next() *OutboundGroupItem
|
||||||
|
HasNext() bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CommandClient) handleGroupConn(conn net.Conn) {
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
for {
|
||||||
|
groups, err := readGroups(conn)
|
||||||
|
if err != nil {
|
||||||
|
c.handler.Disconnected(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.handler.WriteGroups(groups)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CommandServer) handleGroupConn(conn net.Conn) error {
|
||||||
|
defer conn.Close()
|
||||||
|
ctx := connKeepAlive(conn)
|
||||||
|
for {
|
||||||
|
service := s.service
|
||||||
|
if service != nil {
|
||||||
|
err := writeGroups(conn, service)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err := binary.Write(conn, binary.BigEndian, uint16(0))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
case <-s.urlTestUpdate:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func readGroups(reader io.Reader) (OutboundGroupIterator, error) {
|
||||||
|
var groupLength uint16
|
||||||
|
err := binary.Read(reader, binary.BigEndian, &groupLength)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
groups := make([]*OutboundGroup, 0, groupLength)
|
||||||
|
for i := 0; i < int(groupLength); i++ {
|
||||||
|
var group OutboundGroup
|
||||||
|
group.Tag, err = rw.ReadVString(reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
group.Type, err = rw.ReadVString(reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = binary.Read(reader, binary.BigEndian, &group.Selectable)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
group.Selected, err = rw.ReadVString(reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var itemLength uint16
|
||||||
|
err = binary.Read(reader, binary.BigEndian, &itemLength)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
group.items = make([]*OutboundGroupItem, itemLength)
|
||||||
|
for j := 0; j < int(itemLength); j++ {
|
||||||
|
var item OutboundGroupItem
|
||||||
|
item.Tag, err = rw.ReadVString(reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
item.Type, err = rw.ReadVString(reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = binary.Read(reader, binary.BigEndian, &item.URLTestTime)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = binary.Read(reader, binary.BigEndian, &item.URLTestDelay)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
group.items[j] = &item
|
||||||
|
}
|
||||||
|
groups = append(groups, &group)
|
||||||
|
}
|
||||||
|
return newIterator(groups), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeGroups(writer io.Writer, boxService *BoxService) error {
|
||||||
|
historyStorage := service.PtrFromContext[urltest.HistoryStorage](boxService.ctx)
|
||||||
|
|
||||||
|
outbounds := boxService.instance.Router().Outbounds()
|
||||||
|
var iGroups []adapter.OutboundGroup
|
||||||
|
for _, it := range outbounds {
|
||||||
|
if group, isGroup := it.(adapter.OutboundGroup); isGroup {
|
||||||
|
iGroups = append(iGroups, group)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var groups []OutboundGroup
|
||||||
|
for _, iGroup := range iGroups {
|
||||||
|
var group OutboundGroup
|
||||||
|
group.Tag = iGroup.Tag()
|
||||||
|
group.Type = iGroup.Type()
|
||||||
|
_, group.Selectable = iGroup.(*outbound.Selector)
|
||||||
|
group.Selected = iGroup.Now()
|
||||||
|
|
||||||
|
for _, itemTag := range iGroup.All() {
|
||||||
|
itemOutbound, isLoaded := boxService.instance.Router().Outbound(itemTag)
|
||||||
|
if !isLoaded {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var item OutboundGroupItem
|
||||||
|
item.Tag = itemTag
|
||||||
|
item.Type = itemOutbound.Type()
|
||||||
|
if history := historyStorage.LoadURLTestHistory(adapter.OutboundTag(itemOutbound)); history != nil {
|
||||||
|
item.URLTestTime = history.Time.Unix()
|
||||||
|
item.URLTestDelay = int32(history.Delay)
|
||||||
|
}
|
||||||
|
group.items = append(group.items, &item)
|
||||||
|
}
|
||||||
|
groups = append(groups, group)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := binary.Write(writer, binary.BigEndian, uint16(len(groups)))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, group := range groups {
|
||||||
|
err = rw.WriteVString(writer, group.Tag)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = rw.WriteVString(writer, group.Type)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = binary.Write(writer, binary.BigEndian, group.Selectable)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = rw.WriteVString(writer, group.Selected)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = binary.Write(writer, binary.BigEndian, uint16(len(group.items)))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, item := range group.items {
|
||||||
|
err = rw.WriteVString(writer, item.Tag)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = rw.WriteVString(writer, item.Type)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = binary.Write(writer, binary.BigEndian, item.URLTestTime)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = binary.Write(writer, binary.BigEndian, item.URLTestDelay)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -11,7 +11,7 @@ func (s *CommandServer) WriteMessage(message string) {
|
|||||||
s.subscriber.Emit(message)
|
s.subscriber.Emit(message)
|
||||||
s.access.Lock()
|
s.access.Lock()
|
||||||
s.savedLines.PushBack(message)
|
s.savedLines.PushBack(message)
|
||||||
if s.savedLines.Len() > 100 {
|
if s.savedLines.Len() > s.maxLines {
|
||||||
s.savedLines.Remove(s.savedLines.Front())
|
s.savedLines.Remove(s.savedLines.Front())
|
||||||
}
|
}
|
||||||
s.access.Unlock()
|
s.access.Unlock()
|
||||||
|
@ -8,8 +8,8 @@ import (
|
|||||||
"github.com/sagernet/sing/common/rw"
|
"github.com/sagernet/sing/common/rw"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ClientServiceReload(sharedDirectory string) error {
|
func (c *CommandClient) ServiceReload() error {
|
||||||
conn, err := clientConnect(sharedDirectory)
|
conn, err := c.directConnect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
59
experimental/libbox/command_select.go
Normal file
59
experimental/libbox/command_select.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package libbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/outbound"
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
"github.com/sagernet/sing/common/rw"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *CommandClient) SelectOutbound(groupTag string, outboundTag string) error {
|
||||||
|
conn, err := c.directConnect()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
err = binary.Write(conn, binary.BigEndian, uint8(CommandSelectOutbound))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = rw.WriteVString(conn, groupTag)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = rw.WriteVString(conn, outboundTag)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return readError(conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CommandServer) handleSelectOutbound(conn net.Conn) error {
|
||||||
|
defer conn.Close()
|
||||||
|
groupTag, err := rw.ReadVString(conn)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
outboundTag, err := rw.ReadVString(conn)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
service := s.service
|
||||||
|
if service == nil {
|
||||||
|
return writeError(conn, E.New("service not ready"))
|
||||||
|
}
|
||||||
|
outboundGroup, isLoaded := service.instance.Router().Outbound(groupTag)
|
||||||
|
if !isLoaded {
|
||||||
|
return writeError(conn, E.New("selector not found: ", groupTag))
|
||||||
|
}
|
||||||
|
selector, isSelector := outboundGroup.(*outbound.Selector)
|
||||||
|
if !isSelector {
|
||||||
|
return writeError(conn, E.New("outbound is not a selector: ", groupTag))
|
||||||
|
}
|
||||||
|
if !selector.SelectOutbound(outboundTag) {
|
||||||
|
return writeError(conn, E.New("outbound not found in selector: ", outboundTag))
|
||||||
|
}
|
||||||
|
return writeError(conn, nil)
|
||||||
|
}
|
@ -7,12 +7,14 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/common/urltest"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
"github.com/sagernet/sing/common/debug"
|
"github.com/sagernet/sing/common/debug"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
"github.com/sagernet/sing/common/observable"
|
"github.com/sagernet/sing/common/observable"
|
||||||
"github.com/sagernet/sing/common/x/list"
|
"github.com/sagernet/sing/common/x/list"
|
||||||
|
"github.com/sagernet/sing/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CommandServer struct {
|
type CommandServer struct {
|
||||||
@ -22,26 +24,51 @@ type CommandServer struct {
|
|||||||
|
|
||||||
access sync.Mutex
|
access sync.Mutex
|
||||||
savedLines *list.List[string]
|
savedLines *list.List[string]
|
||||||
|
maxLines int
|
||||||
subscriber *observable.Subscriber[string]
|
subscriber *observable.Subscriber[string]
|
||||||
observer *observable.Observer[string]
|
observer *observable.Observer[string]
|
||||||
|
service *BoxService
|
||||||
|
|
||||||
|
urlTestListener *list.Element[func()]
|
||||||
|
urlTestUpdate chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
type CommandServerHandler interface {
|
type CommandServerHandler interface {
|
||||||
ServiceStop() error
|
|
||||||
ServiceReload() error
|
ServiceReload() error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCommandServer(sharedDirectory string, handler CommandServerHandler) *CommandServer {
|
func NewCommandServer(sharedDirectory string, handler CommandServerHandler, maxLines int32) *CommandServer {
|
||||||
server := &CommandServer{
|
server := &CommandServer{
|
||||||
sockPath: filepath.Join(sharedDirectory, "command.sock"),
|
sockPath: filepath.Join(sharedDirectory, "command.sock"),
|
||||||
handler: handler,
|
handler: handler,
|
||||||
savedLines: new(list.List[string]),
|
savedLines: new(list.List[string]),
|
||||||
|
maxLines: int(maxLines),
|
||||||
subscriber: observable.NewSubscriber[string](128),
|
subscriber: observable.NewSubscriber[string](128),
|
||||||
|
urlTestUpdate: make(chan struct{}, 1),
|
||||||
}
|
}
|
||||||
server.observer = observable.NewObserver[string](server.subscriber, 64)
|
server.observer = observable.NewObserver[string](server.subscriber, 64)
|
||||||
return server
|
return server
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *CommandServer) SetService(newService *BoxService) {
|
||||||
|
if s.service != nil && s.listener != nil {
|
||||||
|
service.PtrFromContext[urltest.HistoryStorage](s.service.ctx).RemoveListener(s.urlTestListener)
|
||||||
|
s.urlTestListener = nil
|
||||||
|
}
|
||||||
|
s.service = newService
|
||||||
|
if newService != nil {
|
||||||
|
s.urlTestListener = service.PtrFromContext[urltest.HistoryStorage](newService.ctx).AddListener(s.notifyURLTestUpdate)
|
||||||
|
}
|
||||||
|
s.notifyURLTestUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CommandServer) notifyURLTestUpdate() {
|
||||||
|
select {
|
||||||
|
case s.urlTestUpdate <- struct{}{}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *CommandServer) Start() error {
|
func (s *CommandServer) Start() error {
|
||||||
os.Remove(s.sockPath)
|
os.Remove(s.sockPath)
|
||||||
listener, err := net.ListenUnix("unix", &net.UnixAddr{
|
listener, err := net.ListenUnix("unix", &net.UnixAddr{
|
||||||
@ -92,12 +119,16 @@ func (s *CommandServer) handleConnection(conn net.Conn) error {
|
|||||||
return s.handleLogConn(conn)
|
return s.handleLogConn(conn)
|
||||||
case CommandStatus:
|
case CommandStatus:
|
||||||
return s.handleStatusConn(conn)
|
return s.handleStatusConn(conn)
|
||||||
case CommandServiceStop:
|
|
||||||
return s.handleServiceStop(conn)
|
|
||||||
case CommandServiceReload:
|
case CommandServiceReload:
|
||||||
return s.handleServiceReload(conn)
|
return s.handleServiceReload(conn)
|
||||||
case CommandCloseConnections:
|
case CommandCloseConnections:
|
||||||
return s.handleCloseConnections(conn)
|
return s.handleCloseConnections(conn)
|
||||||
|
case CommandGroup:
|
||||||
|
return s.handleGroupConn(conn)
|
||||||
|
case CommandSelectOutbound:
|
||||||
|
return s.handleSelectOutbound(conn)
|
||||||
|
case CommandURLTest:
|
||||||
|
return s.handleURLTest(conn)
|
||||||
default:
|
default:
|
||||||
return E.New("unknown command: ", command)
|
return E.New("unknown command: ", command)
|
||||||
}
|
}
|
||||||
|
39
experimental/libbox/command_shared.go
Normal file
39
experimental/libbox/command_shared.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package libbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
"github.com/sagernet/sing/common/rw"
|
||||||
|
)
|
||||||
|
|
||||||
|
func readError(reader io.Reader) error {
|
||||||
|
var hasError bool
|
||||||
|
err := binary.Read(reader, binary.BigEndian, &hasError)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if hasError {
|
||||||
|
errorMessage, err := rw.ReadVString(reader)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return E.New(errorMessage)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeError(writer io.Writer, wErr error) error {
|
||||||
|
err := binary.Write(writer, binary.BigEndian, wErr != nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if wErr != nil {
|
||||||
|
err = rw.WriteVString(writer, wErr.Error())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -1,48 +0,0 @@
|
|||||||
package libbox
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"net"
|
|
||||||
"runtime/debug"
|
|
||||||
|
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
|
||||||
"github.com/sagernet/sing/common/rw"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ClientServiceStop(sharedDirectory string) error {
|
|
||||||
conn, err := clientConnect(sharedDirectory)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
err = binary.Write(conn, binary.BigEndian, uint8(CommandServiceStop))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var hasError bool
|
|
||||||
err = binary.Read(conn, binary.BigEndian, &hasError)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if hasError {
|
|
||||||
errorMessage, err := rw.ReadVString(conn)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return E.New(errorMessage)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *CommandServer) handleServiceStop(conn net.Conn) error {
|
|
||||||
rErr := s.handler.ServiceStop()
|
|
||||||
err := binary.Write(conn, binary.BigEndian, rErr != nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if rErr != nil {
|
|
||||||
return rw.WriteVString(conn, rErr.Error())
|
|
||||||
}
|
|
||||||
debug.FreeOSMemory()
|
|
||||||
return nil
|
|
||||||
}
|
|
95
experimental/libbox/command_urltest.go
Normal file
95
experimental/libbox/command_urltest.go
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
package libbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/common/urltest"
|
||||||
|
"github.com/sagernet/sing-box/outbound"
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
|
"github.com/sagernet/sing/common/batch"
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
"github.com/sagernet/sing/common/rw"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *CommandClient) URLTest(groupTag string) error {
|
||||||
|
conn, err := c.directConnect()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
err = binary.Write(conn, binary.BigEndian, uint8(CommandURLTest))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = rw.WriteVString(conn, groupTag)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return readError(conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CommandServer) handleURLTest(conn net.Conn) error {
|
||||||
|
defer conn.Close()
|
||||||
|
groupTag, err := rw.ReadVString(conn)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
service := s.service
|
||||||
|
if service == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
abstractOutboundGroup, isLoaded := service.instance.Router().Outbound(groupTag)
|
||||||
|
if !isLoaded {
|
||||||
|
return writeError(conn, E.New("outbound group not found: ", groupTag))
|
||||||
|
}
|
||||||
|
outboundGroup, isOutboundGroup := abstractOutboundGroup.(adapter.OutboundGroup)
|
||||||
|
if !isOutboundGroup {
|
||||||
|
return writeError(conn, E.New("outbound is not a group: ", groupTag))
|
||||||
|
}
|
||||||
|
urlTest, isURLTest := abstractOutboundGroup.(*outbound.URLTest)
|
||||||
|
if isURLTest {
|
||||||
|
go urlTest.CheckOutbounds()
|
||||||
|
} else {
|
||||||
|
var historyStorage *urltest.HistoryStorage
|
||||||
|
if clashServer := service.instance.Router().ClashServer(); clashServer != nil {
|
||||||
|
historyStorage = clashServer.HistoryStorage()
|
||||||
|
} else {
|
||||||
|
return writeError(conn, E.New("Clash API is required for URLTest on non-URLTest group"))
|
||||||
|
}
|
||||||
|
|
||||||
|
outbounds := common.Filter(common.Map(outboundGroup.All(), func(it string) adapter.Outbound {
|
||||||
|
itOutbound, _ := service.instance.Router().Outbound(it)
|
||||||
|
return itOutbound
|
||||||
|
}), func(it adapter.Outbound) bool {
|
||||||
|
if it == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
_, isGroup := it.(adapter.OutboundGroup)
|
||||||
|
if isGroup {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
b, _ := batch.New(service.ctx, batch.WithConcurrencyNum[any](10))
|
||||||
|
for _, detour := range outbounds {
|
||||||
|
outboundToTest := detour
|
||||||
|
outboundTag := outboundToTest.Tag()
|
||||||
|
b.Go(outboundTag, func() (any, error) {
|
||||||
|
t, err := urltest.URLTest(service.ctx, "", outboundToTest)
|
||||||
|
if err != nil {
|
||||||
|
historyStorage.DeleteURLTestHistory(outboundTag)
|
||||||
|
} else {
|
||||||
|
historyStorage.StoreURLTestHistory(outboundTag, &urltest.History{
|
||||||
|
Time: time.Now(),
|
||||||
|
Delay: t,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return writeError(conn, nil)
|
||||||
|
}
|
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/sagernet/sing-box"
|
"github.com/sagernet/sing-box"
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/common/process"
|
"github.com/sagernet/sing-box/common/process"
|
||||||
|
"github.com/sagernet/sing-box/common/urltest"
|
||||||
"github.com/sagernet/sing-box/experimental/libbox/internal/procfs"
|
"github.com/sagernet/sing-box/experimental/libbox/internal/procfs"
|
||||||
"github.com/sagernet/sing-box/experimental/libbox/platform"
|
"github.com/sagernet/sing-box/experimental/libbox/platform"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
@ -16,6 +17,7 @@ import (
|
|||||||
"github.com/sagernet/sing/common/control"
|
"github.com/sagernet/sing/common/control"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
"github.com/sagernet/sing/service"
|
||||||
"github.com/sagernet/sing/service/filemanager"
|
"github.com/sagernet/sing/service/filemanager"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -32,6 +34,7 @@ func NewService(configContent string, platformInterface PlatformInterface) (*Box
|
|||||||
}
|
}
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
ctx = filemanager.WithDefault(ctx, sBasePath, sTempPath, sUserID, sGroupID)
|
ctx = filemanager.WithDefault(ctx, sBasePath, sTempPath, sUserID, sGroupID)
|
||||||
|
ctx = service.ContextWithPtr(ctx, urltest.NewHistoryStorage())
|
||||||
instance, err := box.New(box.Options{
|
instance, err := box.New(box.Options{
|
||||||
Context: ctx,
|
Context: ctx,
|
||||||
Options: options,
|
Options: options,
|
||||||
|
36
go.mod
36
go.mod
@ -4,7 +4,7 @@ go 1.18
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
berty.tech/go-libtor v1.0.385
|
berty.tech/go-libtor v1.0.385
|
||||||
github.com/Dreamacro/clash v1.16.0
|
github.com/Dreamacro/clash v1.17.0
|
||||||
github.com/caddyserver/certmagic v0.18.2
|
github.com/caddyserver/certmagic v0.18.2
|
||||||
github.com/cretz/bine v0.2.0
|
github.com/cretz/bine v0.2.0
|
||||||
github.com/dustin/go-humanize v1.0.1
|
github.com/dustin/go-humanize v1.0.1
|
||||||
@ -21,18 +21,18 @@ require (
|
|||||||
github.com/oschwald/maxminddb-golang v1.11.0
|
github.com/oschwald/maxminddb-golang v1.11.0
|
||||||
github.com/pires/go-proxyproto v0.7.0
|
github.com/pires/go-proxyproto v0.7.0
|
||||||
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0
|
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0
|
||||||
github.com/sagernet/gomobile v0.0.0-20230413023804-244d7ff07035
|
github.com/sagernet/gomobile v0.0.0-20230701084532-493ee2e45182
|
||||||
github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2
|
github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2
|
||||||
github.com/sagernet/quic-go v0.0.0-20230615020047-10f05c797c02
|
github.com/sagernet/quic-go v0.0.0-20230615020047-10f05c797c02
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
||||||
github.com/sagernet/sing v0.2.7
|
github.com/sagernet/sing v0.2.8-0.20230707055657-7c9b4d624da7
|
||||||
github.com/sagernet/sing-dns v0.1.6
|
github.com/sagernet/sing-dns v0.1.7-0.20230703131656-fd65b6178bf9
|
||||||
github.com/sagernet/sing-mux v0.1.0
|
github.com/sagernet/sing-mux v0.1.1-0.20230703132253-2cedde0fbc90
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.2
|
github.com/sagernet/sing-shadowsocks v0.2.3-0.20230703131347-b044960bd355
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.1.1
|
github.com/sagernet/sing-shadowsocks2 v0.1.2-0.20230703131506-ca0c6adde968
|
||||||
github.com/sagernet/sing-shadowtls v0.1.2
|
github.com/sagernet/sing-shadowtls v0.1.3-0.20230703132509-93bbad3057e4
|
||||||
github.com/sagernet/sing-tun v0.1.8
|
github.com/sagernet/sing-tun v0.1.9-0.20230703134424-fd850d00e5cd
|
||||||
github.com/sagernet/sing-vmess v0.1.6
|
github.com/sagernet/sing-vmess v0.1.7-0.20230711074224-7d2a9a318162
|
||||||
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37
|
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37
|
||||||
github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9
|
github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9
|
||||||
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2
|
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2
|
||||||
@ -43,19 +43,19 @@ require (
|
|||||||
go.etcd.io/bbolt v1.3.7
|
go.etcd.io/bbolt v1.3.7
|
||||||
go.uber.org/zap v1.24.0
|
go.uber.org/zap v1.24.0
|
||||||
go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35
|
go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35
|
||||||
golang.org/x/crypto v0.10.0
|
golang.org/x/crypto v0.11.0
|
||||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1
|
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df
|
||||||
golang.org/x/net v0.11.0
|
golang.org/x/net v0.12.0
|
||||||
golang.org/x/sys v0.9.0
|
golang.org/x/sys v0.10.0
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
|
||||||
google.golang.org/grpc v1.56.1
|
google.golang.org/grpc v1.56.2
|
||||||
google.golang.org/protobuf v1.30.0
|
google.golang.org/protobuf v1.31.0
|
||||||
)
|
)
|
||||||
|
|
||||||
//replace github.com/sagernet/sing => ../sing
|
//replace github.com/sagernet/sing => ../sing
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Dreamacro/protobytes v0.0.0-20230324064118-87bc784139cd // indirect
|
github.com/Dreamacro/protobytes v0.0.0-20230617041236-6500a9f4f158 // indirect
|
||||||
github.com/ajg/form v1.5.1 // indirect
|
github.com/ajg/form v1.5.1 // indirect
|
||||||
github.com/andybalholm/brotli v1.0.5 // indirect
|
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||||
github.com/cloudflare/circl v1.2.1-0.20221019164342-6ab4dfed8f3c // indirect
|
github.com/cloudflare/circl v1.2.1-0.20221019164342-6ab4dfed8f3c // indirect
|
||||||
@ -89,7 +89,7 @@ require (
|
|||||||
go.uber.org/atomic v1.11.0 // indirect
|
go.uber.org/atomic v1.11.0 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
golang.org/x/mod v0.11.0 // indirect
|
golang.org/x/mod v0.11.0 // indirect
|
||||||
golang.org/x/text v0.10.0 // indirect
|
golang.org/x/text v0.11.0 // indirect
|
||||||
golang.org/x/time v0.3.0 // indirect
|
golang.org/x/time v0.3.0 // indirect
|
||||||
golang.org/x/tools v0.10.0 // indirect
|
golang.org/x/tools v0.10.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
|
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
|
||||||
|
74
go.sum
74
go.sum
@ -1,9 +1,9 @@
|
|||||||
berty.tech/go-libtor v1.0.385 h1:RWK94C3hZj6Z2GdvePpHJLnWYobFr3bY/OdUJ5aoEXw=
|
berty.tech/go-libtor v1.0.385 h1:RWK94C3hZj6Z2GdvePpHJLnWYobFr3bY/OdUJ5aoEXw=
|
||||||
berty.tech/go-libtor v1.0.385/go.mod h1:9swOOQVb+kmvuAlsgWUK/4c52pm69AdbJsxLzk+fJEw=
|
berty.tech/go-libtor v1.0.385/go.mod h1:9swOOQVb+kmvuAlsgWUK/4c52pm69AdbJsxLzk+fJEw=
|
||||||
github.com/Dreamacro/clash v1.16.0 h1:Ve+8mvtsCv7ySa6f53/GOW6Tho0AFp5RNFsgQZFKcZs=
|
github.com/Dreamacro/clash v1.17.0 h1:LWtp6KcnrCiujY58ufI8pylI+hbCBgSCsLI90EWhpi4=
|
||||||
github.com/Dreamacro/clash v1.16.0/go.mod h1:ZM3UI2gqqUN7UL7L/F9aTHODTByya6sbC/WivQpaoJk=
|
github.com/Dreamacro/clash v1.17.0/go.mod h1:PtcAft7sdsK325BD6uwm8wvhOkMV3TCeED6dfZ/lnfE=
|
||||||
github.com/Dreamacro/protobytes v0.0.0-20230324064118-87bc784139cd h1:ygk7IF14j4ep4H2ZyeDe3IEoMZF8JdbX851RVVa/4D8=
|
github.com/Dreamacro/protobytes v0.0.0-20230617041236-6500a9f4f158 h1:JFnwKplz9hj8ubqYjm8HkgZS1Rvz9yW+u/XCNNTxr0k=
|
||||||
github.com/Dreamacro/protobytes v0.0.0-20230324064118-87bc784139cd/go.mod h1:QvmEZ/h6KXszPOr2wUFl7Zn3hfFNYdfbXwPVDTyZs6k=
|
github.com/Dreamacro/protobytes v0.0.0-20230617041236-6500a9f4f158/go.mod h1:QvmEZ/h6KXszPOr2wUFl7Zn3hfFNYdfbXwPVDTyZs6k=
|
||||||
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
|
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
|
||||||
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
|
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
|
||||||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||||
@ -104,8 +104,8 @@ github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0 h1:KyhtFFt
|
|||||||
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0/go.mod h1:D4SFEOkJK+4W1v86ZhX0jPM0rAL498fyQAChqMtes/I=
|
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0/go.mod h1:D4SFEOkJK+4W1v86ZhX0jPM0rAL498fyQAChqMtes/I=
|
||||||
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 h1:5+m7c6AkmAylhauulqN/c5dnh8/KssrE9c93TQrXldA=
|
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 h1:5+m7c6AkmAylhauulqN/c5dnh8/KssrE9c93TQrXldA=
|
||||||
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61/go.mod h1:QUQ4RRHD6hGGHdFMEtR8T2P6GS6R3D/CXKdaYHKKXms=
|
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61/go.mod h1:QUQ4RRHD6hGGHdFMEtR8T2P6GS6R3D/CXKdaYHKKXms=
|
||||||
github.com/sagernet/gomobile v0.0.0-20230413023804-244d7ff07035 h1:KttYh6bBhIw8Y6/Ljn7CGwC3CKZn788rzMJmeAKjY+8=
|
github.com/sagernet/gomobile v0.0.0-20230701084532-493ee2e45182 h1:sD5g92IO15RAX2DvA4Cq3Uc7tcgqNWVi8K3VTCI6sEo=
|
||||||
github.com/sagernet/gomobile v0.0.0-20230413023804-244d7ff07035/go.mod h1:5YE39YkJkCcMsfq1jMKkjsrM2GfBoF9JVWnvU89hmvU=
|
github.com/sagernet/gomobile v0.0.0-20230701084532-493ee2e45182/go.mod h1:5YE39YkJkCcMsfq1jMKkjsrM2GfBoF9JVWnvU89hmvU=
|
||||||
github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2 h1:dnkKrzapqtAwjTSWt6hdPrARORfoYvuUczynvRLrueo=
|
github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2 h1:dnkKrzapqtAwjTSWt6hdPrARORfoYvuUczynvRLrueo=
|
||||||
github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2/go.mod h1:1JUiV7nGuf++YFm9eWZ8q2lrwHmhcUGzptMl/vL1+LA=
|
github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2/go.mod h1:1JUiV7nGuf++YFm9eWZ8q2lrwHmhcUGzptMl/vL1+LA=
|
||||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
|
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
|
||||||
@ -116,22 +116,22 @@ github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byL
|
|||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
||||||
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||||
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
|
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
|
||||||
github.com/sagernet/sing v0.2.7 h1:cOy0FfPS8q7m0aJ51wS7LRQAGc9wF+fWhHtBDj99wy8=
|
github.com/sagernet/sing v0.2.8-0.20230707055657-7c9b4d624da7 h1:sKQu4Gc6vMfzleoFK3h8ROfn/TP2U36qQME3/iYaoqA=
|
||||||
github.com/sagernet/sing v0.2.7/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
|
github.com/sagernet/sing v0.2.8-0.20230707055657-7c9b4d624da7/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
|
||||||
github.com/sagernet/sing-dns v0.1.6 h1:qQRxmtUjCYkRLyzkTHpBvZQeAMeKpZwYsBOcs4U7gns=
|
github.com/sagernet/sing-dns v0.1.7-0.20230703131656-fd65b6178bf9 h1:35qe74ygIKj5uQkDDD0Xtv+iWOspQsS/Lqhs2XiY0Ak=
|
||||||
github.com/sagernet/sing-dns v0.1.6/go.mod h1:DY3LYJXIsM/kezUIJxf2TwBzqTTQAepi2KgazkDfahA=
|
github.com/sagernet/sing-dns v0.1.7-0.20230703131656-fd65b6178bf9/go.mod h1:wgmbh0yruJXRO8tmfwPx6hOl6pyReWRoeHdkRehWkmw=
|
||||||
github.com/sagernet/sing-mux v0.1.0 h1:xihlDRNs1J+hYwmvW9/ZmaghjDx7O0Y5dty0pOLQGB4=
|
github.com/sagernet/sing-mux v0.1.1-0.20230703132253-2cedde0fbc90 h1:aEe2HrRc9OTS7IZ8RHyh224OhltnwRQs4/y89UsHPo8=
|
||||||
github.com/sagernet/sing-mux v0.1.0/go.mod h1:i3jKjV4pRTFTV/ly5V3oa2JMPy0SAZ5X8X4tDU9Hw94=
|
github.com/sagernet/sing-mux v0.1.1-0.20230703132253-2cedde0fbc90/go.mod h1:sm126rB5EUi9HLf4jCSHTqo+XRPbh4BoEVeLbr2WRbE=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.2 h1:ezSdVhrmIcwDXmCZF3bOJVMuVtTQWpda+1Op+Ie2TA4=
|
github.com/sagernet/sing-shadowsocks v0.2.3-0.20230703131347-b044960bd355 h1:XOgNZYnkDrx5qtNS4kqIOHMhjZuc7mJ2pY/x3EyZX8Q=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.2/go.mod h1:JIBWG6a7orB2HxBxYElViQFLUQxFVG7DuqIj8gD7uCQ=
|
github.com/sagernet/sing-shadowsocks v0.2.3-0.20230703131347-b044960bd355/go.mod h1:atEATsxqPo8qCPcFt8Rw7TFEJ70egCoMR7PziX4jmjI=
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.1.1 h1:/cZteeSFXyHKg0uOparIFNj8hHrV8F2rRzTm8arpBTs=
|
github.com/sagernet/sing-shadowsocks2 v0.1.2-0.20230703131506-ca0c6adde968 h1:UctXygnZfqsFR+2hZXfpWK3pSYKLbBQMuli9GDE6QU0=
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.1.1/go.mod h1:p18C731ogLED66ZgC1SNYMOXAOxJIRwcTSUk73q/rsc=
|
github.com/sagernet/sing-shadowsocks2 v0.1.2-0.20230703131506-ca0c6adde968/go.mod h1:xFxUGbtnqRLxtQftCILFeKf43GE6S83f0I6CsO9BxGE=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.2 h1:wkPf4gF+cmaP0cIbArpyq+mc6GcwbMx60CssmmhEQ0s=
|
github.com/sagernet/sing-shadowtls v0.1.3-0.20230703132509-93bbad3057e4 h1:ZjLyCkEENqXzGp4PRZbQGk5wPzEq0Rg+/2jK82lmy3Q=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.2/go.mod h1:rTxhbSY8jGWZOWjdeOe1vP3E+hkgen8aRA2p7YccM88=
|
github.com/sagernet/sing-shadowtls v0.1.3-0.20230703132509-93bbad3057e4/go.mod h1:8ZSSHJSNOG7cUCUYJemZNH873EsKdFqABykTypoS/2M=
|
||||||
github.com/sagernet/sing-tun v0.1.8 h1:nc5mAdsYVB5TAv0UI0DaZJrd+sOv+HVf6V5B6XfJgSI=
|
github.com/sagernet/sing-tun v0.1.9-0.20230703134424-fd850d00e5cd h1:lkJA/P1L2XE5lNDnzA2fygx6DZIks3Sx87GN2OE0jNY=
|
||||||
github.com/sagernet/sing-tun v0.1.8/go.mod h1:Vj0AcDoneVIYMx8QujpXs2NQJ5Byc0FPhnRj5V3RGdo=
|
github.com/sagernet/sing-tun v0.1.9-0.20230703134424-fd850d00e5cd/go.mod h1:XNQoXtvsmeva+dADmo/57KktLNgm5ubOyR67Niahqj8=
|
||||||
github.com/sagernet/sing-vmess v0.1.6 h1:u9VhPNMP0u1vaEjWRWitJQ4KKYPhTF0rorpAlQZcFBg=
|
github.com/sagernet/sing-vmess v0.1.7-0.20230711074224-7d2a9a318162 h1:EvEbqAdZJalFqLwKSHIixH+TRed0iY2f8KatI7mtt1Q=
|
||||||
github.com/sagernet/sing-vmess v0.1.6/go.mod h1:XYXpk405G+kxRMNfREhROJsBxh1ccHy1v/fWSV5lx38=
|
github.com/sagernet/sing-vmess v0.1.7-0.20230711074224-7d2a9a318162/go.mod h1:FHEBboQRvfBDbZd/fAKBpgR4w7QbYyzNL/MLd22/iTk=
|
||||||
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as=
|
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as=
|
||||||
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37/go.mod h1:3skNSftZDJWTGVtVaM2jfbce8qHnmH/AGDRe62iNOg0=
|
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37/go.mod h1:3skNSftZDJWTGVtVaM2jfbce8qHnmH/AGDRe62iNOg0=
|
||||||
github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 h1:2ItpW1nMNkPzmBTxV0/eClCklHrFSQMnUGcpUmJxVeE=
|
github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 h1:2ItpW1nMNkPzmBTxV0/eClCklHrFSQMnUGcpUmJxVeE=
|
||||||
@ -171,16 +171,16 @@ go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35 h1:nJAwRlGWZZDOD+6wni9KVUNHMpH
|
|||||||
go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35/go.mod h1:TQvodOM+hJTioNQJilmLXu08JNb8i+ccq418+KWu1/Y=
|
go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35/go.mod h1:TQvodOM+hJTioNQJilmLXu08JNb8i+ccq418+KWu1/Y=
|
||||||
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||||
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
|
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
|
||||||
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
||||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
|
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME=
|
||||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
|
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
||||||
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
|
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
|
||||||
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU=
|
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
|
||||||
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
|
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||||
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@ -192,14 +192,14 @@ golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
|
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
|
||||||
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28=
|
golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
|
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
|
||||||
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
@ -210,12 +210,12 @@ golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 h1:CawjfCvY
|
|||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80=
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80=
|
||||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
|
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
|
||||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
|
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
|
||||||
google.golang.org/grpc v1.56.1 h1:z0dNfjIl0VpaZ9iSVjA6daGatAYwPGstTjt5vkRMFkQ=
|
google.golang.org/grpc v1.56.2 h1:fVRFRnXvU+x6C4IlHZewvJOVHoOv1TUuQyoRsYnB4bI=
|
||||||
google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
|
google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
@ -38,9 +38,7 @@ func (a *myInboundAdapter) ListenUDP() (net.PacketConn, error) {
|
|||||||
|
|
||||||
func (a *myInboundAdapter) loopUDPIn() {
|
func (a *myInboundAdapter) loopUDPIn() {
|
||||||
defer close(a.packetOutboundClosed)
|
defer close(a.packetOutboundClosed)
|
||||||
_buffer := buf.StackNewPacket()
|
buffer := buf.NewPacket()
|
||||||
defer common.KeepAlive(_buffer)
|
|
||||||
buffer := common.Dup(_buffer)
|
|
||||||
defer buffer.Release()
|
defer buffer.Release()
|
||||||
buffer.IncRef()
|
buffer.IncRef()
|
||||||
defer buffer.DecRef()
|
defer buffer.DecRef()
|
||||||
@ -67,9 +65,7 @@ func (a *myInboundAdapter) loopUDPIn() {
|
|||||||
|
|
||||||
func (a *myInboundAdapter) loopUDPOOBIn() {
|
func (a *myInboundAdapter) loopUDPOOBIn() {
|
||||||
defer close(a.packetOutboundClosed)
|
defer close(a.packetOutboundClosed)
|
||||||
_buffer := buf.StackNewPacket()
|
buffer := buf.NewPacket()
|
||||||
defer common.KeepAlive(_buffer)
|
|
||||||
buffer := common.Dup(_buffer)
|
|
||||||
defer buffer.Release()
|
defer buffer.Release()
|
||||||
buffer.IncRef()
|
buffer.IncRef()
|
||||||
defer buffer.DecRef()
|
defer buffer.DecRef()
|
||||||
|
@ -283,6 +283,7 @@ func (h *Hysteria) acceptStream(ctx context.Context, conn quic.Connection, strea
|
|||||||
metadata.Source = M.SocksaddrFromNet(conn.RemoteAddr()).Unwrap()
|
metadata.Source = M.SocksaddrFromNet(conn.RemoteAddr()).Unwrap()
|
||||||
metadata.OriginDestination = M.SocksaddrFromNet(conn.LocalAddr()).Unwrap()
|
metadata.OriginDestination = M.SocksaddrFromNet(conn.LocalAddr()).Unwrap()
|
||||||
metadata.Destination = M.ParseSocksaddrHostPort(request.Host, request.Port).Unwrap()
|
metadata.Destination = M.ParseSocksaddrHostPort(request.Host, request.Port).Unwrap()
|
||||||
|
metadata.User, _ = auth.UserFromContext[string](ctx)
|
||||||
|
|
||||||
if !request.UDP {
|
if !request.UDP {
|
||||||
err = hysteria.WriteServerResponse(stream, hysteria.ServerResponse{
|
err = hysteria.WriteServerResponse(stream, hysteria.ServerResponse{
|
||||||
@ -332,7 +333,7 @@ func (h *Hysteria) Close() error {
|
|||||||
h.udpAccess.Unlock()
|
h.udpAccess.Unlock()
|
||||||
return common.Close(
|
return common.Close(
|
||||||
&h.myInboundAdapter,
|
&h.myInboundAdapter,
|
||||||
h.listener,
|
common.PtrOrNil(h.listener),
|
||||||
h.tlsConfig,
|
h.tlsConfig,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -270,9 +270,7 @@ func (c *naiveH1Conn) read(p []byte) (n int, err error) {
|
|||||||
if len(p) >= 3 {
|
if len(p) >= 3 {
|
||||||
paddingHdr = p[:3]
|
paddingHdr = p[:3]
|
||||||
} else {
|
} else {
|
||||||
_paddingHdr := make([]byte, 3)
|
paddingHdr = make([]byte, 3)
|
||||||
defer common.KeepAlive(_paddingHdr)
|
|
||||||
paddingHdr = common.Dup(_paddingHdr)
|
|
||||||
}
|
}
|
||||||
_, err = io.ReadFull(c.Conn, paddingHdr)
|
_, err = io.ReadFull(c.Conn, paddingHdr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -320,9 +318,7 @@ func (c *naiveH1Conn) write(p []byte) (n int, err error) {
|
|||||||
if c.writePadding < kFirstPaddings {
|
if c.writePadding < kFirstPaddings {
|
||||||
paddingSize := rand.Intn(256)
|
paddingSize := rand.Intn(256)
|
||||||
|
|
||||||
_buffer := buf.StackNewSize(3 + len(p) + paddingSize)
|
buffer := buf.NewSize(3 + len(p) + paddingSize)
|
||||||
defer common.KeepAlive(_buffer)
|
|
||||||
buffer := common.Dup(_buffer)
|
|
||||||
defer buffer.Release()
|
defer buffer.Release()
|
||||||
header := buffer.Extend(3)
|
header := buffer.Extend(3)
|
||||||
binary.BigEndian.PutUint16(header, uint16(len(p)))
|
binary.BigEndian.PutUint16(header, uint16(len(p)))
|
||||||
@ -449,9 +445,7 @@ func (c *naiveH2Conn) read(p []byte) (n int, err error) {
|
|||||||
if len(p) >= 3 {
|
if len(p) >= 3 {
|
||||||
paddingHdr = p[:3]
|
paddingHdr = p[:3]
|
||||||
} else {
|
} else {
|
||||||
_paddingHdr := make([]byte, 3)
|
paddingHdr = make([]byte, 3)
|
||||||
defer common.KeepAlive(_paddingHdr)
|
|
||||||
paddingHdr = common.Dup(_paddingHdr)
|
|
||||||
}
|
}
|
||||||
_, err = io.ReadFull(c.reader, paddingHdr)
|
_, err = io.ReadFull(c.reader, paddingHdr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -502,9 +496,7 @@ func (c *naiveH2Conn) write(p []byte) (n int, err error) {
|
|||||||
if c.writePadding < kFirstPaddings {
|
if c.writePadding < kFirstPaddings {
|
||||||
paddingSize := rand.Intn(256)
|
paddingSize := rand.Intn(256)
|
||||||
|
|
||||||
_buffer := buf.StackNewSize(3 + len(p) + paddingSize)
|
buffer := buf.NewSize(3 + len(p) + paddingSize)
|
||||||
defer common.KeepAlive(_buffer)
|
|
||||||
buffer := common.Dup(_buffer)
|
|
||||||
defer buffer.Release()
|
defer buffer.Release()
|
||||||
header := buffer.Extend(3)
|
header := buffer.Extend(3)
|
||||||
binary.BigEndian.PutUint16(header, uint16(len(p)))
|
binary.BigEndian.PutUint16(header, uint16(len(p)))
|
||||||
|
@ -26,6 +26,7 @@ func NewFactory(formatter Formatter, writer io.Writer, platformWriter io.Writer)
|
|||||||
platformFormatter: Formatter{
|
platformFormatter: Formatter{
|
||||||
BaseTime: formatter.BaseTime,
|
BaseTime: formatter.BaseTime,
|
||||||
DisableColors: C.IsDarwin || C.IsIos,
|
DisableColors: C.IsDarwin || C.IsIos,
|
||||||
|
DisableLineBreak: true,
|
||||||
},
|
},
|
||||||
writer: writer,
|
writer: writer,
|
||||||
platformWriter: platformWriter,
|
platformWriter: platformWriter,
|
||||||
|
@ -17,6 +17,7 @@ type Formatter struct {
|
|||||||
DisableTimestamp bool
|
DisableTimestamp bool
|
||||||
FullTimestamp bool
|
FullTimestamp bool
|
||||||
TimestampFormat string
|
TimestampFormat string
|
||||||
|
DisableLineBreak bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f Formatter) Format(ctx context.Context, level Level, tag string, message string, timestamp time.Time) string {
|
func (f Formatter) Format(ctx context.Context, level Level, tag string, message string, timestamp time.Time) string {
|
||||||
@ -76,9 +77,15 @@ func (f Formatter) Format(ctx context.Context, level Level, tag string, message
|
|||||||
default:
|
default:
|
||||||
message = levelString + "[" + xd(int(timestamp.Sub(f.BaseTime)/time.Second), 4) + "] " + message
|
message = levelString + "[" + xd(int(timestamp.Sub(f.BaseTime)/time.Second), 4) + "] " + message
|
||||||
}
|
}
|
||||||
|
if f.DisableLineBreak {
|
||||||
|
if message[len(message)-1] == '\n' {
|
||||||
|
message = message[:len(message)-1]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if message[len(message)-1] != '\n' {
|
if message[len(message)-1] != '\n' {
|
||||||
message += "\n"
|
message += "\n"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return message
|
return message
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ func NewObservableFactory(formatter Formatter, writer io.Writer, platformWriter
|
|||||||
platformFormatter: Formatter{
|
platformFormatter: Formatter{
|
||||||
BaseTime: formatter.BaseTime,
|
BaseTime: formatter.BaseTime,
|
||||||
DisableColors: C.IsDarwin || C.IsIos,
|
DisableColors: C.IsDarwin || C.IsIos,
|
||||||
|
DisableLineBreak: true,
|
||||||
},
|
},
|
||||||
writer: writer,
|
writer: writer,
|
||||||
platformWriter: platformWriter,
|
platformWriter: platformWriter,
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
@ -112,8 +111,7 @@ func CopyEarlyConn(ctx context.Context, conn net.Conn, serverConn net.Conn) erro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if earlyConn, isEarlyConn := common.Cast[N.EarlyConn](serverConn); isEarlyConn && earlyConn.NeedHandshake() {
|
if earlyConn, isEarlyConn := common.Cast[N.EarlyConn](serverConn); isEarlyConn && earlyConn.NeedHandshake() {
|
||||||
_payload := buf.StackNew()
|
payload := buf.NewPacket()
|
||||||
payload := common.Dup(_payload)
|
|
||||||
err := conn.SetReadDeadline(time.Now().Add(C.ReadPayloadTimeout))
|
err := conn.SetReadDeadline(time.Now().Add(C.ReadPayloadTimeout))
|
||||||
if err != os.ErrInvalid {
|
if err != os.ErrInvalid {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -133,7 +131,6 @@ func CopyEarlyConn(ctx context.Context, conn net.Conn, serverConn net.Conn) erro
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return N.HandshakeFailure(conn, err)
|
return N.HandshakeFailure(conn, err)
|
||||||
}
|
}
|
||||||
runtime.KeepAlive(_payload)
|
|
||||||
payload.Release()
|
payload.Release()
|
||||||
}
|
}
|
||||||
return bufio.CopyConn(ctx, conn, serverConn)
|
return bufio.CopyConn(ctx, conn, serverConn)
|
||||||
|
@ -65,9 +65,7 @@ func (d *DNS) handleConnection(ctx context.Context, conn net.Conn, metadata adap
|
|||||||
if queryLength == 0 {
|
if queryLength == 0 {
|
||||||
return dns.RCodeFormatError
|
return dns.RCodeFormatError
|
||||||
}
|
}
|
||||||
_buffer := buf.StackNewSize(int(queryLength))
|
buffer := buf.NewSize(int(queryLength))
|
||||||
defer common.KeepAlive(_buffer)
|
|
||||||
buffer := common.Dup(_buffer)
|
|
||||||
defer buffer.Release()
|
defer buffer.Release()
|
||||||
_, err = buffer.ReadFullFrom(conn, int(queryLength))
|
_, err = buffer.ReadFullFrom(conn, int(queryLength))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -84,9 +82,7 @@ func (d *DNS) handleConnection(ctx context.Context, conn net.Conn, metadata adap
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_responseBuffer := buf.StackNewPacket()
|
responseBuffer := buf.NewPacket()
|
||||||
defer common.KeepAlive(_responseBuffer)
|
|
||||||
responseBuffer := common.Dup(_responseBuffer)
|
|
||||||
defer responseBuffer.Release()
|
defer responseBuffer.Release()
|
||||||
responseBuffer.Resize(2, 0)
|
responseBuffer.Resize(2, 0)
|
||||||
n, err := response.PackBuffer(responseBuffer.FreeBytes())
|
n, err := response.PackBuffer(responseBuffer.FreeBytes())
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
"github.com/sagernet/sing/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -74,7 +75,11 @@ func (s *URLTest) Start() error {
|
|||||||
outbounds = append(outbounds, detour)
|
outbounds = append(outbounds, detour)
|
||||||
}
|
}
|
||||||
s.group = NewURLTestGroup(s.ctx, s.router, s.logger, outbounds, s.link, s.interval, s.tolerance)
|
s.group = NewURLTestGroup(s.ctx, s.router, s.logger, outbounds, s.link, s.interval, s.tolerance)
|
||||||
go s.group.CheckOutbounds(false)
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *URLTest) PostStart() error {
|
||||||
|
go s.CheckOutbounds()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,6 +101,10 @@ func (s *URLTest) URLTest(ctx context.Context, link string) (map[string]uint16,
|
|||||||
return s.group.URLTest(ctx, link)
|
return s.group.URLTest(ctx, link)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *URLTest) CheckOutbounds() {
|
||||||
|
s.group.CheckOutbounds(true)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *URLTest) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
func (s *URLTest) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
s.group.Start()
|
s.group.Start()
|
||||||
outbound := s.group.Select(network)
|
outbound := s.group.Select(network)
|
||||||
@ -157,7 +166,8 @@ func NewURLTestGroup(ctx context.Context, router adapter.Router, logger log.Logg
|
|||||||
tolerance = 50
|
tolerance = 50
|
||||||
}
|
}
|
||||||
var history *urltest.HistoryStorage
|
var history *urltest.HistoryStorage
|
||||||
if clashServer := router.ClashServer(); clashServer != nil {
|
if history = service.PtrFromContext[urltest.HistoryStorage](ctx); history != nil {
|
||||||
|
} else if clashServer := router.ClashServer(); clashServer != nil {
|
||||||
history = clashServer.HistoryStorage()
|
history = clashServer.HistoryStorage()
|
||||||
} else {
|
} else {
|
||||||
history = urltest.NewHistoryStorage()
|
history = urltest.NewHistoryStorage()
|
||||||
|
@ -252,7 +252,7 @@ func NewRouter(
|
|||||||
if fakeIPOptions.Inet6Range != nil {
|
if fakeIPOptions.Inet6Range != nil {
|
||||||
inet6Range = fakeIPOptions.Inet6Range.Build()
|
inet6Range = fakeIPOptions.Inet6Range.Build()
|
||||||
}
|
}
|
||||||
router.fakeIPStore = fakeip.NewStore(router, inet4Range, inet6Range)
|
router.fakeIPStore = fakeip.NewStore(router, router.logger, inet4Range, inet6Range)
|
||||||
}
|
}
|
||||||
|
|
||||||
usePlatformDefaultInterfaceMonitor := platformInterface != nil && platformInterface.UsePlatformDefaultInterfaceMonitor()
|
usePlatformDefaultInterfaceMonitor := platformInterface != nil && platformInterface.UsePlatformDefaultInterfaceMonitor()
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box"
|
"github.com/sagernet/sing-box"
|
||||||
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
"github.com/sagernet/sing/common/bufio"
|
"github.com/sagernet/sing/common/bufio"
|
||||||
"github.com/sagernet/sing/common/debug"
|
"github.com/sagernet/sing/common/debug"
|
||||||
@ -105,10 +106,14 @@ func testSuitSimple1(t *testing.T, clientPort uint16, testPort uint16) {
|
|||||||
return dialer.ListenPacket(context.Background(), M.ParseSocksaddrHostPort("127.0.0.1", testPort))
|
return dialer.ListenPacket(context.Background(), M.ParseSocksaddrHostPort("127.0.0.1", testPort))
|
||||||
}
|
}
|
||||||
require.NoError(t, testPingPongWithConn(t, testPort, dialTCP))
|
require.NoError(t, testPingPongWithConn(t, testPort, dialTCP))
|
||||||
|
if !C.IsDarwin {
|
||||||
require.NoError(t, testPingPongWithPacketConn(t, testPort, dialUDP))
|
require.NoError(t, testPingPongWithPacketConn(t, testPort, dialUDP))
|
||||||
|
}
|
||||||
require.NoError(t, testPingPongWithConn(t, testPort, dialTCP))
|
require.NoError(t, testPingPongWithConn(t, testPort, dialTCP))
|
||||||
|
if !C.IsDarwin {
|
||||||
require.NoError(t, testLargeDataWithPacketConn(t, testPort, dialUDP))
|
require.NoError(t, testLargeDataWithPacketConn(t, testPort, dialUDP))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func testSuitWg(t *testing.T, clientPort uint16, testPort uint16) {
|
func testSuitWg(t *testing.T, clientPort uint16, testPort uint16) {
|
||||||
dialer := socks.NewClient(N.SystemDialer, M.ParseSocksaddrHostPort("127.0.0.1", clientPort), socks.Version5, "", "")
|
dialer := socks.NewClient(N.SystemDialer, M.ParseSocksaddrHostPort("127.0.0.1", clientPort), socks.Version5, "", "")
|
||||||
|
@ -8,7 +8,8 @@ import (
|
|||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestProxyProtocol(t *testing.T) {
|
// Since this is a feature one-off added by outsiders, I won't address these anymore.
|
||||||
|
func _TestProxyProtocol(t *testing.T) {
|
||||||
startInstance(t, option.Options{
|
startInstance(t, option.Options{
|
||||||
Inbounds: []option.Inbound{
|
Inbounds: []option.Inbound{
|
||||||
{
|
{
|
||||||
@ -38,7 +39,7 @@ func TestProxyProtocol(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: C.TypeDirect,
|
Type: C.TypeDirect,
|
||||||
Tag: "trojan-out",
|
Tag: "proxy-out",
|
||||||
DirectOptions: option.DirectOutboundOptions{
|
DirectOptions: option.DirectOutboundOptions{
|
||||||
OverrideAddress: "127.0.0.1",
|
OverrideAddress: "127.0.0.1",
|
||||||
OverridePort: serverPort,
|
OverridePort: serverPort,
|
||||||
@ -51,7 +52,7 @@ func TestProxyProtocol(t *testing.T) {
|
|||||||
{
|
{
|
||||||
DefaultOptions: option.DefaultRule{
|
DefaultOptions: option.DefaultRule{
|
||||||
Inbound: []string{"mixed-in"},
|
Inbound: []string{"mixed-in"},
|
||||||
Outbound: "trojan-out",
|
Outbound: "proxy-out",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
C "github.com/sagernet/sing-box/constant"
|
|
||||||
"github.com/sagernet/sing/common/debug"
|
"github.com/sagernet/sing/common/debug"
|
||||||
F "github.com/sagernet/sing/common/format"
|
F "github.com/sagernet/sing/common/format"
|
||||||
"github.com/sagernet/sing/common/rw"
|
"github.com/sagernet/sing/common/rw"
|
||||||
@ -54,9 +53,7 @@ func startDockerContainer(t *testing.T, options DockerOptions) {
|
|||||||
containerOptions.ExposedPorts = make(nat.PortSet)
|
containerOptions.ExposedPorts = make(nat.PortSet)
|
||||||
|
|
||||||
var hostOptions container.HostConfig
|
var hostOptions container.HostConfig
|
||||||
if !C.IsDarwin {
|
|
||||||
hostOptions.NetworkMode = "host"
|
hostOptions.NetworkMode = "host"
|
||||||
}
|
|
||||||
hostOptions.CapAdd = options.Cap
|
hostOptions.CapAdd = options.Cap
|
||||||
hostOptions.PortBindings = make(nat.PortMap)
|
hostOptions.PortBindings = make(nat.PortMap)
|
||||||
|
|
||||||
|
79
test/go.mod
79
test/go.mod
@ -10,21 +10,23 @@ require (
|
|||||||
github.com/docker/docker v20.10.18+incompatible
|
github.com/docker/docker v20.10.18+incompatible
|
||||||
github.com/docker/go-connections v0.4.0
|
github.com/docker/go-connections v0.4.0
|
||||||
github.com/gofrs/uuid/v5 v5.0.0
|
github.com/gofrs/uuid/v5 v5.0.0
|
||||||
github.com/sagernet/sing v0.2.4
|
github.com/sagernet/sing v0.2.8-0.20230707055657-7c9b4d624da7
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230417102954-f77257340507
|
github.com/sagernet/sing-shadowsocks v0.2.3-0.20230703131347-b044960bd355
|
||||||
|
github.com/sagernet/sing-shadowsocks2 v0.1.2-0.20230703131506-ca0c6adde968
|
||||||
github.com/spyzhov/ajson v0.7.1
|
github.com/spyzhov/ajson v0.7.1
|
||||||
github.com/stretchr/testify v1.8.2
|
github.com/stretchr/testify v1.8.4
|
||||||
go.uber.org/goleak v1.2.0
|
go.uber.org/goleak v1.2.0
|
||||||
golang.org/x/net v0.9.0
|
golang.org/x/net v0.12.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
berty.tech/go-libtor v1.0.385 // indirect
|
berty.tech/go-libtor v1.0.385 // indirect
|
||||||
github.com/Dreamacro/clash v1.15.0 // indirect
|
github.com/Dreamacro/clash v1.17.0 // indirect
|
||||||
|
github.com/Dreamacro/protobytes v0.0.0-20230617041236-6500a9f4f158 // indirect
|
||||||
github.com/Microsoft/go-winio v0.6.0 // indirect
|
github.com/Microsoft/go-winio v0.6.0 // indirect
|
||||||
github.com/ajg/form v1.5.1 // indirect
|
github.com/ajg/form v1.5.1 // indirect
|
||||||
github.com/andybalholm/brotli v1.0.5 // indirect
|
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||||
github.com/caddyserver/certmagic v0.17.2 // indirect
|
github.com/caddyserver/certmagic v0.18.2 // indirect
|
||||||
github.com/cloudflare/circl v1.2.1-0.20221019164342-6ab4dfed8f3c // indirect
|
github.com/cloudflare/circl v1.2.1-0.20221019164342-6ab4dfed8f3c // indirect
|
||||||
github.com/cretz/bine v0.2.0 // indirect
|
github.com/cretz/bine v0.2.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
@ -35,69 +37,72 @@ require (
|
|||||||
github.com/go-chi/chi/v5 v5.0.8 // indirect
|
github.com/go-chi/chi/v5 v5.0.8 // indirect
|
||||||
github.com/go-chi/cors v1.2.1 // indirect
|
github.com/go-chi/cors v1.2.1 // indirect
|
||||||
github.com/go-chi/render v1.0.2 // indirect
|
github.com/go-chi/render v1.0.2 // indirect
|
||||||
|
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/mock v1.6.0 // indirect
|
github.com/golang/protobuf v1.5.3 // indirect
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/google/btree v1.1.2 // indirect
|
||||||
github.com/google/btree v1.0.1 // indirect
|
|
||||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||||
github.com/hashicorp/yamux v0.1.1 // indirect
|
github.com/hashicorp/yamux v0.1.1 // indirect
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20230407062729-974c6f05fe16 // indirect
|
github.com/insomniacslk/dhcp v0.0.0-20230612134759-b20c9ba983df // indirect
|
||||||
github.com/josharian/native v1.1.0 // indirect
|
github.com/josharian/native v1.1.0 // indirect
|
||||||
github.com/klauspost/compress v1.15.15 // indirect
|
github.com/klauspost/compress v1.15.15 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.1.1 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
||||||
github.com/libdns/libdns v0.2.1 // indirect
|
github.com/libdns/libdns v0.2.1 // indirect
|
||||||
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
|
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
|
||||||
github.com/mholt/acmez v1.1.0 // indirect
|
github.com/mholt/acmez v1.2.0 // indirect
|
||||||
github.com/miekg/dns v1.1.53 // indirect
|
github.com/miekg/dns v1.1.55 // indirect
|
||||||
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect
|
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect
|
||||||
github.com/morikuni/aec v1.0.0 // indirect
|
github.com/morikuni/aec v1.0.0 // indirect
|
||||||
github.com/onsi/ginkgo/v2 v2.2.0 // indirect
|
github.com/onsi/ginkgo/v2 v2.2.0 // indirect
|
||||||
github.com/ooni/go-libtor v1.1.7 // indirect
|
github.com/ooni/go-libtor v1.1.8 // indirect
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/opencontainers/image-spec v1.0.2 // indirect
|
github.com/opencontainers/image-spec v1.0.2 // indirect
|
||||||
github.com/oschwald/maxminddb-golang v1.10.0 // indirect
|
github.com/oschwald/maxminddb-golang v1.11.0 // indirect
|
||||||
github.com/pierrec/lz4/v4 v4.1.14 // indirect
|
github.com/pierrec/lz4/v4 v4.1.14 // indirect
|
||||||
github.com/pires/go-proxyproto v0.7.0 // indirect
|
github.com/pires/go-proxyproto v0.7.0 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/quic-go/qpack v0.4.0 // indirect
|
github.com/quic-go/qpack v0.4.0 // indirect
|
||||||
github.com/quic-go/qtls-go1-18 v0.2.0 // indirect
|
github.com/quic-go/qtls-go1-18 v0.2.0 // indirect
|
||||||
github.com/quic-go/qtls-go1-19 v0.2.0 // indirect
|
github.com/quic-go/qtls-go1-19 v0.3.2 // indirect
|
||||||
github.com/quic-go/qtls-go1-20 v0.1.0 // indirect
|
github.com/quic-go/qtls-go1-20 v0.2.2 // indirect
|
||||||
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0 // indirect
|
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0 // indirect
|
||||||
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 // indirect
|
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 // indirect
|
||||||
|
github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2 // indirect
|
||||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
|
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
|
||||||
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32 // indirect
|
github.com/sagernet/quic-go v0.0.0-20230615020047-10f05c797c02 // indirect
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect
|
||||||
github.com/sagernet/sing-dns v0.1.5-0.20230415085626-111ecf799dfc // indirect
|
github.com/sagernet/sing-dns v0.1.7-0.20230703131656-fd65b6178bf9 // indirect
|
||||||
github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b // indirect
|
github.com/sagernet/sing-mux v0.1.1-0.20230703132253-2cedde0fbc90 // indirect
|
||||||
github.com/sagernet/sing-tun v0.1.5-0.20230422121432-209ec123ca7b // indirect
|
github.com/sagernet/sing-shadowtls v0.1.3-0.20230703132509-93bbad3057e4 // indirect
|
||||||
github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 // indirect
|
github.com/sagernet/sing-tun v0.1.9-0.20230703134424-fd850d00e5cd // indirect
|
||||||
|
github.com/sagernet/sing-vmess v0.1.7-0.20230711074224-7d2a9a318162 // indirect
|
||||||
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 // indirect
|
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 // indirect
|
||||||
github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 // indirect
|
github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 // indirect
|
||||||
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 // indirect
|
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 // indirect
|
||||||
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e // indirect
|
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e // indirect
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77 // indirect
|
github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77 // indirect
|
||||||
github.com/sirupsen/logrus v1.9.0 // indirect
|
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 // indirect
|
||||||
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect
|
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect
|
||||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
||||||
go.etcd.io/bbolt v1.3.7 // indirect
|
go.etcd.io/bbolt v1.3.7 // indirect
|
||||||
go.uber.org/atomic v1.10.0 // indirect
|
go.uber.org/atomic v1.11.0 // indirect
|
||||||
go.uber.org/multierr v1.6.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.uber.org/zap v1.24.0 // indirect
|
go.uber.org/zap v1.24.0 // indirect
|
||||||
go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35 // indirect
|
go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35 // indirect
|
||||||
golang.org/x/crypto v0.8.0 // indirect
|
golang.org/x/crypto v0.11.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect
|
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect
|
||||||
golang.org/x/mod v0.8.0 // indirect
|
golang.org/x/mod v0.11.0 // indirect
|
||||||
golang.org/x/sys v0.7.0 // indirect
|
golang.org/x/sys v0.10.0 // indirect
|
||||||
golang.org/x/text v0.9.0 // indirect
|
golang.org/x/text v0.11.0 // indirect
|
||||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
|
golang.org/x/time v0.3.0 // indirect
|
||||||
golang.org/x/tools v0.6.0 // indirect
|
golang.org/x/tools v0.10.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
|
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
|
||||||
google.golang.org/grpc v1.54.0 // indirect
|
google.golang.org/grpc v1.56.2 // indirect
|
||||||
google.golang.org/protobuf v1.30.0 // indirect
|
google.golang.org/protobuf v1.31.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
gvisor.dev/gvisor v0.0.0-20230415003630-3981d5d5e523 // indirect
|
gotest.tools/v3 v3.4.0 // indirect
|
||||||
lukechampine.com/blake3 v1.1.7 // indirect
|
lukechampine.com/blake3 v1.2.1 // indirect
|
||||||
)
|
)
|
||||||
|
177
test/go.sum
177
test/go.sum
@ -1,8 +1,10 @@
|
|||||||
berty.tech/go-libtor v1.0.385 h1:RWK94C3hZj6Z2GdvePpHJLnWYobFr3bY/OdUJ5aoEXw=
|
berty.tech/go-libtor v1.0.385 h1:RWK94C3hZj6Z2GdvePpHJLnWYobFr3bY/OdUJ5aoEXw=
|
||||||
berty.tech/go-libtor v1.0.385/go.mod h1:9swOOQVb+kmvuAlsgWUK/4c52pm69AdbJsxLzk+fJEw=
|
berty.tech/go-libtor v1.0.385/go.mod h1:9swOOQVb+kmvuAlsgWUK/4c52pm69AdbJsxLzk+fJEw=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
||||||
github.com/Dreamacro/clash v1.15.0 h1:mlpD950VEggXZBNahV66hyKDRxcczkj3vymoAt78KyE=
|
github.com/Dreamacro/clash v1.17.0 h1:LWtp6KcnrCiujY58ufI8pylI+hbCBgSCsLI90EWhpi4=
|
||||||
github.com/Dreamacro/clash v1.15.0/go.mod h1:WNH69bN11LiAdgdSr4hpkEuXVMfBbWyhEKMCTx9BtNE=
|
github.com/Dreamacro/clash v1.17.0/go.mod h1:PtcAft7sdsK325BD6uwm8wvhOkMV3TCeED6dfZ/lnfE=
|
||||||
|
github.com/Dreamacro/protobytes v0.0.0-20230617041236-6500a9f4f158 h1:JFnwKplz9hj8ubqYjm8HkgZS1Rvz9yW+u/XCNNTxr0k=
|
||||||
|
github.com/Dreamacro/protobytes v0.0.0-20230617041236-6500a9f4f158/go.mod h1:QvmEZ/h6KXszPOr2wUFl7Zn3hfFNYdfbXwPVDTyZs6k=
|
||||||
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
|
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
|
||||||
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
|
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
|
||||||
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
|
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
|
||||||
@ -10,8 +12,8 @@ github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY
|
|||||||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||||
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||||
github.com/caddyserver/certmagic v0.17.2 h1:o30seC1T/dBqBCNNGNHWwj2i5/I/FMjBbTAhjADP3nE=
|
github.com/caddyserver/certmagic v0.18.2 h1:Nj2+M+A2Ho9IF6n1wUSbra4mX1X6ALzWpul9HooprHA=
|
||||||
github.com/caddyserver/certmagic v0.17.2/go.mod h1:ouWUuC490GOLJzkyN35eXfV8bSbwMwSf4bdhkIxtdQE=
|
github.com/caddyserver/certmagic v0.18.2/go.mod h1:cLsgYXecH1iVUPjDXw15/1SKjZk/TK+aFfQk5FnugGQ=
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
@ -41,6 +43,8 @@ github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
|
|||||||
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
||||||
github.com/go-chi/render v1.0.2 h1:4ER/udB0+fMWB2Jlf15RV3F4A2FDuYi/9f+lFttR/Lg=
|
github.com/go-chi/render v1.0.2 h1:4ER/udB0+fMWB2Jlf15RV3F4A2FDuYi/9f+lFttR/Lg=
|
||||||
github.com/go-chi/render v1.0.2/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
|
github.com/go-chi/render v1.0.2/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
|
||||||
|
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||||
|
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M=
|
github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M=
|
||||||
@ -48,12 +52,11 @@ github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV
|
|||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
||||||
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
||||||
@ -61,8 +64,8 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLe
|
|||||||
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
|
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
|
||||||
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20230407062729-974c6f05fe16 h1:+aAGyK41KRn8jbF2Q7PLL0Sxwg6dShGcQSeCC7nZQ8E=
|
github.com/insomniacslk/dhcp v0.0.0-20230612134759-b20c9ba983df h1:pF1MMIzEJzJ/MyI4bXYXVYyN8CJgoQ2PPKT2z3O/Cl4=
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20230407062729-974c6f05fe16/go.mod h1:IKrnDWs3/Mqq5n0lI+RxA2sB7MvN/vbMBP3ehXg65UI=
|
github.com/insomniacslk/dhcp v0.0.0-20230612134759-b20c9ba983df/go.mod h1:7474bZ1YNCvarT6WFKie4kEET6J0KYRDC4XJqqXzQW4=
|
||||||
github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||||
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
||||||
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||||
@ -70,18 +73,17 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
|
|||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw=
|
github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw=
|
||||||
github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4=
|
github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
|
||||||
github.com/klauspost/cpuid/v2 v2.1.1 h1:t0wUqjowdm8ezddV5k0tLWVklVuvLJpoHeb4WBdydm0=
|
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||||
github.com/klauspost/cpuid/v2 v2.1.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis=
|
github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis=
|
||||||
github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
|
github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
|
||||||
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
|
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
|
||||||
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||||
github.com/mholt/acmez v1.1.0 h1:IQ9CGHKOHokorxnffsqDvmmE30mDenO1lptYZ1AYkHY=
|
github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30=
|
||||||
github.com/mholt/acmez v1.1.0/go.mod h1:zwo5+fbLLTowAX8o8ETfQzbDtwGEXnPhkmGdKIP+bgs=
|
github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
|
||||||
github.com/miekg/dns v1.1.53 h1:ZBkuHr5dxHtB1caEOlZTLPo7D3L3TWckgUUs/RHfDxw=
|
github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo=
|
||||||
github.com/miekg/dns v1.1.53/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
|
github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
|
||||||
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA=
|
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA=
|
||||||
github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||||
@ -90,14 +92,14 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb
|
|||||||
github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI=
|
github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI=
|
||||||
github.com/onsi/ginkgo/v2 v2.2.0/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
|
github.com/onsi/ginkgo/v2 v2.2.0/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
|
||||||
github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
|
github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
|
||||||
github.com/ooni/go-libtor v1.1.7 h1:ooVcdEPBqDox5OfeXAfXIeQFCbqMLJVfIpO+Irr7N9A=
|
github.com/ooni/go-libtor v1.1.8 h1:Wo3V3DVTxl5vZdxtQakqYP+DAHx7pPtAFSl1bnAa08w=
|
||||||
github.com/ooni/go-libtor v1.1.7/go.mod h1:q1YyLwRD9GeMyeerVvwc0vJ2YgwDLTp2bdVcrh/JXyI=
|
github.com/ooni/go-libtor v1.1.8/go.mod h1:q1YyLwRD9GeMyeerVvwc0vJ2YgwDLTp2bdVcrh/JXyI=
|
||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
|
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
|
||||||
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/oschwald/maxminddb-golang v1.10.0 h1:Xp1u0ZhqkSuopaKmk1WwHtjF0H9Hd9181uj2MQ5Vndg=
|
github.com/oschwald/maxminddb-golang v1.11.0 h1:aSXMqYR/EPNjGE8epgqwDay+P30hCBZIveY0WZbAWh0=
|
||||||
github.com/oschwald/maxminddb-golang v1.10.0/go.mod h1:Y2ELenReaLAZ0b400URyGwvYxHV1dLIxBuyOsyYjHK0=
|
github.com/oschwald/maxminddb-golang v1.11.0/go.mod h1:YmVI+H0zh3ySFR3w+oz8PCfglAFj3PuCmui13+P9zDg=
|
||||||
github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE=
|
github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE=
|
||||||
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||||
github.com/pires/go-proxyproto v0.7.0 h1:IukmRewDQFWC7kfnb66CSomk2q/seBuilHBYFwyq0Hs=
|
github.com/pires/go-proxyproto v0.7.0 h1:IukmRewDQFWC7kfnb66CSomk2q/seBuilHBYFwyq0Hs=
|
||||||
@ -110,34 +112,40 @@ github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
|||||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||||
github.com/quic-go/qtls-go1-18 v0.2.0 h1:5ViXqBZ90wpUcZS0ge79rf029yx0dYB0McyPJwqqj7U=
|
github.com/quic-go/qtls-go1-18 v0.2.0 h1:5ViXqBZ90wpUcZS0ge79rf029yx0dYB0McyPJwqqj7U=
|
||||||
github.com/quic-go/qtls-go1-18 v0.2.0/go.mod h1:moGulGHK7o6O8lSPSZNoOwcLvJKJ85vVNc7oJFD65bc=
|
github.com/quic-go/qtls-go1-18 v0.2.0/go.mod h1:moGulGHK7o6O8lSPSZNoOwcLvJKJ85vVNc7oJFD65bc=
|
||||||
github.com/quic-go/qtls-go1-19 v0.2.0 h1:Cvn2WdhyViFUHoOqK52i51k4nDX8EwIh5VJiVM4nttk=
|
github.com/quic-go/qtls-go1-19 v0.3.2 h1:tFxjCFcTQzK+oMxG6Zcvp4Dq8dx4yD3dDiIiyc86Z5U=
|
||||||
github.com/quic-go/qtls-go1-19 v0.2.0/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
|
github.com/quic-go/qtls-go1-19 v0.3.2/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
|
||||||
github.com/quic-go/qtls-go1-20 v0.1.0 h1:d1PK3ErFy9t7zxKsG3NXBJXZjp/kMLoIb3y/kV54oAI=
|
github.com/quic-go/qtls-go1-20 v0.2.2 h1:WLOPx6OY/hxtTxKV1Zrq20FtXtDEkeY00CGQm8GEa3E=
|
||||||
github.com/quic-go/qtls-go1-20 v0.1.0/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
|
github.com/quic-go/qtls-go1-20 v0.2.2/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
|
||||||
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0 h1:KyhtFFt1Jtp5vW2ohNvstvQffTOQ/s5vENuGXzdA+TM=
|
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0 h1:KyhtFFt1Jtp5vW2ohNvstvQffTOQ/s5vENuGXzdA+TM=
|
||||||
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0/go.mod h1:D4SFEOkJK+4W1v86ZhX0jPM0rAL498fyQAChqMtes/I=
|
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0/go.mod h1:D4SFEOkJK+4W1v86ZhX0jPM0rAL498fyQAChqMtes/I=
|
||||||
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 h1:5+m7c6AkmAylhauulqN/c5dnh8/KssrE9c93TQrXldA=
|
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 h1:5+m7c6AkmAylhauulqN/c5dnh8/KssrE9c93TQrXldA=
|
||||||
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61/go.mod h1:QUQ4RRHD6hGGHdFMEtR8T2P6GS6R3D/CXKdaYHKKXms=
|
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61/go.mod h1:QUQ4RRHD6hGGHdFMEtR8T2P6GS6R3D/CXKdaYHKKXms=
|
||||||
|
github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2 h1:dnkKrzapqtAwjTSWt6hdPrARORfoYvuUczynvRLrueo=
|
||||||
|
github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2/go.mod h1:1JUiV7nGuf++YFm9eWZ8q2lrwHmhcUGzptMl/vL1+LA=
|
||||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
|
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
|
||||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
||||||
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32 h1:tztuJB+giOWNRKQEBVY2oI3PsheTooMdh+/yxemYQYY=
|
github.com/sagernet/quic-go v0.0.0-20230615020047-10f05c797c02 h1:9S+L1n/4hbe1pCLNTZnnddSNseQda8tuSm/+uRy6p8s=
|
||||||
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32/go.mod h1:QMCkxXAC3CvBgDZVIJp43NWTuwGBScCzMLVLynjERL8=
|
github.com/sagernet/quic-go v0.0.0-20230615020047-10f05c797c02/go.mod h1:rth94YcHJfkC4mG03JTXmv7mJsDc8MOIIqQrCtoaV4U=
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
||||||
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||||
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
|
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
|
||||||
github.com/sagernet/sing v0.2.4 h1:gC8BR5sglbJZX23RtMyFa8EETP9YEUADhfbEzU1yVbo=
|
github.com/sagernet/sing v0.2.8-0.20230707055657-7c9b4d624da7 h1:sKQu4Gc6vMfzleoFK3h8ROfn/TP2U36qQME3/iYaoqA=
|
||||||
github.com/sagernet/sing v0.2.4/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
|
github.com/sagernet/sing v0.2.8-0.20230707055657-7c9b4d624da7/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
|
||||||
github.com/sagernet/sing-dns v0.1.5-0.20230415085626-111ecf799dfc h1:hmbuqKv48SAjiKPoqtJGvS5pEHVPZjTHq9CPwQY2cZ4=
|
github.com/sagernet/sing-dns v0.1.7-0.20230703131656-fd65b6178bf9 h1:35qe74ygIKj5uQkDDD0Xtv+iWOspQsS/Lqhs2XiY0Ak=
|
||||||
github.com/sagernet/sing-dns v0.1.5-0.20230415085626-111ecf799dfc/go.mod h1:ZKuuqgsHRxDahYrzgSgy4vIAGGuKPlIf4hLcNzYzLkY=
|
github.com/sagernet/sing-dns v0.1.7-0.20230703131656-fd65b6178bf9/go.mod h1:wgmbh0yruJXRO8tmfwPx6hOl6pyReWRoeHdkRehWkmw=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230417102954-f77257340507 h1:bAHZCdWqJkb8LEW98+YsMVDXGRMUVjka8IC+St6ot88=
|
github.com/sagernet/sing-mux v0.1.1-0.20230703132253-2cedde0fbc90 h1:aEe2HrRc9OTS7IZ8RHyh224OhltnwRQs4/y89UsHPo8=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230417102954-f77257340507/go.mod h1:UJjvQGw0lyYaDGIDvUraL16fwaAEH1WFw1Y6sUcMPog=
|
github.com/sagernet/sing-mux v0.1.1-0.20230703132253-2cedde0fbc90/go.mod h1:sm126rB5EUi9HLf4jCSHTqo+XRPbh4BoEVeLbr2WRbE=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b h1:ouW/6IDCrxkBe19YSbdCd7buHix7b+UZ6BM4Zz74XF4=
|
github.com/sagernet/sing-shadowsocks v0.2.3-0.20230703131347-b044960bd355 h1:XOgNZYnkDrx5qtNS4kqIOHMhjZuc7mJ2pY/x3EyZX8Q=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b/go.mod h1:oG8bPerYI6cZ74KquY3DvA7ynECyrILPBnce6wtBqeI=
|
github.com/sagernet/sing-shadowsocks v0.2.3-0.20230703131347-b044960bd355/go.mod h1:atEATsxqPo8qCPcFt8Rw7TFEJ70egCoMR7PziX4jmjI=
|
||||||
github.com/sagernet/sing-tun v0.1.5-0.20230422121432-209ec123ca7b h1:9NsciSJGwzdkXwVvT2c2g+RvkTVkANeBLr2l+soJ7LM=
|
github.com/sagernet/sing-shadowsocks2 v0.1.2-0.20230703131506-ca0c6adde968 h1:UctXygnZfqsFR+2hZXfpWK3pSYKLbBQMuli9GDE6QU0=
|
||||||
github.com/sagernet/sing-tun v0.1.5-0.20230422121432-209ec123ca7b/go.mod h1:DD7Ce2Gt0GFc6I/1+Uw4D/aUlBsGqrQsC52CMK/V818=
|
github.com/sagernet/sing-shadowsocks2 v0.1.2-0.20230703131506-ca0c6adde968/go.mod h1:xFxUGbtnqRLxtQftCILFeKf43GE6S83f0I6CsO9BxGE=
|
||||||
github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 h1:BHOnxrbC929JonuKqFdJ7ZbDp7zs4oTlH5KFvKtWu9U=
|
github.com/sagernet/sing-shadowtls v0.1.3-0.20230703132509-93bbad3057e4 h1:ZjLyCkEENqXzGp4PRZbQGk5wPzEq0Rg+/2jK82lmy3Q=
|
||||||
github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3/go.mod h1:yKrAr+dqZd64DxBXCHWrYicp+n4qbqO73mtwv3dck8U=
|
github.com/sagernet/sing-shadowtls v0.1.3-0.20230703132509-93bbad3057e4/go.mod h1:8ZSSHJSNOG7cUCUYJemZNH873EsKdFqABykTypoS/2M=
|
||||||
|
github.com/sagernet/sing-tun v0.1.9-0.20230703134424-fd850d00e5cd h1:lkJA/P1L2XE5lNDnzA2fygx6DZIks3Sx87GN2OE0jNY=
|
||||||
|
github.com/sagernet/sing-tun v0.1.9-0.20230703134424-fd850d00e5cd/go.mod h1:XNQoXtvsmeva+dADmo/57KktLNgm5ubOyR67Niahqj8=
|
||||||
|
github.com/sagernet/sing-vmess v0.1.7-0.20230711074224-7d2a9a318162 h1:EvEbqAdZJalFqLwKSHIixH+TRed0iY2f8KatI7mtt1Q=
|
||||||
|
github.com/sagernet/sing-vmess v0.1.7-0.20230711074224-7d2a9a318162/go.mod h1:FHEBboQRvfBDbZd/fAKBpgR4w7QbYyzNL/MLd22/iTk=
|
||||||
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as=
|
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as=
|
||||||
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37/go.mod h1:3skNSftZDJWTGVtVaM2jfbce8qHnmH/AGDRe62iNOg0=
|
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37/go.mod h1:3skNSftZDJWTGVtVaM2jfbce8qHnmH/AGDRe62iNOg0=
|
||||||
github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 h1:2ItpW1nMNkPzmBTxV0/eClCklHrFSQMnUGcpUmJxVeE=
|
github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 h1:2ItpW1nMNkPzmBTxV0/eClCklHrFSQMnUGcpUmJxVeE=
|
||||||
@ -148,36 +156,32 @@ github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e h1:7uw2njHFGE+V
|
|||||||
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e/go.mod h1:45TUl8+gH4SIKr4ykREbxKWTxkDlSzFENzctB1dVRRY=
|
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e/go.mod h1:45TUl8+gH4SIKr4ykREbxKWTxkDlSzFENzctB1dVRRY=
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77 h1:g6QtRWQ2dKX7EQP++1JLNtw4C2TNxd4/ov8YUpOPOSo=
|
github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77 h1:g6QtRWQ2dKX7EQP++1JLNtw4C2TNxd4/ov8YUpOPOSo=
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77/go.mod h1:pJDdXzZIwJ+2vmnT0TKzmf8meeum+e2mTDSehw79eE0=
|
github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77/go.mod h1:pJDdXzZIwJ+2vmnT0TKzmf8meeum+e2mTDSehw79eE0=
|
||||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 h1:rc/CcqLH3lh8n+csdOuDfP+NuykE0U6AeYSJJHKDgSg=
|
||||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9/go.mod h1:a/83NAfUXvEuLpmxDssAXxgUgrEy12MId3Wd7OTs76s=
|
||||||
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/spyzhov/ajson v0.7.1 h1:1MDIlPc6x0zjNtpa7tDzRAyFAvRX+X8ZsvtYz5lZg6A=
|
github.com/spyzhov/ajson v0.7.1 h1:1MDIlPc6x0zjNtpa7tDzRAyFAvRX+X8ZsvtYz5lZg6A=
|
||||||
github.com/spyzhov/ajson v0.7.1/go.mod h1:63V+CGM6f1Bu/p4nLIN8885ojBdt88TbLoSFzyqMuVA=
|
github.com/spyzhov/ajson v0.7.1/go.mod h1:63V+CGM6f1Bu/p4nLIN8885ojBdt88TbLoSFzyqMuVA=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
|
||||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
|
||||||
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 h1:tHNk7XK9GkmKUR6Gh8gVBKXc2MVSZ4G/NnWLtzw4gNA=
|
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 h1:tHNk7XK9GkmKUR6Gh8gVBKXc2MVSZ4G/NnWLtzw4gNA=
|
||||||
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
|
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
|
||||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
|
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
|
||||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
|
||||||
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
|
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
|
||||||
go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
||||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||||
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
|
||||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||||
go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
|
go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
|
||||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
|
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
|
||||||
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
|
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
|
||||||
go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35 h1:nJAwRlGWZZDOD+6wni9KVUNHMpHko/OnRwsrCYeAzPo=
|
go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35 h1:nJAwRlGWZZDOD+6wni9KVUNHMpHko/OnRwsrCYeAzPo=
|
||||||
@ -187,76 +191,72 @@ golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaE
|
|||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||||
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
|
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
|
||||||
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
||||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug=
|
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME=
|
||||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
|
||||||
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
|
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
|
||||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
|
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
|
||||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
|
||||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ=
|
golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
|
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||||
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
|
golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg=
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w=
|
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
|
||||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
|
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
|
||||||
google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag=
|
google.golang.org/grpc v1.56.2 h1:fVRFRnXvU+x6C4IlHZewvJOVHoOv1TUuQyoRsYnB4bI=
|
||||||
google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
|
google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
@ -264,7 +264,6 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
|||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
|
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
|
||||||
gvisor.dev/gvisor v0.0.0-20230415003630-3981d5d5e523 h1:zUQYeyyPLnSR6yMvLSOmLH37xDWCZ7BqlpE69fE5K3Q=
|
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
|
||||||
gvisor.dev/gvisor v0.0.0-20230415003630-3981d5d5e523/go.mod h1:pzr6sy8gDLfVmDAg8OYrlKvGEHw5C3PGTiBXBTCx76Q=
|
lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI=
|
||||||
lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0=
|
lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
|
||||||
lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
|
|
||||||
|
@ -125,7 +125,7 @@ func TestHysteriaOutbound(t *testing.T) {
|
|||||||
_, certPem, keyPem := createSelfSignedCertificate(t, "example.org")
|
_, certPem, keyPem := createSelfSignedCertificate(t, "example.org")
|
||||||
startDockerContainer(t, DockerOptions{
|
startDockerContainer(t, DockerOptions{
|
||||||
Image: ImageHysteria,
|
Image: ImageHysteria,
|
||||||
Ports: []uint16{serverPort, testPort},
|
Ports: []uint16{testPort},
|
||||||
Cmd: []string{"-c", "/etc/hysteria/config.json", "server"},
|
Cmd: []string{"-c", "/etc/hysteria/config.json", "server"},
|
||||||
Bind: map[string]string{
|
Bind: map[string]string{
|
||||||
"hysteria-server.json": "/etc/hysteria/config.json",
|
"hysteria-server.json": "/etc/hysteria/config.json",
|
||||||
|
@ -32,6 +32,7 @@ func TestMuxCoolServer(t *testing.T) {
|
|||||||
Image: ImageV2RayCore,
|
Image: ImageV2RayCore,
|
||||||
Ports: []uint16{serverPort, testPort},
|
Ports: []uint16{serverPort, testPort},
|
||||||
EntryPoint: "v2ray",
|
EntryPoint: "v2ray",
|
||||||
|
Cmd: []string{"run"},
|
||||||
Stdin: content,
|
Stdin: content,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"net/netip"
|
"net/netip"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/common/mux"
|
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
|
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
|
||||||
@ -12,24 +11,25 @@ import (
|
|||||||
"github.com/gofrs/uuid/v5"
|
"github.com/gofrs/uuid/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
var muxProtocols = []mux.Protocol{
|
var muxProtocols = []string{
|
||||||
mux.ProtocolYAMux,
|
"h2mux",
|
||||||
mux.ProtocolSMux,
|
"smux",
|
||||||
|
"yamux",
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVMessSMux(t *testing.T) {
|
func TestVMessSMux(t *testing.T) {
|
||||||
testVMessMux(t, option.MultiplexOptions{
|
testVMessMux(t, option.MultiplexOptions{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
Protocol: mux.ProtocolSMux.String(),
|
Protocol: "smux",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShadowsocksMux(t *testing.T) {
|
func TestShadowsocksMux(t *testing.T) {
|
||||||
for _, protocol := range muxProtocols {
|
for _, protocol := range muxProtocols {
|
||||||
t.Run(protocol.String(), func(t *testing.T) {
|
t.Run(protocol, func(t *testing.T) {
|
||||||
testShadowsocksMux(t, option.MultiplexOptions{
|
testShadowsocksMux(t, option.MultiplexOptions{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
Protocol: protocol.String(),
|
Protocol: protocol,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -38,7 +38,7 @@ func TestShadowsocksMux(t *testing.T) {
|
|||||||
func TestShadowsockH2Mux(t *testing.T) {
|
func TestShadowsockH2Mux(t *testing.T) {
|
||||||
testShadowsocksMux(t, option.MultiplexOptions{
|
testShadowsocksMux(t, option.MultiplexOptions{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
Protocol: mux.ProtocolH2Mux.String(),
|
Protocol: "h2mux",
|
||||||
Padding: true,
|
Padding: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ func TestShadowsockH2Mux(t *testing.T) {
|
|||||||
func TestShadowsockSMuxPadding(t *testing.T) {
|
func TestShadowsockSMuxPadding(t *testing.T) {
|
||||||
testShadowsocksMux(t, option.MultiplexOptions{
|
testShadowsocksMux(t, option.MultiplexOptions{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
Protocol: mux.ProtocolSMux.String(),
|
Protocol: "smux",
|
||||||
Padding: true,
|
Padding: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,9 @@ func TestShadowTLSFallback(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Version: 3,
|
Version: 3,
|
||||||
Password: "hello",
|
Users: []option.ShadowTLSUser{
|
||||||
|
{Password: "hello"},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -200,7 +202,9 @@ func TestShadowTLSInbound(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Version: 3,
|
Version: 3,
|
||||||
Password: password,
|
Users: []option.ShadowTLSUser{
|
||||||
|
{Password: password},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -18,7 +18,8 @@ func TestShadowsocksObfs(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShadowsocksV2RayPlugin(t *testing.T) {
|
// Since I can't test this on m1 mac (rosetta error: bss_size overflow), I don't care about it
|
||||||
|
func _TestShadowsocksV2RayPlugin(t *testing.T) {
|
||||||
testShadowsocksPlugin(t, "v2ray-plugin", "", "--plugin v2ray-plugin --plugin-opts=server")
|
testShadowsocksPlugin(t, "v2ray-plugin", "", "--plugin v2ray-plugin --plugin-opts=server")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/sagernet/sing/common"
|
|
||||||
"github.com/sagernet/sing/common/buf"
|
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
|
||||||
N "github.com/sagernet/sing/common/network"
|
|
||||||
"github.com/sagernet/sing/common/udpnat"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestUDPNatClose(t *testing.T) {
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
defer cancel()
|
|
||||||
connCtx, connCancel := common.ContextWithCancelCause(context.Background())
|
|
||||||
defer connCancel(net.ErrClosed)
|
|
||||||
service := udpnat.New[int](1, &testUDPNatCloseHandler{connCancel})
|
|
||||||
service.NewPacket(ctx, 0, buf.As([]byte("Hello")), M.Metadata{}, func(natConn N.PacketConn) N.PacketWriter {
|
|
||||||
return &testPacketWriter{}
|
|
||||||
})
|
|
||||||
select {
|
|
||||||
case <-connCtx.Done():
|
|
||||||
if E.IsClosed(connCtx.Err()) {
|
|
||||||
t.Fatal(E.New("conn closed unexpectedly: ", connCtx.Err()))
|
|
||||||
}
|
|
||||||
case <-time.After(2 * time.Second):
|
|
||||||
t.Fatal("conn not closed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type testUDPNatCloseHandler struct {
|
|
||||||
done common.ContextCancelCauseFunc
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *testUDPNatCloseHandler) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
|
|
||||||
for {
|
|
||||||
buffer := buf.NewPacket()
|
|
||||||
_, err := conn.ReadPacket(buffer)
|
|
||||||
buffer.Release()
|
|
||||||
if err != nil {
|
|
||||||
h.done(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *testUDPNatCloseHandler) NewError(ctx context.Context, err error) {
|
|
||||||
}
|
|
||||||
|
|
||||||
type testPacketWriter struct{}
|
|
||||||
|
|
||||||
func (t *testPacketWriter) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -75,6 +75,7 @@ func testV2RayGRPCInbound(t *testing.T, forceLite bool) {
|
|||||||
Image: ImageV2RayCore,
|
Image: ImageV2RayCore,
|
||||||
Ports: []uint16{serverPort, testPort},
|
Ports: []uint16{serverPort, testPort},
|
||||||
EntryPoint: "v2ray",
|
EntryPoint: "v2ray",
|
||||||
|
Cmd: []string{"run"},
|
||||||
Stdin: content,
|
Stdin: content,
|
||||||
Bind: map[string]string{
|
Bind: map[string]string{
|
||||||
certPem: "/path/to/certificate.crt",
|
certPem: "/path/to/certificate.crt",
|
||||||
@ -114,6 +115,7 @@ func testV2RayGRPCOutbound(t *testing.T, forceLite bool) {
|
|||||||
Image: ImageV2RayCore,
|
Image: ImageV2RayCore,
|
||||||
Ports: []uint16{serverPort, testPort},
|
Ports: []uint16{serverPort, testPort},
|
||||||
EntryPoint: "v2ray",
|
EntryPoint: "v2ray",
|
||||||
|
Cmd: []string{"run"},
|
||||||
Stdin: content,
|
Stdin: content,
|
||||||
Env: []string{"V2RAY_VMESS_AEAD_FORCED=false"},
|
Env: []string{"V2RAY_VMESS_AEAD_FORCED=false"},
|
||||||
Bind: map[string]string{
|
Bind: map[string]string{
|
||||||
|
@ -113,6 +113,7 @@ func testV2RayWebsocketInbound(t *testing.T, maxEarlyData uint32, earlyDataHeade
|
|||||||
Image: ImageV2RayCore,
|
Image: ImageV2RayCore,
|
||||||
Ports: []uint16{serverPort, testPort},
|
Ports: []uint16{serverPort, testPort},
|
||||||
EntryPoint: "v2ray",
|
EntryPoint: "v2ray",
|
||||||
|
Cmd: []string{"run"},
|
||||||
Stdin: content,
|
Stdin: content,
|
||||||
Bind: map[string]string{
|
Bind: map[string]string{
|
||||||
certPem: "/path/to/certificate.crt",
|
certPem: "/path/to/certificate.crt",
|
||||||
@ -146,6 +147,7 @@ func testV2RayWebsocketOutbound(t *testing.T, maxEarlyData uint32, earlyDataHead
|
|||||||
Image: ImageV2RayCore,
|
Image: ImageV2RayCore,
|
||||||
Ports: []uint16{serverPort, testPort},
|
Ports: []uint16{serverPort, testPort},
|
||||||
EntryPoint: "v2ray",
|
EntryPoint: "v2ray",
|
||||||
|
Cmd: []string{"run"},
|
||||||
Stdin: content,
|
Stdin: content,
|
||||||
Env: []string{"V2RAY_VMESS_AEAD_FORCED=false"},
|
Env: []string{"V2RAY_VMESS_AEAD_FORCED=false"},
|
||||||
Bind: map[string]string{
|
Bind: map[string]string{
|
||||||
|
@ -175,6 +175,7 @@ func testVMessInboundWithV2Ray(t *testing.T, security string, alterId int, authe
|
|||||||
Image: ImageV2RayCore,
|
Image: ImageV2RayCore,
|
||||||
Ports: []uint16{serverPort, testPort},
|
Ports: []uint16{serverPort, testPort},
|
||||||
EntryPoint: "v2ray",
|
EntryPoint: "v2ray",
|
||||||
|
Cmd: []string{"run"},
|
||||||
Stdin: content,
|
Stdin: content,
|
||||||
Env: []string{"V2RAY_VMESS_AEAD_FORCED=false"},
|
Env: []string{"V2RAY_VMESS_AEAD_FORCED=false"},
|
||||||
})
|
})
|
||||||
@ -222,6 +223,7 @@ func testVMessOutboundWithV2Ray(t *testing.T, security string, globalPadding boo
|
|||||||
Image: ImageV2RayCore,
|
Image: ImageV2RayCore,
|
||||||
Ports: []uint16{serverPort, testPort},
|
Ports: []uint16{serverPort, testPort},
|
||||||
EntryPoint: "v2ray",
|
EntryPoint: "v2ray",
|
||||||
|
Cmd: []string{"run"},
|
||||||
Stdin: content,
|
Stdin: content,
|
||||||
Env: []string{"V2RAY_VMESS_AEAD_FORCED=false"},
|
Env: []string{"V2RAY_VMESS_AEAD_FORCED=false"},
|
||||||
})
|
})
|
||||||
|
@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestWireGuard(t *testing.T) {
|
func _TestWireGuard(t *testing.T) {
|
||||||
startDockerContainer(t, DockerOptions{
|
startDockerContainer(t, DockerOptions{
|
||||||
Image: ImageBoringTun,
|
Image: ImageBoringTun,
|
||||||
Cap: []string{"MKNOD", "NET_ADMIN", "NET_RAW"},
|
Cap: []string{"MKNOD", "NET_ADMIN", "NET_RAW"},
|
||||||
|
@ -199,9 +199,7 @@ func (t *Transport) fetchServers0(ctx context.Context, iface *net.Interface) err
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transport) fetchServersResponse(iface *net.Interface, packetConn net.PacketConn, transactionID dhcpv4.TransactionID) error {
|
func (t *Transport) fetchServersResponse(iface *net.Interface, packetConn net.PacketConn, transactionID dhcpv4.TransactionID) error {
|
||||||
_buffer := buf.StackNewSize(dhcpv4.MaxMessageSize)
|
buffer := buf.NewSize(dhcpv4.MaxMessageSize)
|
||||||
defer common.KeepAlive(_buffer)
|
|
||||||
buffer := common.Dup(_buffer)
|
|
||||||
defer buffer.Release()
|
defer buffer.Release()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
@ -2,43 +2,78 @@ package fakeip
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing/common/cache"
|
"github.com/sagernet/sing/common/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ adapter.FakeIPStorage = (*MemoryStorage)(nil)
|
var _ adapter.FakeIPStorage = (*MemoryStorage)(nil)
|
||||||
|
|
||||||
type MemoryStorage struct {
|
type MemoryStorage struct {
|
||||||
metadata *adapter.FakeIPMetadata
|
addressAccess sync.RWMutex
|
||||||
domainCache *cache.LruCache[netip.Addr, string]
|
domainAccess sync.RWMutex
|
||||||
|
addressCache map[netip.Addr]string
|
||||||
|
domainCache4 map[string]netip.Addr
|
||||||
|
domainCache6 map[string]netip.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMemoryStorage() *MemoryStorage {
|
func NewMemoryStorage() *MemoryStorage {
|
||||||
return &MemoryStorage{
|
return &MemoryStorage{
|
||||||
domainCache: cache.New[netip.Addr, string](),
|
addressCache: make(map[netip.Addr]string),
|
||||||
|
domainCache4: make(map[string]netip.Addr),
|
||||||
|
domainCache6: make(map[string]netip.Addr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MemoryStorage) FakeIPMetadata() *adapter.FakeIPMetadata {
|
func (s *MemoryStorage) FakeIPMetadata() *adapter.FakeIPMetadata {
|
||||||
return s.metadata
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MemoryStorage) FakeIPSaveMetadata(metadata *adapter.FakeIPMetadata) error {
|
func (s *MemoryStorage) FakeIPSaveMetadata(metadata *adapter.FakeIPMetadata) error {
|
||||||
s.metadata = metadata
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MemoryStorage) FakeIPStore(address netip.Addr, domain string) error {
|
func (s *MemoryStorage) FakeIPStore(address netip.Addr, domain string) error {
|
||||||
s.domainCache.Store(address, domain)
|
s.addressAccess.Lock()
|
||||||
|
s.domainAccess.Lock()
|
||||||
|
s.addressCache[address] = domain
|
||||||
|
if address.Is4() {
|
||||||
|
s.domainCache4[domain] = address
|
||||||
|
} else {
|
||||||
|
s.domainCache6[domain] = address
|
||||||
|
}
|
||||||
|
s.domainAccess.Unlock()
|
||||||
|
s.addressAccess.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *MemoryStorage) FakeIPStoreAsync(address netip.Addr, domain string, logger logger.Logger) {
|
||||||
|
_ = s.FakeIPStore(address, domain)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *MemoryStorage) FakeIPLoad(address netip.Addr) (string, bool) {
|
func (s *MemoryStorage) FakeIPLoad(address netip.Addr) (string, bool) {
|
||||||
return s.domainCache.Load(address)
|
s.addressAccess.RLock()
|
||||||
|
defer s.addressAccess.RUnlock()
|
||||||
|
domain, loaded := s.addressCache[address]
|
||||||
|
return domain, loaded
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MemoryStorage) FakeIPLoadDomain(domain string, isIPv6 bool) (netip.Addr, bool) {
|
||||||
|
s.domainAccess.RLock()
|
||||||
|
defer s.domainAccess.RUnlock()
|
||||||
|
if !isIPv6 {
|
||||||
|
address, loaded := s.domainCache4[domain]
|
||||||
|
return address, loaded
|
||||||
|
} else {
|
||||||
|
address, loaded := s.domainCache6[domain]
|
||||||
|
return address, loaded
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MemoryStorage) FakeIPReset() error {
|
func (s *MemoryStorage) FakeIPReset() error {
|
||||||
s.domainCache = cache.New[netip.Addr, string]()
|
s.addressCache = make(map[netip.Addr]string)
|
||||||
|
s.domainCache4 = make(map[string]netip.Addr)
|
||||||
|
s.domainCache6 = make(map[string]netip.Addr)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -69,14 +69,14 @@ func (s *Transport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg,
|
|||||||
func (s *Transport) Lookup(ctx context.Context, domain string, strategy dns.DomainStrategy) ([]netip.Addr, error) {
|
func (s *Transport) Lookup(ctx context.Context, domain string, strategy dns.DomainStrategy) ([]netip.Addr, error) {
|
||||||
var addresses []netip.Addr
|
var addresses []netip.Addr
|
||||||
if strategy != dns.DomainStrategyUseIPv6 {
|
if strategy != dns.DomainStrategyUseIPv6 {
|
||||||
inet4Address, err := s.store.Create(domain, dns.DomainStrategyUseIPv4)
|
inet4Address, err := s.store.Create(domain, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
addresses = append(addresses, inet4Address)
|
addresses = append(addresses, inet4Address)
|
||||||
}
|
}
|
||||||
if strategy != dns.DomainStrategyUseIPv4 {
|
if strategy != dns.DomainStrategyUseIPv4 {
|
||||||
inet6Address, err := s.store.Create(domain, dns.DomainStrategyUseIPv6)
|
inet6Address, err := s.store.Create(domain, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,15 @@ import (
|
|||||||
"net/netip"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-dns"
|
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
"github.com/sagernet/sing/common/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ adapter.FakeIPStore = (*Store)(nil)
|
var _ adapter.FakeIPStore = (*Store)(nil)
|
||||||
|
|
||||||
type Store struct {
|
type Store struct {
|
||||||
router adapter.Router
|
router adapter.Router
|
||||||
|
logger logger.Logger
|
||||||
inet4Range netip.Prefix
|
inet4Range netip.Prefix
|
||||||
inet6Range netip.Prefix
|
inet6Range netip.Prefix
|
||||||
storage adapter.FakeIPStorage
|
storage adapter.FakeIPStorage
|
||||||
@ -19,9 +20,10 @@ type Store struct {
|
|||||||
inet6Current netip.Addr
|
inet6Current netip.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStore(router adapter.Router, inet4Range netip.Prefix, inet6Range netip.Prefix) *Store {
|
func NewStore(router adapter.Router, logger logger.Logger, inet4Range netip.Prefix, inet6Range netip.Prefix) *Store {
|
||||||
return &Store{
|
return &Store{
|
||||||
router: router,
|
router: router,
|
||||||
|
logger: logger,
|
||||||
inet4Range: inet4Range,
|
inet4Range: inet4Range,
|
||||||
inet6Range: inet6Range,
|
inet6Range: inet6Range,
|
||||||
}
|
}
|
||||||
@ -69,9 +71,12 @@ func (s *Store) Close() error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) Create(domain string, strategy dns.DomainStrategy) (netip.Addr, error) {
|
func (s *Store) Create(domain string, isIPv6 bool) (netip.Addr, error) {
|
||||||
|
if address, loaded := s.storage.FakeIPLoadDomain(domain, isIPv6); loaded {
|
||||||
|
return address, nil
|
||||||
|
}
|
||||||
var address netip.Addr
|
var address netip.Addr
|
||||||
if strategy == dns.DomainStrategyUseIPv4 {
|
if !isIPv6 {
|
||||||
if !s.inet4Current.IsValid() {
|
if !s.inet4Current.IsValid() {
|
||||||
return netip.Addr{}, E.New("missing IPv4 fakeip address range")
|
return netip.Addr{}, E.New("missing IPv4 fakeip address range")
|
||||||
}
|
}
|
||||||
@ -92,10 +97,7 @@ func (s *Store) Create(domain string, strategy dns.DomainStrategy) (netip.Addr,
|
|||||||
s.inet6Current = nextAddress
|
s.inet6Current = nextAddress
|
||||||
address = nextAddress
|
address = nextAddress
|
||||||
}
|
}
|
||||||
err := s.storage.FakeIPStore(address, domain)
|
s.storage.FakeIPStoreAsync(address, domain, s.logger)
|
||||||
if err != nil {
|
|
||||||
return netip.Addr{}, err
|
|
||||||
}
|
|
||||||
return address, nil
|
return address, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,9 +41,7 @@ func WriteClientHello(stream io.Writer, hello ClientHello) error {
|
|||||||
requestLen += 8 // recvBPS
|
requestLen += 8 // recvBPS
|
||||||
requestLen += 2 // auth len
|
requestLen += 2 // auth len
|
||||||
requestLen += len(hello.Auth)
|
requestLen += len(hello.Auth)
|
||||||
_request := buf.StackNewSize(requestLen)
|
request := buf.NewSize(requestLen)
|
||||||
defer common.KeepAlive(_request)
|
|
||||||
request := common.Dup(_request)
|
|
||||||
defer request.Release()
|
defer request.Release()
|
||||||
common.Must(
|
common.Must(
|
||||||
request.WriteByte(Version),
|
request.WriteByte(Version),
|
||||||
@ -99,9 +97,7 @@ func ReadServerHello(stream io.Reader) (*ServerHello, error) {
|
|||||||
responseLen += 8 // sendBPS
|
responseLen += 8 // sendBPS
|
||||||
responseLen += 8 // recvBPS
|
responseLen += 8 // recvBPS
|
||||||
responseLen += 2 // message len
|
responseLen += 2 // message len
|
||||||
_response := buf.StackNewSize(responseLen)
|
response := buf.NewSize(responseLen)
|
||||||
defer common.KeepAlive(_response)
|
|
||||||
response := common.Dup(_response)
|
|
||||||
defer response.Release()
|
defer response.Release()
|
||||||
_, err := response.ReadFullFrom(stream, responseLen)
|
_, err := response.ReadFullFrom(stream, responseLen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -131,9 +127,7 @@ func WriteServerHello(stream io.Writer, hello ServerHello) error {
|
|||||||
responseLen += 8 // recvBPS
|
responseLen += 8 // recvBPS
|
||||||
responseLen += 2 // message len
|
responseLen += 2 // message len
|
||||||
responseLen += len(hello.Message)
|
responseLen += len(hello.Message)
|
||||||
_response := buf.StackNewSize(responseLen)
|
response := buf.NewSize(responseLen)
|
||||||
defer common.KeepAlive(_response)
|
|
||||||
response := common.Dup(_response)
|
|
||||||
defer response.Release()
|
defer response.Release()
|
||||||
if hello.OK {
|
if hello.OK {
|
||||||
common.Must(response.WriteByte(1))
|
common.Must(response.WriteByte(1))
|
||||||
@ -185,9 +179,7 @@ func WriteClientRequest(stream io.Writer, request ClientRequest) error {
|
|||||||
requestLen += 2 // host len
|
requestLen += 2 // host len
|
||||||
requestLen += len(request.Host)
|
requestLen += len(request.Host)
|
||||||
requestLen += 2 // port
|
requestLen += 2 // port
|
||||||
_buffer := buf.StackNewSize(requestLen)
|
buffer := buf.NewSize(requestLen)
|
||||||
defer common.KeepAlive(_buffer)
|
|
||||||
buffer := common.Dup(_buffer)
|
|
||||||
defer buffer.Release()
|
defer buffer.Release()
|
||||||
if request.UDP {
|
if request.UDP {
|
||||||
common.Must(buffer.WriteByte(1))
|
common.Must(buffer.WriteByte(1))
|
||||||
@ -213,9 +205,7 @@ func ReadServerResponse(stream io.Reader) (*ServerResponse, error) {
|
|||||||
responseLen += 1 // ok
|
responseLen += 1 // ok
|
||||||
responseLen += 4 // udp session id
|
responseLen += 4 // udp session id
|
||||||
responseLen += 2 // message len
|
responseLen += 2 // message len
|
||||||
_response := buf.StackNewSize(responseLen)
|
response := buf.NewSize(responseLen)
|
||||||
defer common.KeepAlive(_response)
|
|
||||||
response := common.Dup(_response)
|
|
||||||
defer response.Release()
|
defer response.Release()
|
||||||
_, err := response.ReadFullFrom(stream, responseLen)
|
_, err := response.ReadFullFrom(stream, responseLen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -243,9 +233,7 @@ func WriteServerResponse(stream io.Writer, response ServerResponse) error {
|
|||||||
responseLen += 4 // udp session id
|
responseLen += 4 // udp session id
|
||||||
responseLen += 2 // message len
|
responseLen += 2 // message len
|
||||||
responseLen += len(response.Message)
|
responseLen += len(response.Message)
|
||||||
_buffer := buf.StackNewSize(responseLen)
|
buffer := buf.NewSize(responseLen)
|
||||||
defer common.KeepAlive(_buffer)
|
|
||||||
buffer := common.Dup(_buffer)
|
|
||||||
defer buffer.Release()
|
defer buffer.Release()
|
||||||
if response.OK {
|
if response.OK {
|
||||||
common.Must(buffer.WriteByte(1))
|
common.Must(buffer.WriteByte(1))
|
||||||
@ -338,9 +326,7 @@ func WriteUDPMessage(conn quic.Connection, message UDPMessage) error {
|
|||||||
messageLen += 1 // frag count
|
messageLen += 1 // frag count
|
||||||
messageLen += 2 // data len
|
messageLen += 2 // data len
|
||||||
messageLen += len(message.Data)
|
messageLen += len(message.Data)
|
||||||
_buffer := buf.StackNewSize(messageLen)
|
buffer := buf.NewSize(messageLen)
|
||||||
defer common.KeepAlive(_buffer)
|
|
||||||
buffer := common.Dup(_buffer)
|
|
||||||
defer buffer.Release()
|
defer buffer.Release()
|
||||||
err := writeUDPMessage(conn, message, buffer)
|
err := writeUDPMessage(conn, message, buffer)
|
||||||
if errSize, ok := err.(quic.ErrMessageTooLarge); ok {
|
if errSize, ok := err.(quic.ErrMessageTooLarge); ok {
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"io"
|
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
@ -72,17 +71,6 @@ func (c *ClientConn) WriteBuffer(buffer *buf.Buffer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClientConn) ReadFrom(r io.Reader) (n int64, err error) {
|
|
||||||
if !c.headerWritten {
|
|
||||||
return bufio.ReadFrom0(c, r)
|
|
||||||
}
|
|
||||||
return bufio.Copy(c.ExtendedConn, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ClientConn) WriteTo(w io.Writer) (n int64, err error) {
|
|
||||||
return bufio.Copy(w, c.ExtendedConn)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ClientConn) FrontHeadroom() int {
|
func (c *ClientConn) FrontHeadroom() int {
|
||||||
if !c.headerWritten {
|
if !c.headerWritten {
|
||||||
return KeyLength + 5 + M.MaxSocksaddrLength
|
return KeyLength + 5 + M.MaxSocksaddrLength
|
||||||
@ -203,39 +191,18 @@ func ClientHandshakeRaw(conn net.Conn, key [KeyLength]byte, command byte, destin
|
|||||||
|
|
||||||
func ClientHandshake(conn net.Conn, key [KeyLength]byte, destination M.Socksaddr, payload []byte) error {
|
func ClientHandshake(conn net.Conn, key [KeyLength]byte, destination M.Socksaddr, payload []byte) error {
|
||||||
headerLen := KeyLength + M.SocksaddrSerializer.AddrPortLen(destination) + 5
|
headerLen := KeyLength + M.SocksaddrSerializer.AddrPortLen(destination) + 5
|
||||||
var header *buf.Buffer
|
header := buf.NewSize(headerLen + len(payload))
|
||||||
defer header.Release()
|
defer header.Release()
|
||||||
var writeHeader bool
|
|
||||||
if len(payload) > 0 && headerLen+len(payload) < 65535 {
|
|
||||||
buffer := buf.StackNewSize(headerLen + len(payload))
|
|
||||||
defer common.KeepAlive(buffer)
|
|
||||||
header = common.Dup(buffer)
|
|
||||||
} else {
|
|
||||||
buffer := buf.StackNewSize(headerLen)
|
|
||||||
defer common.KeepAlive(buffer)
|
|
||||||
header = common.Dup(buffer)
|
|
||||||
writeHeader = true
|
|
||||||
}
|
|
||||||
common.Must1(header.Write(key[:]))
|
common.Must1(header.Write(key[:]))
|
||||||
common.Must1(header.Write(CRLF))
|
common.Must1(header.Write(CRLF))
|
||||||
common.Must(header.WriteByte(CommandTCP))
|
common.Must(header.WriteByte(CommandTCP))
|
||||||
common.Must(M.SocksaddrSerializer.WriteAddrPort(header, destination))
|
common.Must(M.SocksaddrSerializer.WriteAddrPort(header, destination))
|
||||||
common.Must1(header.Write(CRLF))
|
common.Must1(header.Write(CRLF))
|
||||||
if !writeHeader {
|
|
||||||
common.Must1(header.Write(payload))
|
common.Must1(header.Write(payload))
|
||||||
}
|
|
||||||
|
|
||||||
_, err := conn.Write(header.Bytes())
|
_, err := conn.Write(header.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(err, "write request")
|
return E.Cause(err, "write request")
|
||||||
}
|
}
|
||||||
|
|
||||||
if writeHeader {
|
|
||||||
_, err = conn.Write(payload)
|
|
||||||
if err != nil {
|
|
||||||
return E.Cause(err, "write payload")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,14 +225,12 @@ func ClientHandshakePacket(conn net.Conn, key [KeyLength]byte, destination M.Soc
|
|||||||
headerLen := KeyLength + 2*M.SocksaddrSerializer.AddrPortLen(destination) + 9
|
headerLen := KeyLength + 2*M.SocksaddrSerializer.AddrPortLen(destination) + 9
|
||||||
payloadLen := payload.Len()
|
payloadLen := payload.Len()
|
||||||
var header *buf.Buffer
|
var header *buf.Buffer
|
||||||
defer header.Release()
|
|
||||||
var writeHeader bool
|
var writeHeader bool
|
||||||
if payload.Start() >= headerLen {
|
if payload.Start() >= headerLen {
|
||||||
header = buf.With(payload.ExtendHeader(headerLen))
|
header = buf.With(payload.ExtendHeader(headerLen))
|
||||||
} else {
|
} else {
|
||||||
buffer := buf.StackNewSize(headerLen)
|
header = buf.NewSize(headerLen)
|
||||||
defer common.KeepAlive(buffer)
|
defer header.Release()
|
||||||
header = common.Dup(buffer)
|
|
||||||
writeHeader = true
|
writeHeader = true
|
||||||
}
|
}
|
||||||
common.Must1(header.Write(key[:]))
|
common.Must1(header.Write(key[:]))
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/sagernet/sing/common"
|
|
||||||
"github.com/sagernet/sing/common/auth"
|
"github.com/sagernet/sing/common/auth"
|
||||||
"github.com/sagernet/sing/common/buf"
|
"github.com/sagernet/sing/common/buf"
|
||||||
"github.com/sagernet/sing/common/bufio"
|
"github.com/sagernet/sing/common/bufio"
|
||||||
@ -59,7 +58,7 @@ func (s *Service[K]) UpdateUsers(userList []K, passwordList []string) error {
|
|||||||
|
|
||||||
func (s *Service[K]) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
|
func (s *Service[K]) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
|
||||||
var key [KeyLength]byte
|
var key [KeyLength]byte
|
||||||
n, err := conn.Read(common.Dup(key[:]))
|
n, err := conn.Read(key[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if n != KeyLength {
|
} else if n != KeyLength {
|
||||||
|
@ -12,7 +12,6 @@ import (
|
|||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
"github.com/sagernet/sing-box/transport/hysteria"
|
"github.com/sagernet/sing-box/transport/hysteria"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
)
|
)
|
||||||
@ -24,7 +23,6 @@ type Server struct {
|
|||||||
tlsConfig *tls.STDConfig
|
tlsConfig *tls.STDConfig
|
||||||
quicConfig *quic.Config
|
quicConfig *quic.Config
|
||||||
handler adapter.V2RayServerTransportHandler
|
handler adapter.V2RayServerTransportHandler
|
||||||
errorHandler E.Handler
|
|
||||||
udpListener net.PacketConn
|
udpListener net.PacketConn
|
||||||
quicListener *quic.Listener
|
quicListener *quic.Listener
|
||||||
}
|
}
|
||||||
@ -77,7 +75,7 @@ func (s *Server) acceptLoop() {
|
|||||||
go func() {
|
go func() {
|
||||||
hErr := s.streamAcceptLoop(conn)
|
hErr := s.streamAcceptLoop(conn)
|
||||||
if hErr != nil {
|
if hErr != nil {
|
||||||
s.errorHandler.NewError(conn.Context(), hErr)
|
s.handler.NewError(conn.Context(), hErr)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
@ -94,5 +92,5 @@ func (s *Server) streamAcceptLoop(conn quic.Connection) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Close() error {
|
func (s *Server) Close() error {
|
||||||
return common.Close(s.udpListener, s.quicListener)
|
return common.Close(s.udpListener, common.PtrOrNil(s.quicListener))
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,8 @@ var _ adapter.V2RayClientTransport = (*Client)(nil)
|
|||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
dialer *websocket.Dialer
|
dialer *websocket.Dialer
|
||||||
uri string
|
requestURL url.URL
|
||||||
|
requestURLString string
|
||||||
headers http.Header
|
headers http.Header
|
||||||
maxEarlyData uint32
|
maxEarlyData uint32
|
||||||
earlyDataHeaderName string
|
earlyDataHeaderName string
|
||||||
@ -57,15 +58,15 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
|
|||||||
return &deadConn{conn}, nil
|
return &deadConn{conn}, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var uri url.URL
|
var requestURL url.URL
|
||||||
if tlsConfig == nil {
|
if tlsConfig == nil {
|
||||||
uri.Scheme = "ws"
|
requestURL.Scheme = "ws"
|
||||||
} else {
|
} else {
|
||||||
uri.Scheme = "wss"
|
requestURL.Scheme = "wss"
|
||||||
}
|
}
|
||||||
uri.Host = serverAddr.String()
|
requestURL.Host = serverAddr.String()
|
||||||
uri.Path = options.Path
|
requestURL.Path = options.Path
|
||||||
err := sHTTP.URLSetPath(&uri, options.Path)
|
err := sHTTP.URLSetPath(&requestURL, options.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -75,7 +76,8 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
|
|||||||
}
|
}
|
||||||
return &Client{
|
return &Client{
|
||||||
wsDialer,
|
wsDialer,
|
||||||
uri.String(),
|
requestURL,
|
||||||
|
requestURL.String(),
|
||||||
headers,
|
headers,
|
||||||
options.MaxEarlyData,
|
options.MaxEarlyData,
|
||||||
options.EarlyDataHeaderName,
|
options.EarlyDataHeaderName,
|
||||||
@ -84,7 +86,7 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
|
|||||||
|
|
||||||
func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
|
func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
|
||||||
if c.maxEarlyData <= 0 {
|
if c.maxEarlyData <= 0 {
|
||||||
conn, response, err := c.dialer.DialContext(ctx, c.uri, c.headers)
|
conn, response, err := c.dialer.DialContext(ctx, c.requestURLString, c.headers)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return &WebsocketConn{Conn: conn, Writer: NewWriter(conn, false)}, nil
|
return &WebsocketConn{Conn: conn, Writer: NewWriter(conn, false)}, nil
|
||||||
}
|
}
|
||||||
|
@ -94,51 +94,64 @@ type EarlyWebsocketConn struct {
|
|||||||
ctx context.Context
|
ctx context.Context
|
||||||
conn *WebsocketConn
|
conn *WebsocketConn
|
||||||
create chan struct{}
|
create chan struct{}
|
||||||
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *EarlyWebsocketConn) Read(b []byte) (n int, err error) {
|
func (c *EarlyWebsocketConn) Read(b []byte) (n int, err error) {
|
||||||
if c.conn == nil {
|
if c.conn == nil {
|
||||||
<-c.create
|
<-c.create
|
||||||
|
if c.err != nil {
|
||||||
|
return 0, c.err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return c.conn.Read(b)
|
return c.conn.Read(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *EarlyWebsocketConn) writeRequest(content []byte) error {
|
||||||
|
var (
|
||||||
|
earlyData []byte
|
||||||
|
lateData []byte
|
||||||
|
conn *websocket.Conn
|
||||||
|
response *http.Response
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if len(content) > int(c.maxEarlyData) {
|
||||||
|
earlyData = content[:c.maxEarlyData]
|
||||||
|
lateData = content[c.maxEarlyData:]
|
||||||
|
} else {
|
||||||
|
earlyData = content
|
||||||
|
}
|
||||||
|
if len(earlyData) > 0 {
|
||||||
|
earlyDataString := base64.RawURLEncoding.EncodeToString(earlyData)
|
||||||
|
if c.earlyDataHeaderName == "" {
|
||||||
|
requestURL := c.requestURL
|
||||||
|
requestURL.Path += earlyDataString
|
||||||
|
conn, response, err = c.dialer.DialContext(c.ctx, requestURL.String(), c.headers)
|
||||||
|
} else {
|
||||||
|
headers := c.headers.Clone()
|
||||||
|
headers.Set(c.earlyDataHeaderName, earlyDataString)
|
||||||
|
conn, response, err = c.dialer.DialContext(c.ctx, c.requestURLString, headers)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
conn, response, err = c.dialer.DialContext(c.ctx, c.requestURLString, c.headers)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return wrapDialError(response, err)
|
||||||
|
}
|
||||||
|
c.conn = &WebsocketConn{Conn: conn, Writer: NewWriter(conn, false)}
|
||||||
|
if len(lateData) > 0 {
|
||||||
|
_, err = c.conn.Write(lateData)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (c *EarlyWebsocketConn) Write(b []byte) (n int, err error) {
|
func (c *EarlyWebsocketConn) Write(b []byte) (n int, err error) {
|
||||||
if c.conn != nil {
|
if c.conn != nil {
|
||||||
return c.conn.Write(b)
|
return c.conn.Write(b)
|
||||||
}
|
}
|
||||||
var (
|
err = c.writeRequest(b)
|
||||||
earlyData []byte
|
c.err = err
|
||||||
lateData []byte
|
|
||||||
conn *websocket.Conn
|
|
||||||
response *http.Response
|
|
||||||
)
|
|
||||||
if len(b) > int(c.maxEarlyData) {
|
|
||||||
earlyData = b[:c.maxEarlyData]
|
|
||||||
lateData = b[c.maxEarlyData:]
|
|
||||||
} else {
|
|
||||||
earlyData = b
|
|
||||||
}
|
|
||||||
if len(earlyData) > 0 {
|
|
||||||
earlyDataString := base64.RawURLEncoding.EncodeToString(earlyData)
|
|
||||||
if c.earlyDataHeaderName == "" {
|
|
||||||
conn, response, err = c.dialer.DialContext(c.ctx, c.uri+earlyDataString, c.headers)
|
|
||||||
} else {
|
|
||||||
headers := c.headers.Clone()
|
|
||||||
headers.Set(c.earlyDataHeaderName, earlyDataString)
|
|
||||||
conn, response, err = c.dialer.DialContext(c.ctx, c.uri, headers)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
conn, response, err = c.dialer.DialContext(c.ctx, c.uri, c.headers)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return 0, wrapDialError(response, err)
|
|
||||||
}
|
|
||||||
c.conn = &WebsocketConn{Conn: conn, Writer: NewWriter(conn, false)}
|
|
||||||
close(c.create)
|
close(c.create)
|
||||||
if len(lateData) > 0 {
|
|
||||||
_, err = c.conn.Write(lateData)
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -149,39 +162,9 @@ func (c *EarlyWebsocketConn) WriteBuffer(buffer *buf.Buffer) error {
|
|||||||
if c.conn != nil {
|
if c.conn != nil {
|
||||||
return c.conn.WriteBuffer(buffer)
|
return c.conn.WriteBuffer(buffer)
|
||||||
}
|
}
|
||||||
var (
|
err := c.writeRequest(buffer.Bytes())
|
||||||
earlyData []byte
|
c.err = err
|
||||||
lateData []byte
|
|
||||||
conn *websocket.Conn
|
|
||||||
response *http.Response
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
if buffer.Len() > int(c.maxEarlyData) {
|
|
||||||
earlyData = buffer.Bytes()[:c.maxEarlyData]
|
|
||||||
lateData = buffer.Bytes()[c.maxEarlyData:]
|
|
||||||
} else {
|
|
||||||
earlyData = buffer.Bytes()
|
|
||||||
}
|
|
||||||
if len(earlyData) > 0 {
|
|
||||||
earlyDataString := base64.RawURLEncoding.EncodeToString(earlyData)
|
|
||||||
if c.earlyDataHeaderName == "" {
|
|
||||||
conn, response, err = c.dialer.DialContext(c.ctx, c.uri+earlyDataString, c.headers)
|
|
||||||
} else {
|
|
||||||
headers := c.headers.Clone()
|
|
||||||
headers.Set(c.earlyDataHeaderName, earlyDataString)
|
|
||||||
conn, response, err = c.dialer.DialContext(c.ctx, c.uri, headers)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
conn, response, err = c.dialer.DialContext(c.ctx, c.uri, c.headers)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return wrapDialError(response, err)
|
|
||||||
}
|
|
||||||
c.conn = &WebsocketConn{Conn: conn, Writer: NewWriter(conn, false)}
|
|
||||||
close(c.create)
|
close(c.create)
|
||||||
if len(lateData) > 0 {
|
|
||||||
_, err = c.conn.Write(lateData)
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,9 +139,7 @@ func WriteRequest(writer io.Writer, request Request, payload []byte) error {
|
|||||||
requestLen += vmess.AddressSerializer.AddrPortLen(request.Destination)
|
requestLen += vmess.AddressSerializer.AddrPortLen(request.Destination)
|
||||||
}
|
}
|
||||||
requestLen += len(payload)
|
requestLen += len(payload)
|
||||||
_buffer := buf.StackNewSize(requestLen)
|
buffer := buf.NewSize(requestLen)
|
||||||
defer common.KeepAlive(_buffer)
|
|
||||||
buffer := common.Dup(_buffer)
|
|
||||||
defer buffer.Release()
|
defer buffer.Release()
|
||||||
common.Must(
|
common.Must(
|
||||||
buffer.WriteByte(Version),
|
buffer.WriteByte(Version),
|
||||||
@ -239,9 +237,7 @@ func WritePacketRequest(writer io.Writer, request Request, payload []byte) error
|
|||||||
requestLen += 2
|
requestLen += 2
|
||||||
requestLen += len(payload)
|
requestLen += len(payload)
|
||||||
}
|
}
|
||||||
_buffer := buf.StackNewSize(requestLen)
|
buffer := buf.NewSize(requestLen)
|
||||||
defer common.KeepAlive(_buffer)
|
|
||||||
buffer := common.Dup(_buffer)
|
|
||||||
defer buffer.Release()
|
defer buffer.Release()
|
||||||
common.Must(
|
common.Must(
|
||||||
buffer.WriteByte(Version),
|
buffer.WriteByte(Version),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user