mirror of
https://github.com/SagerNet/sing-box.git
synced 2026-04-13 20:28:32 +10:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a792b186a | ||
|
|
3f458064a3 | ||
|
|
5269231df0 | ||
|
|
fc8e49994c | ||
|
|
e911d4aa4b | ||
|
|
01f6e70bc5 |
@@ -43,7 +43,7 @@ type OutboundGroup interface {
|
|||||||
|
|
||||||
type URLTestGroup interface {
|
type URLTestGroup interface {
|
||||||
OutboundGroup
|
OutboundGroup
|
||||||
URLTest(ctx context.Context, url string) (map[string]uint16, error)
|
URLTest(ctx context.Context) (map[string]uint16, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func OutboundTag(detour Outbound) string {
|
func OutboundTag(detour Outbound) string {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import (
|
|||||||
|
|
||||||
type Router interface {
|
type Router interface {
|
||||||
Service
|
Service
|
||||||
|
PostStarter
|
||||||
|
|
||||||
Outbounds() []Outbound
|
Outbounds() []Outbound
|
||||||
Outbound(tag string) (Outbound, bool)
|
Outbound(tag string) (Outbound, bool)
|
||||||
|
|||||||
15
box.go
15
box.go
@@ -258,7 +258,7 @@ 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
|
return s.postStart()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Box) postStart() error {
|
func (s *Box) postStart() error {
|
||||||
@@ -269,16 +269,17 @@ func (s *Box) postStart() error {
|
|||||||
return E.Cause(err, "start ", serviceName)
|
return E.Cause(err, "start ", serviceName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for serviceName, service := range s.outbounds {
|
for _, outbound := range s.outbounds {
|
||||||
if lateService, isLateService := service.(adapter.PostStarter); isLateService {
|
if lateOutbound, isLateOutbound := outbound.(adapter.PostStarter); isLateOutbound {
|
||||||
s.logger.Trace("post-starting ", service)
|
s.logger.Trace("post-starting outbound/", outbound.Tag())
|
||||||
err := lateService.PostStart()
|
err := lateOutbound.PostStart()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(err, "post-start ", serviceName)
|
return E.Cause(err, "post-start outbound/", outbound.Tag())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
s.logger.Trace("post-starting router")
|
||||||
|
return s.router.PostStart()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Box) Close() error {
|
func (s *Box) Close() error {
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing/common/bufio/deadline"
|
|
||||||
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"
|
||||||
@@ -45,14 +44,7 @@ func (d *DetourDialer) DialContext(ctx context.Context, network string, destinat
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
conn, err := dialer.DialContext(ctx, network, destination)
|
return dialer.DialContext(ctx, network, destination)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if deadline.NeedAdditionalReadDeadline(conn) {
|
|
||||||
conn = deadline.NewConn(conn)
|
|
||||||
}
|
|
||||||
return conn, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DetourDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
func (d *DetourDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
|
|||||||
@@ -4,6 +4,14 @@ icon: material/alert-decagram
|
|||||||
|
|
||||||
# ChangeLog
|
# ChangeLog
|
||||||
|
|
||||||
|
#### 1.7.2
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
#### 1.7.1
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
#### 1.7.0
|
#### 1.7.0
|
||||||
|
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ func getGroupDelay(server *Server) func(w http.ResponseWriter, r *http.Request)
|
|||||||
|
|
||||||
var result map[string]uint16
|
var result map[string]uint16
|
||||||
if urlTestGroup, isURLTestGroup := group.(adapter.URLTestGroup); isURLTestGroup {
|
if urlTestGroup, isURLTestGroup := group.(adapter.URLTestGroup); isURLTestGroup {
|
||||||
result, err = urlTestGroup.URLTest(ctx, url)
|
result, err = urlTestGroup.URLTest(ctx)
|
||||||
} else {
|
} else {
|
||||||
outbounds := common.FilterNotNil(common.Map(group.All(), func(it string) adapter.Outbound {
|
outbounds := common.FilterNotNil(common.Map(group.All(), func(it string) adapter.Outbound {
|
||||||
itOutbound, _ := server.router.Outbound(it)
|
itOutbound, _ := server.router.Outbound(it)
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -26,7 +26,7 @@ require (
|
|||||||
github.com/sagernet/gvisor v0.0.0-20231119034329-07cfb6aaf930
|
github.com/sagernet/gvisor v0.0.0-20231119034329-07cfb6aaf930
|
||||||
github.com/sagernet/quic-go v0.40.0
|
github.com/sagernet/quic-go v0.40.0
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
||||||
github.com/sagernet/sing v0.2.18-0.20231124125253-2dcabf4bfcbc
|
github.com/sagernet/sing v0.2.18-0.20231203085253-0ba5576c7be8
|
||||||
github.com/sagernet/sing-dns v0.1.11
|
github.com/sagernet/sing-dns v0.1.11
|
||||||
github.com/sagernet/sing-mux v0.1.5-0.20231109075101-6b086ed6bb07
|
github.com/sagernet/sing-mux v0.1.5-0.20231109075101-6b086ed6bb07
|
||||||
github.com/sagernet/sing-quic v0.1.5-0.20231123150216-00957d136203
|
github.com/sagernet/sing-quic v0.1.5-0.20231123150216-00957d136203
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -110,8 +110,8 @@ 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.18-0.20231124125253-2dcabf4bfcbc h1:vESVuxHgbd2EzHxd+TYTpNACIEGBOhp5n3KG7bgbcws=
|
github.com/sagernet/sing v0.2.18-0.20231203085253-0ba5576c7be8 h1:wQuG3Kfob9jppmkamoRmvUE4nwTltxLhDGeeGUD66Dk=
|
||||||
github.com/sagernet/sing v0.2.18-0.20231124125253-2dcabf4bfcbc/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo=
|
github.com/sagernet/sing v0.2.18-0.20231203085253-0ba5576c7be8/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo=
|
||||||
github.com/sagernet/sing-dns v0.1.11 h1:PPrMCVVrAeR3f5X23I+cmvacXJ+kzuyAsBiWyUKhGSE=
|
github.com/sagernet/sing-dns v0.1.11 h1:PPrMCVVrAeR3f5X23I+cmvacXJ+kzuyAsBiWyUKhGSE=
|
||||||
github.com/sagernet/sing-dns v0.1.11/go.mod h1:zJ/YjnYB61SYE+ubMcMqVdpaSvsyQ2iShQGO3vuLvvE=
|
github.com/sagernet/sing-dns v0.1.11/go.mod h1:zJ/YjnYB61SYE+ubMcMqVdpaSvsyQ2iShQGO3vuLvvE=
|
||||||
github.com/sagernet/sing-mux v0.1.5-0.20231109075101-6b086ed6bb07 h1:ncKb5tVOsCQgCsv6UpsA0jinbNb5OQ5GMPJlyQP3EHM=
|
github.com/sagernet/sing-mux v0.1.5-0.20231109075101-6b086ed6bb07 h1:ncKb5tVOsCQgCsv6UpsA0jinbNb5OQ5GMPJlyQP3EHM=
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package outbound
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
"sort"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -83,7 +82,7 @@ func (s *URLTest) Start() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *URLTest) PostStart() error {
|
func (s *URLTest) PostStart() error {
|
||||||
go s.CheckOutbounds()
|
s.group.PostStart()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,8 +100,8 @@ func (s *URLTest) All() []string {
|
|||||||
return s.tags
|
return s.tags
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *URLTest) URLTest(ctx context.Context, link string) (map[string]uint16, error) {
|
func (s *URLTest) URLTest(ctx context.Context) (map[string]uint16, error) {
|
||||||
return s.group.URLTest(ctx, link)
|
return s.group.URLTest(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *URLTest) CheckOutbounds() {
|
func (s *URLTest) CheckOutbounds() {
|
||||||
@@ -110,7 +109,7 @@ func (s *URLTest) CheckOutbounds() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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.Touch()
|
||||||
outbound := s.group.Select(network)
|
outbound := s.group.Select(network)
|
||||||
conn, err := outbound.DialContext(ctx, network, destination)
|
conn, err := outbound.DialContext(ctx, network, destination)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -122,7 +121,7 @@ func (s *URLTest) DialContext(ctx context.Context, network string, destination M
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *URLTest) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
func (s *URLTest) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
s.group.Start()
|
s.group.Touch()
|
||||||
outbound := s.group.Select(N.NetworkUDP)
|
outbound := s.group.Select(N.NetworkUDP)
|
||||||
conn, err := outbound.ListenPacket(ctx, destination)
|
conn, err := outbound.ListenPacket(ctx, destination)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -164,9 +163,11 @@ type URLTestGroup struct {
|
|||||||
interruptGroup *interrupt.Group
|
interruptGroup *interrupt.Group
|
||||||
interruptExternalConnections bool
|
interruptExternalConnections bool
|
||||||
|
|
||||||
access sync.Mutex
|
access sync.Mutex
|
||||||
ticker *time.Ticker
|
ticker *time.Ticker
|
||||||
close chan struct{}
|
close chan struct{}
|
||||||
|
started bool
|
||||||
|
lastActive atomic.TypedValue[time.Time]
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewURLTestGroup(
|
func NewURLTestGroup(
|
||||||
@@ -208,8 +209,18 @@ func NewURLTestGroup(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *URLTestGroup) Start() {
|
func (g *URLTestGroup) PostStart() {
|
||||||
|
g.started = true
|
||||||
|
g.lastActive.Store(time.Now())
|
||||||
|
go g.CheckOutbounds(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *URLTestGroup) Touch() {
|
||||||
|
if !g.started {
|
||||||
|
return
|
||||||
|
}
|
||||||
if g.ticker != nil {
|
if g.ticker != nil {
|
||||||
|
g.lastActive.Store(time.Now())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
g.access.Lock()
|
g.access.Lock()
|
||||||
@@ -260,51 +271,30 @@ func (g *URLTestGroup) Select(network string) adapter.Outbound {
|
|||||||
return minOutbound
|
return minOutbound
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *URLTestGroup) Fallback(used adapter.Outbound) []adapter.Outbound {
|
|
||||||
outbounds := make([]adapter.Outbound, 0, len(g.outbounds)-1)
|
|
||||||
for _, detour := range g.outbounds {
|
|
||||||
if detour != used {
|
|
||||||
outbounds = append(outbounds, detour)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort.SliceStable(outbounds, func(i, j int) bool {
|
|
||||||
oi := outbounds[i]
|
|
||||||
oj := outbounds[j]
|
|
||||||
hi := g.history.LoadURLTestHistory(RealTag(oi))
|
|
||||||
if hi == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
hj := g.history.LoadURLTestHistory(RealTag(oj))
|
|
||||||
if hj == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return hi.Delay < hj.Delay
|
|
||||||
})
|
|
||||||
return outbounds
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *URLTestGroup) loopCheck() {
|
func (g *URLTestGroup) loopCheck() {
|
||||||
go g.CheckOutbounds(true)
|
if time.Now().Sub(g.lastActive.Load()) > g.interval {
|
||||||
|
g.CheckOutbounds(false)
|
||||||
|
}
|
||||||
for {
|
for {
|
||||||
g.pauseManager.WaitActive()
|
|
||||||
select {
|
select {
|
||||||
case <-g.close:
|
case <-g.close:
|
||||||
return
|
return
|
||||||
case <-g.ticker.C:
|
case <-g.ticker.C:
|
||||||
g.CheckOutbounds(false)
|
|
||||||
}
|
}
|
||||||
|
g.pauseManager.WaitActive()
|
||||||
|
g.CheckOutbounds(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *URLTestGroup) CheckOutbounds(force bool) {
|
func (g *URLTestGroup) CheckOutbounds(force bool) {
|
||||||
_, _ = g.urlTest(g.ctx, g.link, force)
|
_, _ = g.urlTest(g.ctx, force)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *URLTestGroup) URLTest(ctx context.Context, link string) (map[string]uint16, error) {
|
func (g *URLTestGroup) URLTest(ctx context.Context) (map[string]uint16, error) {
|
||||||
return g.urlTest(ctx, link, false)
|
return g.urlTest(ctx, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *URLTestGroup) urlTest(ctx context.Context, link string, force bool) (map[string]uint16, error) {
|
func (g *URLTestGroup) urlTest(ctx context.Context, force bool) (map[string]uint16, error) {
|
||||||
result := make(map[string]uint16)
|
result := make(map[string]uint16)
|
||||||
if g.checking.Swap(true) {
|
if g.checking.Swap(true) {
|
||||||
return result, nil
|
return result, nil
|
||||||
@@ -331,7 +321,7 @@ func (g *URLTestGroup) urlTest(ctx context.Context, link string, force bool) (ma
|
|||||||
b.Go(realTag, func() (any, error) {
|
b.Go(realTag, func() (any, error) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), C.TCPTimeout)
|
ctx, cancel := context.WithTimeout(context.Background(), C.TCPTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
t, err := urltest.URLTest(ctx, link, p)
|
t, err := urltest.URLTest(ctx, g.link, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
g.logger.Debug("outbound ", tag, " unavailable: ", err)
|
g.logger.Debug("outbound ", tag, " unavailable: ", err)
|
||||||
g.history.DeleteURLTestHistory(realTag)
|
g.history.DeleteURLTestHistory(realTag)
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ type Router struct {
|
|||||||
platformInterface platform.Interface
|
platformInterface platform.Interface
|
||||||
needWIFIState bool
|
needWIFIState bool
|
||||||
wifiState adapter.WIFIState
|
wifiState adapter.WIFIState
|
||||||
|
started bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRouter(
|
func NewRouter(
|
||||||
@@ -571,6 +572,11 @@ func (r *Router) Close() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Router) PostStart() error {
|
||||||
|
r.started = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Router) Outbound(tag string) (adapter.Outbound, bool) {
|
func (r *Router) Outbound(tag string) (adapter.Outbound, bool) {
|
||||||
outbound, loaded := r.outboundByTag[tag]
|
outbound, loaded := r.outboundByTag[tag]
|
||||||
return outbound, loaded
|
return outbound, loaded
|
||||||
@@ -1015,8 +1021,11 @@ func (r *Router) notifyNetworkUpdate(event int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r.ResetNetwork()
|
if !r.started {
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = r.ResetNetwork()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) ResetNetwork() error {
|
func (r *Router) ResetNetwork() error {
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ import (
|
|||||||
"github.com/sagernet/sing-box/common/tls"
|
"github.com/sagernet/sing-box/common/tls"
|
||||||
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/common/buf"
|
||||||
|
"github.com/sagernet/sing/common/bufio"
|
||||||
|
"github.com/sagernet/sing/common/bufio/deadline"
|
||||||
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"
|
||||||
@@ -87,18 +90,35 @@ func (c *Client) dialContext(ctx context.Context, requestURL *url.URL, headers h
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
conn.SetDeadline(time.Now().Add(C.TCPTimeout))
|
var deadlineConn net.Conn
|
||||||
|
if deadline.NeedAdditionalReadDeadline(conn) {
|
||||||
|
deadlineConn = deadline.NewConn(conn)
|
||||||
|
} else {
|
||||||
|
deadlineConn = conn
|
||||||
|
}
|
||||||
|
err = deadlineConn.SetDeadline(time.Now().Add(C.TCPTimeout))
|
||||||
|
if err != nil {
|
||||||
|
return nil, E.Cause(err, "set read deadline")
|
||||||
|
}
|
||||||
var protocols []string
|
var protocols []string
|
||||||
if protocolHeader := headers.Get("Sec-WebSocket-Protocol"); protocolHeader != "" {
|
if protocolHeader := headers.Get("Sec-WebSocket-Protocol"); protocolHeader != "" {
|
||||||
protocols = []string{protocolHeader}
|
protocols = []string{protocolHeader}
|
||||||
headers.Del("Sec-WebSocket-Protocol")
|
headers.Del("Sec-WebSocket-Protocol")
|
||||||
}
|
}
|
||||||
reader, _, err := ws.Dialer{Header: ws.HandshakeHeaderHTTP(headers), Protocols: protocols}.Upgrade(conn, requestURL)
|
reader, _, err := ws.Dialer{Header: ws.HandshakeHeaderHTTP(headers), Protocols: protocols}.Upgrade(deadlineConn, requestURL)
|
||||||
conn.SetDeadline(time.Time{})
|
deadlineConn.SetDeadline(time.Time{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return NewConn(conn, reader, nil, ws.StateClientSide), nil
|
if reader != nil {
|
||||||
|
buffer := buf.NewSize(reader.Buffered())
|
||||||
|
_, err = buffer.ReadFullFrom(reader, buffer.Len())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conn = bufio.NewCachedConn(conn, buffer)
|
||||||
|
}
|
||||||
|
return NewConn(conn, nil, ws.StateClientSide), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
|
func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package v2raywebsocket
|
package v2raywebsocket
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"io"
|
"io"
|
||||||
@@ -28,19 +27,13 @@ type WebsocketConn struct {
|
|||||||
remoteAddr net.Addr
|
remoteAddr net.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConn(conn net.Conn, br *bufio.Reader, remoteAddr net.Addr, state ws.State) *WebsocketConn {
|
func NewConn(conn net.Conn, remoteAddr net.Addr, state ws.State) *WebsocketConn {
|
||||||
controlHandler := wsutil.ControlFrameHandler(conn, state)
|
controlHandler := wsutil.ControlFrameHandler(conn, state)
|
||||||
var reader io.Reader
|
|
||||||
if br != nil && br.Buffered() > 0 {
|
|
||||||
reader = br
|
|
||||||
} else {
|
|
||||||
reader = conn
|
|
||||||
}
|
|
||||||
return &WebsocketConn{
|
return &WebsocketConn{
|
||||||
Conn: conn,
|
Conn: conn,
|
||||||
state: state,
|
state: state,
|
||||||
reader: &wsutil.Reader{
|
reader: &wsutil.Reader{
|
||||||
Source: reader,
|
Source: conn,
|
||||||
State: state,
|
State: state,
|
||||||
SkipHeaderCheck: !debug.Enabled,
|
SkipHeaderCheck: !debug.Enabled,
|
||||||
OnIntermediate: controlHandler,
|
OnIntermediate: controlHandler,
|
||||||
|
|||||||
@@ -88,14 +88,14 @@ func (s *Server) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
|||||||
s.invalidRequest(writer, request, http.StatusBadRequest, E.Cause(err, "decode early data"))
|
s.invalidRequest(writer, request, http.StatusBadRequest, E.Cause(err, "decode early data"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
wsConn, reader, _, err := ws.UpgradeHTTP(request, writer)
|
wsConn, _, _, err := ws.UpgradeHTTP(request, writer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.invalidRequest(writer, request, 0, E.Cause(err, "upgrade websocket connection"))
|
s.invalidRequest(writer, request, 0, E.Cause(err, "upgrade websocket connection"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var metadata M.Metadata
|
var metadata M.Metadata
|
||||||
metadata.Source = sHttp.SourceAddress(request)
|
metadata.Source = sHttp.SourceAddress(request)
|
||||||
conn = NewConn(wsConn, reader.Reader, metadata.Source.TCPAddr(), ws.StateServerSide)
|
conn = NewConn(wsConn, metadata.Source.TCPAddr(), ws.StateServerSide)
|
||||||
if len(earlyData) > 0 {
|
if len(earlyData) > 0 {
|
||||||
conn = bufio.NewCachedConn(conn, buf.As(earlyData))
|
conn = bufio.NewCachedConn(conn, buf.As(earlyData))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user