mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-22 00:21:30 +00:00
Add v2ray QUIC transport
This commit is contained in:
parent
77c98fd042
commit
d4b7e221f0
|
@ -6,7 +6,9 @@ import (
|
|||
)
|
||||
|
||||
type V2RayServerTransport interface {
|
||||
Network() []string
|
||||
Serve(listener net.Listener) error
|
||||
ServePacket(listener net.PacketConn) error
|
||||
Close() error
|
||||
}
|
||||
|
||||
|
|
|
@ -2,4 +2,8 @@
|
|||
|
||||
package constant
|
||||
|
||||
import E "github.com/sagernet/sing/common/exceptions"
|
||||
|
||||
const QUIC_AVAILABLE = false
|
||||
|
||||
var ErrQUICNotIncluded = E.New(`QUIC is not included in this build, rebuild with -tags with_quic`)
|
||||
|
|
|
@ -3,4 +3,5 @@ package constant
|
|||
const (
|
||||
V2RayTransportTypeGRPC = "grpc"
|
||||
V2RayTransportTypeWebsocket = "ws"
|
||||
V2RayTransportTypeQUIC = "quic"
|
||||
)
|
||||
|
|
|
@ -129,6 +129,18 @@ func (a *myInboundAdapter) ListenTCP() (*net.TCPListener, error) {
|
|||
return tcpListener, err
|
||||
}
|
||||
|
||||
func (a *myInboundAdapter) ListenUDP() (*net.UDPConn, error) {
|
||||
bindAddr := M.SocksaddrFrom(netip.Addr(a.listenOptions.Listen), a.listenOptions.ListenPort)
|
||||
udpConn, err := net.ListenUDP(M.NetworkFromNetAddr(N.NetworkUDP, bindAddr.Addr), bindAddr.UDPAddr())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a.udpConn = udpConn
|
||||
a.udpAddr = bindAddr
|
||||
a.logger.Info("udp server started at ", udpConn.LocalAddr())
|
||||
return udpConn, err
|
||||
}
|
||||
|
||||
func (a *myInboundAdapter) Close() error {
|
||||
var err error
|
||||
if a.clearSystemProxy != nil {
|
||||
|
|
|
@ -6,11 +6,11 @@ import (
|
|||
"context"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
)
|
||||
|
||||
func NewHysteria(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.HysteriaInboundOptions) (adapter.Inbound, error) {
|
||||
return nil, E.New(`QUIC is not included in this build, rebuild with -tags with_quic`)
|
||||
return nil, C.ErrQUICNotIncluded
|
||||
}
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
|
||||
package inbound
|
||||
|
||||
import E "github.com/sagernet/sing/common/exceptions"
|
||||
import (
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
)
|
||||
|
||||
func (n *Naive) configureHTTP3Listener(listenAddr string) error {
|
||||
return E.New("QUIC is not included in this build, rebuild with -tags with_quic")
|
||||
return C.ErrQUICNotIncluded
|
||||
}
|
||||
|
|
|
@ -83,16 +83,30 @@ func (h *VMess) Start() error {
|
|||
if h.transport == nil {
|
||||
return h.myInboundAdapter.Start()
|
||||
}
|
||||
tcpListener, err := h.myInboundAdapter.ListenTCP()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go func() {
|
||||
sErr := h.transport.Serve(tcpListener)
|
||||
if sErr != nil && !E.IsClosed(sErr) {
|
||||
h.logger.Error("transport serve error: ", sErr)
|
||||
if common.Contains(h.transport.Network(), N.NetworkTCP) {
|
||||
tcpListener, err := h.myInboundAdapter.ListenTCP()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
sErr := h.transport.Serve(tcpListener)
|
||||
if sErr != nil && !E.IsClosed(sErr) {
|
||||
h.logger.Error("transport serve error: ", sErr)
|
||||
}
|
||||
}()
|
||||
}
|
||||
if common.Contains(h.transport.Network(), N.NetworkUDP) {
|
||||
udpConn, err := h.myInboundAdapter.ListenUDP()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go func() {
|
||||
sErr := h.transport.ServePacket(udpConn)
|
||||
if sErr != nil && !E.IsClosed(sErr) {
|
||||
h.logger.Error("transport serve error: ", sErr)
|
||||
}
|
||||
}()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ type _V2RayTransportOptions struct {
|
|||
Type string `json:"type,omitempty"`
|
||||
GRPCOptions V2RayGRPCOptions `json:"-"`
|
||||
WebsocketOptions V2RayWebsocketOptions `json:"-"`
|
||||
QUICOptions V2RayQUICOptions `json:"-"`
|
||||
}
|
||||
|
||||
type V2RayTransportOptions _V2RayTransportOptions
|
||||
|
@ -23,6 +24,8 @@ func (o V2RayTransportOptions) MarshalJSON() ([]byte, error) {
|
|||
v = o.GRPCOptions
|
||||
case C.V2RayTransportTypeWebsocket:
|
||||
v = o.WebsocketOptions
|
||||
case C.V2RayTransportTypeQUIC:
|
||||
v = o.QUICOptions
|
||||
default:
|
||||
return nil, E.New("unknown transport type: " + o.Type)
|
||||
}
|
||||
|
@ -38,6 +41,10 @@ func (o *V2RayTransportOptions) UnmarshalJSON(bytes []byte) error {
|
|||
switch o.Type {
|
||||
case C.V2RayTransportTypeGRPC:
|
||||
v = &o.GRPCOptions
|
||||
case C.V2RayTransportTypeWebsocket:
|
||||
v = &o.WebsocketOptions
|
||||
case C.V2RayTransportTypeQUIC:
|
||||
v = &o.QUICOptions
|
||||
default:
|
||||
return E.New("unknown transport type: " + o.Type)
|
||||
}
|
||||
|
@ -102,3 +109,5 @@ type V2RayWebsocketOptions struct {
|
|||
MaxEarlyData uint32 `json:"max_early_data,omitempty"`
|
||||
EarlyDataHeaderName string `json:"early_data_header_name,omitempty"`
|
||||
}
|
||||
|
||||
type V2RayQUICOptions struct{}
|
||||
|
|
|
@ -6,11 +6,11 @@ import (
|
|||
"context"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
)
|
||||
|
||||
func NewHysteria(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.HysteriaOutboundOptions) (adapter.Outbound, error) {
|
||||
return nil, E.New(`QUIC is not included in this build, rebuild with -tags with_quic`)
|
||||
return nil, C.ErrQUICNotIncluded
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ func testTCP(t *testing.T, clientPort uint16, testPort uint16) {
|
|||
require.NoError(t, testPingPongWithConn(t, testPort, dialTCP))
|
||||
}
|
||||
|
||||
func testSuitHy(t *testing.T, clientPort uint16, testPort uint16) {
|
||||
func testSuitQUIC(t *testing.T, clientPort uint16, testPort uint16) {
|
||||
dialer := socks.NewClient(N.SystemDialer, M.ParseSocksaddrHostPort("127.0.0.1", clientPort), socks.Version5, "", "")
|
||||
dialTCP := func() (net.Conn, error) {
|
||||
return dialer.DialContext(context.Background(), "tcp", M.ParseSocksaddrHostPort("127.0.0.1", testPort))
|
||||
|
|
|
@ -83,7 +83,7 @@ func TestHysteriaSelf(t *testing.T) {
|
|||
},
|
||||
},
|
||||
})
|
||||
testSuitHy(t, clientPort, testPort)
|
||||
testSuitQUIC(t, clientPort, testPort)
|
||||
}
|
||||
|
||||
func TestHysteriaInbound(t *testing.T) {
|
||||
|
@ -180,5 +180,5 @@ func TestHysteriaOutbound(t *testing.T) {
|
|||
},
|
||||
},
|
||||
})
|
||||
testSuitHy(t, clientPort, testPort)
|
||||
testSuitQUIC(t, clientPort, testPort)
|
||||
}
|
||||
|
|
|
@ -59,8 +59,7 @@ func TestTrojanSelf(t *testing.T) {
|
|||
_, certPem, keyPem := createSelfSignedCertificate(t, "example.org")
|
||||
startInstance(t, option.Options{
|
||||
Log: &option.LogOptions{
|
||||
Level: "error",
|
||||
Output: "stderr",
|
||||
Level: "error",
|
||||
},
|
||||
Inbounds: []option.Inbound{
|
||||
{
|
||||
|
|
|
@ -229,8 +229,7 @@ func testVMessOutboundWithV2Ray(t *testing.T, security string, uuid uuid.UUID, g
|
|||
func testVMessSelf(t *testing.T, security string, uuid uuid.UUID, alterId int, globalPadding bool, authenticatedLength bool) {
|
||||
startInstance(t, option.Options{
|
||||
Log: &option.LogOptions{
|
||||
Level: "error",
|
||||
Output: "stderr",
|
||||
Level: "error",
|
||||
},
|
||||
Inbounds: []option.Inbound{
|
||||
{
|
||||
|
|
|
@ -45,14 +45,19 @@ func TestVMessWebscoketSelf(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestVMessQUICSelf(t *testing.T) {
|
||||
testVMessWebscoketSelf(t, &option.V2RayTransportOptions{
|
||||
Type: C.V2RayTransportTypeQUIC,
|
||||
})
|
||||
}
|
||||
|
||||
func testVMessWebscoketSelf(t *testing.T, transport *option.V2RayTransportOptions) {
|
||||
user, err := uuid.DefaultGenerator.NewV4()
|
||||
require.NoError(t, err)
|
||||
_, certPem, keyPem := createSelfSignedCertificate(t, "example.org")
|
||||
startInstance(t, option.Options{
|
||||
Log: &option.LogOptions{
|
||||
Level: "error",
|
||||
Output: "stderr",
|
||||
Level: "error",
|
||||
},
|
||||
Inbounds: []option.Inbound{
|
||||
{
|
||||
|
@ -122,5 +127,5 @@ func testVMessWebscoketSelf(t *testing.T, transport *option.V2RayTransportOption
|
|||
},
|
||||
},
|
||||
})
|
||||
testSuit(t, clientPort, testPort)
|
||||
testSuitQUIC(t, clientPort, testPort)
|
||||
}
|
||||
|
|
|
@ -34,9 +34,18 @@ func (c *PacketConnWrapper) Upstream() any {
|
|||
}
|
||||
|
||||
type StreamWrapper struct {
|
||||
Conn quic.Connection
|
||||
quic.Stream
|
||||
}
|
||||
|
||||
func (s *StreamWrapper) LocalAddr() net.Addr {
|
||||
return s.Conn.LocalAddr()
|
||||
}
|
||||
|
||||
func (s *StreamWrapper) RemoteAddr() net.Addr {
|
||||
return s.Conn.RemoteAddr()
|
||||
}
|
||||
|
||||
func (s *StreamWrapper) Upstream() any {
|
||||
return s.Stream
|
||||
}
|
||||
|
|
23
transport/v2ray/quic.go
Normal file
23
transport/v2ray/quic.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
//go:build with_quic
|
||||
|
||||
package v2ray
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing-box/transport/v2rayquic"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
)
|
||||
|
||||
func NewQUICServer(ctx context.Context, options option.V2RayQUICOptions, tlsConfig *tls.Config, handler N.TCPConnectionHandler, errorHandler E.Handler) (adapter.V2RayServerTransport, error) {
|
||||
return v2rayquic.NewServer(ctx, options, tlsConfig, handler, errorHandler), nil
|
||||
}
|
||||
|
||||
func NewQUICClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, options option.V2RayQUICOptions, tlsConfig *tls.Config) (adapter.V2RayClientTransport, error) {
|
||||
return v2rayquic.NewClient(ctx, dialer, serverAddr, options, tlsConfig), nil
|
||||
}
|
23
transport/v2ray/quic_stub.go
Normal file
23
transport/v2ray/quic_stub.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
//go:build !with_quic
|
||||
|
||||
package v2ray
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
)
|
||||
|
||||
func NewQUICServer(ctx context.Context, options option.V2RayQUICOptions, tlsConfig *tls.Config, handler N.TCPConnectionHandler, errorHandler E.Handler) (adapter.V2RayServerTransport, error) {
|
||||
return nil, C.ErrQUICNotIncluded
|
||||
}
|
||||
|
||||
func NewQUICClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, options option.V2RayQUICOptions, tlsConfig *tls.Config) (adapter.V2RayClientTransport, error) {
|
||||
return nil, C.ErrQUICNotIncluded
|
||||
}
|
|
@ -22,6 +22,8 @@ func NewServerTransport(ctx context.Context, options option.V2RayTransportOption
|
|||
return NewGRPCServer(ctx, options.GRPCOptions, tlsConfig, handler)
|
||||
case C.V2RayTransportTypeWebsocket:
|
||||
return v2raywebsocket.NewServer(ctx, options.WebsocketOptions, tlsConfig, handler, errorHandler), nil
|
||||
case C.V2RayTransportTypeQUIC:
|
||||
return NewQUICServer(ctx, options.QUICOptions, tlsConfig, handler, errorHandler)
|
||||
default:
|
||||
return nil, E.New("unknown transport type: " + options.Type)
|
||||
}
|
||||
|
@ -36,6 +38,8 @@ func NewClientTransport(ctx context.Context, dialer N.Dialer, serverAddr M.Socks
|
|||
return NewGRPCClient(ctx, dialer, serverAddr, options.GRPCOptions, tlsConfig)
|
||||
case C.V2RayTransportTypeWebsocket:
|
||||
return v2raywebsocket.NewClient(ctx, dialer, serverAddr, options.WebsocketOptions, tlsConfig), nil
|
||||
case C.V2RayTransportTypeQUIC:
|
||||
return NewQUICClient(ctx, dialer, serverAddr, options.QUICOptions, tlsConfig)
|
||||
default:
|
||||
return nil, E.New("unknown transport type: " + options.Type)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
|
@ -44,10 +45,18 @@ func (s *Server) Tun(server GunService_TunServer) error {
|
|||
func (s *Server) mustEmbedUnimplementedGunServiceServer() {
|
||||
}
|
||||
|
||||
func (s *Server) Network() []string {
|
||||
return []string{N.NetworkTCP}
|
||||
}
|
||||
|
||||
func (s *Server) Serve(listener net.Listener) error {
|
||||
return s.server.Serve(listener)
|
||||
}
|
||||
|
||||
func (s *Server) ServePacket(listener net.PacketConn) error {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
|
||||
func (s *Server) Close() error {
|
||||
s.server.Stop()
|
||||
return nil
|
||||
|
|
92
transport/v2rayquic/client.go
Normal file
92
transport/v2rayquic/client.go
Normal file
|
@ -0,0 +1,92 @@
|
|||
package v2rayquic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/sagernet/quic-go"
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing-box/transport/hysteria"
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
)
|
||||
|
||||
var _ adapter.V2RayClientTransport = (*Client)(nil)
|
||||
|
||||
type Client struct {
|
||||
ctx context.Context
|
||||
dialer N.Dialer
|
||||
serverAddr M.Socksaddr
|
||||
tlsConfig *tls.Config
|
||||
quicConfig *quic.Config
|
||||
conn quic.Connection
|
||||
connAccess sync.Mutex
|
||||
}
|
||||
|
||||
func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, options option.V2RayQUICOptions, tlsConfig *tls.Config) adapter.V2RayClientTransport {
|
||||
quicConfig := &quic.Config{
|
||||
DisablePathMTUDiscovery: !C.IsLinux && !C.IsWindows,
|
||||
}
|
||||
if len(tlsConfig.NextProtos) == 0 {
|
||||
tlsConfig.NextProtos = []string{"h2", "http/1.1"}
|
||||
}
|
||||
return &Client{
|
||||
ctx: ctx,
|
||||
dialer: dialer,
|
||||
serverAddr: serverAddr,
|
||||
tlsConfig: tlsConfig,
|
||||
quicConfig: quicConfig,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) offer() (quic.Connection, error) {
|
||||
conn := c.conn
|
||||
if conn != nil && !common.Done(conn.Context()) {
|
||||
return conn, nil
|
||||
}
|
||||
c.connAccess.Lock()
|
||||
defer c.connAccess.Unlock()
|
||||
conn = c.conn
|
||||
if conn != nil && !common.Done(conn.Context()) {
|
||||
return conn, nil
|
||||
}
|
||||
conn, err := c.offerNew()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.conn = conn
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func (c *Client) offerNew() (quic.Connection, error) {
|
||||
udpConn, err := c.dialer.DialContext(c.ctx, "udp", c.serverAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var packetConn net.PacketConn
|
||||
packetConn = bufio.NewUnbindPacketConn(udpConn)
|
||||
quicConn, err := quic.Dial(packetConn, udpConn.RemoteAddr(), c.serverAddr.AddrString(), c.tlsConfig, c.quicConfig)
|
||||
if err != nil {
|
||||
packetConn.Close()
|
||||
return nil, err
|
||||
}
|
||||
return quicConn, nil
|
||||
}
|
||||
|
||||
func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
|
||||
conn, err := c.offer()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stream, err := conn.OpenStream()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &hysteria.StreamWrapper{Conn: conn, Stream: stream}, nil
|
||||
}
|
95
transport/v2rayquic/server.go
Normal file
95
transport/v2rayquic/server.go
Normal file
|
@ -0,0 +1,95 @@
|
|||
package v2rayquic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/sagernet/quic-go"
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing-box/transport/hysteria"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
)
|
||||
|
||||
var _ adapter.V2RayServerTransport = (*Server)(nil)
|
||||
|
||||
type Server struct {
|
||||
ctx context.Context
|
||||
tlsConfig *tls.Config
|
||||
quicConfig *quic.Config
|
||||
handler N.TCPConnectionHandler
|
||||
errorHandler E.Handler
|
||||
udpListener net.PacketConn
|
||||
quicListener quic.Listener
|
||||
}
|
||||
|
||||
func NewServer(ctx context.Context, options option.V2RayQUICOptions, tlsConfig *tls.Config, handler N.TCPConnectionHandler, errorHandler E.Handler) *Server {
|
||||
quicConfig := &quic.Config{
|
||||
DisablePathMTUDiscovery: !C.IsLinux && !C.IsWindows,
|
||||
}
|
||||
if len(tlsConfig.NextProtos) == 0 {
|
||||
tlsConfig.NextProtos = []string{"h2", "http/1.1"}
|
||||
}
|
||||
server := &Server{
|
||||
ctx: ctx,
|
||||
tlsConfig: tlsConfig,
|
||||
quicConfig: quicConfig,
|
||||
handler: handler,
|
||||
errorHandler: errorHandler,
|
||||
}
|
||||
return server
|
||||
}
|
||||
|
||||
func (s *Server) Network() []string {
|
||||
return []string{N.NetworkUDP}
|
||||
}
|
||||
|
||||
func (s *Server) Serve(listener net.Listener) error {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
|
||||
func (s *Server) ServePacket(listener net.PacketConn) error {
|
||||
quicListener, err := quic.Listen(listener, s.tlsConfig, s.quicConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.udpListener = listener
|
||||
s.quicListener = quicListener
|
||||
go s.acceptLoop()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) acceptLoop() {
|
||||
for {
|
||||
conn, err := s.quicListener.Accept(s.ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
hErr := s.streamAcceptLoop(conn)
|
||||
if hErr != nil {
|
||||
s.errorHandler.NewError(conn.Context(), hErr)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) streamAcceptLoop(conn quic.Connection) error {
|
||||
for {
|
||||
stream, err := conn.AcceptStream(s.ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go s.handler.NewConnection(conn.Context(), &hysteria.StreamWrapper{Conn: conn, Stream: stream}, M.Metadata{})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) Close() error {
|
||||
return common.Close(s.udpListener, s.quicListener)
|
||||
}
|
|
@ -7,6 +7,7 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"net/netip"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
|
@ -125,6 +126,10 @@ func (s *Server) badRequest(request *http.Request, err error) {
|
|||
s.errorHandler.NewError(request.Context(), E.Cause(err, "process connection from ", request.RemoteAddr))
|
||||
}
|
||||
|
||||
func (s *Server) Network() []string {
|
||||
return []string{N.NetworkTCP}
|
||||
}
|
||||
|
||||
func (s *Server) Serve(listener net.Listener) error {
|
||||
if s.httpServer.TLSConfig == nil {
|
||||
return s.httpServer.Serve(listener)
|
||||
|
@ -133,6 +138,10 @@ func (s *Server) Serve(listener net.Listener) error {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *Server) ServePacket(listener net.PacketConn) error {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
|
||||
func (s *Server) Close() error {
|
||||
return common.Close(s.httpServer)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue